Pas à pas sur la théorie, l'implémentation en python et l'analyse à l'aide de scikit-learn sur l'algorithme précédemment repris dans "Classification of Machine Learning" J'étudierai avec. Je l'écris pour un apprentissage personnel, alors j'aimerais que vous oubliez toute erreur.
A partir de ce moment, je commencerai sur le problème de classification. Tout d'abord, du Perceptron de base.
Les sites suivants ont été mentionnés cette fois. Merci beaucoup.
La classification à deux classes fait référence à la sortie de "1" ou "0" (ou "1" ou "-1") pour une entrée. Au lieu de "peut se décomposer avec 60% de chances", mettez en noir et blanc pour voir si ça tombe en panne. Il existe différents types de classification à deux classes et ** Perceptron ** est la machine de classification la plus élémentaire.
Perceptron est un modèle inspiré des cellules nerveuses, et lorsqu'un grand nombre d'entrées sont pondérées ensemble et qu'un certain seuil est dépassé, 1 est émis. C'est cette image que vous voyez souvent lorsqu'elle est illustrée.
n entrées $ \ boldsymbol {x} = (x_0, x_1, \ cdots, x_ {n}) $, poids $ \ boldsymbol {w} = (w_0, w_1, \ cdots, w_ {n}) $ Et ajoutez tout ensemble,
w_0x_0+w_1x_1+\cdots+w_{n}x_{n} \\\
=\sum_{i=0}^{n}w_ix_i \\\
= \boldsymbol{w}^T\boldsymbol{x}
Il est exprimé comme. T est la matrice de translocation. Et si cette valeur est positive, elle sort 1, et si elle est négative, elle sort -1. Une fonction qui indique une telle valeur de -1 ou 1 est appelée une fonction d'étape.
La valeur initiale non pertinente pour l'entrée est appelée ** terme de biais **, mais si le terme de biais est $ w_0 $ et $ x_0 = 1 $, la formule ci-dessus peut être utilisée telle quelle.
Puisque python peut calculer le produit des matrices avec "@", si l'entrée est une entrée dans Perceptron et la sortie est sortie
import numpy as np
w = np.array([1.,-2.,3.,-4.])
x = np.array([1.,2.,3.,4.])
input = w.T @ x
output = 1 if input>=0 else -1
C'est facile.
Perceptron est ce qu'on appelle «l'apprentissage supervisé». Pour le $ \ boldsymbol {x} $ donné, s'il y a une étiquette correcte $ \ boldsymbol {t} = (t_0, t_1, \ cdots, t_n) $, alors $ \ boldsymbol {w} ^ T \ boldsymbol {x Vous devez trouver $ \ boldsymbol {w} $ pour que} $ renvoie correctement l'étiquette correcte.
Cela doit être appris en utilisant les données de l'enseignant comme dans le cas de la régression. Pour Perceptron, la même approche de détermination de la fonction de perte et de mise à jour du paramètre $ \ boldsymbol {w} $ pour minimiser la perte est efficace.
Alors, quel type de fonction de perte devrions-nous définir? L'idée est que si la réponse est correcte, il n'y a pas de perte, et si la réponse est incorrecte, la perte est donnée en fonction de la distance de la frontière en fonction de la limite qui classe les deux classes.
La fonction charnière est souvent utilisée pour répondre à de telles demandes. Il semble que le perceptron de scikit-learn utilise également la fonction charnière. Pour les fonctions de charnière,
Comme vous pouvez le voir ici, c'est une fonction qui augmente à partir d'une certaine valeur, et si c'est $$ h (x)
Pour la fonction de perte, si l'étiquette correcte $ t_n $ pour chaque élément et la valeur prédite $ step (w_nx_n) $ sont identiques, $ t_nw_nx_n $ indique une valeur positive, et si elles sont différentes, c'est une valeur négative. Plus la fonction de perte est petite, mieux c'est, donc si la fonction de perte est $ L
Différenciation partielle de $ L $ par rapport à $ w_n $
\frac{\partial L}{\partial w_n}=-t_nx_n
L'expression graduelle qui met à jour $ w_n $ est donc
w_{i+1}=w_{i}+\eta t_nx_n
Peut être écrit. De plus, $ \ eta $ est le taux d'apprentissage.
Je vais réellement l'implémenter avec python. Les données utilisées sont la classification familière scikit-learn to iris. Voir ci-dessous pour une description détaillée de l'ensemble de données.
Tout d'abord, puisqu'il s'agit d'une classification à deux classes, nous nous spécialiserons dans ce domaine. Peu importe les données que vous utilisez, mais elles sont arbitraires et préjugées, et les étiquettes sont «versicolor» et «virginica». "Longueur de sépale (cm)" et "largeur de pétale (cm)" ont été sélectionnés pour la quantité de caractéristiques.
Tout d'abord, visualisez les données.
mport numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
iris = load_iris()
df_iris = pd.DataFrame(iris.data, columns=iris.feature_names)
df_iris['target'] = iris.target_names[iris.target]
fig, ax = plt.subplots()
x1 = df_iris[df_iris['target']=='versicolor'].iloc[:,3].values
y1 = df_iris[df_iris['target']=='versicolor'].iloc[:,0].values
x2 = df_iris[df_iris['target']=='virginica'].iloc[:,3].values
y2 = df_iris[df_iris['target']=='virginica'].iloc[:,0].values
ax.scatter(x1, y1, color='red', marker='o', label='versicolor')
ax.scatter(x2, y2, color='blue', marker='s', label='virginica')
ax.set_xlabel("petal width (cm)")
ax.set_ylabel("sepal length (cm)")
ax.legend()
plt.plot()
Il semble qu'il puisse être classé d'une manière ou d'une autre (on dit aussi que de telles données ont été sélectionnées).
Implémentez la classe Perceptron. Un terme de biais est ajouté intentionnellement.
class Perceptron:
def __init__(self, eta=0.1, n_iter=1000):
self.eta=eta
self.n_iter=n_iter
self.w = np.array([])
def fit(self, x, y):
self.w = np.ones(len(x[0])+1)
x = np.hstack([np.ones((len(x),1)), x])
for _ in range(self.n_iter):
for i in range(len(x)):
loss = np.max([0, -y[i] * self.w.T @ x[i]])
if (loss!=0):
self.w += self.eta * y[i] * x[i]
def predict(self, x):
x = np.hstack([1., x])
return 1 if self.w.T @ x>=0 else -1
@property
def w_(self):
return self.w
La fonction de perte de charnière est calculée pour chaque donnée, et si la réponse est incorrecte, le poids est mis à jour par la méthode du gradient le plus raide. Le calcul est arrêté lorsque le nombre de mises à jour atteint le nombre spécifié, mais cela peut être arrêté lorsque l'erreur tombe en dessous d'une certaine valeur.
Après avoir mis les données dans la classe précédente et les avoir entraînées, dessinons une limite.
df = df_iris[df_iris['target']!='setosa']
df = df.drop(df.columns[[1,2]], axis=1)
df['target'] = df['target'].map({'versicolor':1, 'virginica':-1})
x = df.iloc[:,0:2].values
y = df['target'].values
model = Perceptron()
model.fit(x, y)
#Dessiner un graphique
fig, ax = plt.subplots()
x1 = df_iris[df_iris['target']=='versicolor'].iloc[:,3].values
y1 = df_iris[df_iris['target']=='versicolor'].iloc[:,0].values
x2 = df_iris[df_iris['target']=='virginica'].iloc[:,3].values
y2 = df_iris[df_iris['target']=='virginica'].iloc[:,0].values
ax.scatter(x1, y1, color='red', marker='o', label='versicolor')
ax.scatter(x2, y2, color='blue', marker='s', label='virginica')
ax.set_xlabel("petal width (cm)")
ax.set_ylabel("sepal length (cm)")
#Tracer des limites de classification
w = model.w_
x_fig = np.linspace(1.,2.5,100)
y_fig = [-w[2]/w[1]*xi-w[0]/w[1] for xi in x_fig]
ax.plot(x_fig, y_fig)
ax.set_ylim(4.8,8.2)
ax.legend()
plt.show()
Il semble que la virginica puisse être classée correctement, mais le visicolor ne peut pas être classé. Est-ce une telle chose?
df = df_iris[df_iris['target']!='setosa']
df = df.drop(df.columns[[1,2]], axis=1)
df['target'] = df['target'].map({'versicolor':1, 'virginica':-1})
x = df.iloc[:,0:2].values
y = df['target'].values
from sklearn.linear_model import Perceptron
model = Perceptron(max_iter=40, eta0=0.1)
model.fit(x,y)
#La partie graphique est omise
Eh bien, le versicolor peut être classé de la manière opposée. La fonction de perte peut être un peu différente, mais je ne l'ai pas vérifiée.
J'ai pensé à Perceptron, qui est la base du classificateur. Le Deep Learning étant un modèle qui combine un grand nombre de Perceptrons, la compréhension des Perceptrons deviendra plus importante.
Recommended Posts