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.
Cette fois à propos de ** Retour logistique **. La régression logistique est également un algorithme qui gère la classification binaire comme Perceptron, bien qu'il soit écrit sous forme de régression.
Les sites suivants ont été mentionnés cette fois. Merci beaucoup.
Concernant la théorie de la régression logistique, dérivons d'abord la fonction d'activation ** fonction sigmoïde **.
Puisque la régression logistique est une classification binaire, considérons les classes $ C_1 $ et $ C_2 $. La somme de la probabilité $ C_1 $ $ P (C_1) $ et de la probabilité $ C_2 $ $ P (C_2) $ est 1.
La probabilité de devenir $ C_1 $ lorsque la chaîne de données $ \ boldsymbol {x} $ est donnée provient du ** théorème de Bayes **.
\begin{align}
P(C_1|\boldsymbol{x})&=\frac{P(\boldsymbol{x}|C_1)P(C_1)}{P(\boldsymbol{x})} \\
&= \frac{P(\boldsymbol{x}|C_1)P(C_1)}{P(\boldsymbol{x}|C_1)P(C_1)+P(\boldsymbol{x}|C_2)P(C_2)} \\
&= \frac{1}{1+\frac{P(\boldsymbol{x}|C_2)P(C_2)}{P(\boldsymbol{x}|C_1)P(C_1)}} \\
&= \frac{1}{1+\exp(-\ln\frac{P(\boldsymbol{x}|C_1)P(C_1)}{P(\boldsymbol{x}|C_2)P(C_2)})} \\
&= \frac{1}{1+\exp(-a)} = \sigma(a)
\end{align}
Cette $ \ sigma (a) $ est appelée ** fonction sigmoïde **. La fonction sigmoïde prend une valeur de 0 à 1 comme indiqué ci-dessous, c'est donc une fonction pratique pour exprimer la probabilité.
En utilisant la chaîne de données donnée $ \ boldsymbol {x} = (x_0, x_1, \ cdots, x_n) $ et la classification de l'enseignant $ \ boldsymbol {t} = (t_0, t_1, \ cdots, t_n) $
L(\boldsymbol{x})=\frac{1}{1+\exp(-\boldsymbol{w}^T\boldsymbol{x})}
Nous optimiserons le paramètre $ \ boldsymbol {w} = (w_0, w_1, \ cdots, w_n) $ of.
y a-t-il
Appliquer ceci à toutes les données
\begin{align}
P(\boldsymbol{t}|\boldsymbol{x})&=P(t_0|x_0)P(t_1|X_1)\cdots P(t_{n-1}|x_{n-1}) \\
&=\prod_{i=0}^{n-1}P(t_i|x_i) \\
&=\prod_{i=1}^{n-1}p_i^{t_i}(1-p_i)^{1-t_i}
\end{align}
Ce sera. Prenant le logarithme des deux côtés,
\log P(\boldsymbol{t}|\boldsymbol{x}) = \sum_{i=0}^{n-1}\{t_i\log p_i+(1-t_i)\log (1-p_i)\}
Ceci est appelé ** vraisemblance log **, avec le signe inversé pour maximiser la vraisemblance log.
E(\boldsymbol{x}) = -\frac{1}{n}\log P(\boldsymbol{t}|\boldsymbol{x}) = \frac{1}{n}\sum_{i=0}^{n-1}\{-t_i\log p_i-(1-t_i)\log (1-p_i)\}
Ce $ E $ est appelé la ** fonction d'erreur d'entropie croisée **. La différenciation de $ E $ sera utilisée plus tard.
\frac{\partial{E}}{\partial{w_i}}=\frac{1}{n}\sum_{i=0}^{n-1}(p_i-t_i)x_i
(Explication omise)
Maintenant, pour minimiser la fonction d'erreur d'entropie croisée, nous utilisons la méthode de gradient qui a été présentée auparavant. Encore une fois, vous pouvez utiliser la méthode de descente la plus raide ou la méthode de descente de gradient probabiliste, mais utilisez la ** méthode du gradient conjugué **. Pour plus d'informations, voir [Wikipedia: Conjugated Gradient Method](https://ja.wikipedia.org/wiki/%E5%85%B1%E5%BD%B9%E5%8B%BE%E9%85%8D%E6% Je vais le donner à B3% 95), mais c'est un algorithme qui est plus rapide que la méthode du gradient le plus raide et qui converge sans fixer le taux d'apprentissage. Je veux également implémenter cela avec python, mais c'est gênant (!) Scipy.optimize.fmin_cg de python Nous utilisons une bibliothèque appelée .fmin_cg.html).
Nous allons implémenter la classe LogisticRegression en utilisant la théorie jusqu'à présent. fmin_cg utilise la fonction de gradient mentionnée précédemment car elle donne de bons résultats lorsqu'on lui donne une fonction de gradient.
from scipy import optimize
class LogisticRegression:
def __init__(self):
self.w = np.array([])
def sigmoid(self, a):
return 1.0 / (1 + np.exp(-a))
def cross_entropy_loss(self, w, *args):
def safe_log(x, minval=0.0000000001):
return np.log(x.clip(min=minval))
t, x = args
loss = 0
for i in range(len(t)):
ti = (t[i]+1)/2
h = self.sigmoid(w.T @ x[i])
loss += -ti*safe_log(h) - (1-ti)*safe_log(1-h)
return loss/len(t)
def grad_cross_entropy_loss(self, w, *args):
t, x = args
grad = np.zeros_like(w)
for i in range(len(t)):
ti = (t[i]+1)/2
h = self.sigmoid(w.T @ x[i])
grad += (h - ti) * x[i]
return grad/len(t)
def fit(self, x, y):
w0 = np.ones(len(x[0])+1)
x = np.hstack([np.ones((len(x),1)), x])
self.w = optimize.fmin_cg(self.cross_entropy_loss, w0, fprime=self.grad_cross_entropy_loss, args=(y, x))
@property
def w_(self):
return self.w
Utilisons cette classe pour classer les données d'iris. Dessinez également la frontière. La limite est une ligne de $ \ boldsymbol {w} ^ T \ boldsymbol {x} = 0 $. J'ai changé les 2 classes en 1 et -1, donc j'ai créé le code pour le faire correspondre.
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})
#Dessiner un graphique
fig, ax = plt.subplots()
df_versicolor = df_iris[df_iris['target']=='versicolor']
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
xs = StandardScaler()
ys = StandardScaler()
xs.fit(np.append(x1,x2).reshape(-1, 1))
ys.fit(np.append(y1,y2).reshape(-1, 1))
x1s = xs.transform(x1.reshape(-1, 1))
x2s = xs.transform(x2.reshape(-1, 1))
y1s = ys.transform(y1.reshape(-1, 1))
y2s = ys.transform(y2.reshape(-1, 1))
x = np.concatenate([np.concatenate([x1s, y1s], axis=1), np.concatenate([x2s, y2s], axis=1)])
y = df['target'].values
model = LogisticRegression()
model.fit(x, y)
ax.scatter(x1s, y1s, color='red', marker='o', label='versicolor')
ax.scatter(x2s, y2s, 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(-2.,2.,100)
y_fig = [-w[1]/w[2]*xi-w[0]/w[2] for xi in x_fig]
ax.plot(x_fig, y_fig)
ax.set_ylim(-2.5,2.5)
ax.legend()
print(w)
plt.show()
Optimization terminated successfully.
Current function value: 0.166434
Iterations: 12
Function evaluations: 41
Gradient evaluations: 41
[-0.57247091 -5.42865492 -0.20202263]
Il semble qu'ils peuvent être classés assez clairement.
scikit-learn a également une classe LogisticRegression, donc c'est presque le même que le code ci-dessus.
from sklearn.linear_model import LogisticRegression
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})
#Dessiner un graphique
fig, ax = plt.subplots()
df_versicolor = df_iris[df_iris['target']=='versicolor']
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
xs = StandardScaler()
ys = StandardScaler()
xs.fit(np.append(x1,x2).reshape(-1, 1))
ys.fit(np.append(y1,y2).reshape(-1, 1))
x1s = xs.transform(x1.reshape(-1, 1))
x2s = xs.transform(x2.reshape(-1, 1))
y1s = ys.transform(y1.reshape(-1, 1))
y2s = ys.transform(y2.reshape(-1, 1))
x = np.concatenate([np.concatenate([x1s, y1s], axis=1), np.concatenate([x2s, y2s], axis=1)])
y = df['target'].values
model = LogisticRegression(C=100)
model.fit(x, y)
ax.scatter(x1s, y1s, color='red', marker='o', label='versicolor')
ax.scatter(x2s, y2s, 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.coef_[0]
x_fig = np.linspace(-2.,2.,100)
y_fig = [-w[0]/w[1]*xi-model.intercept_/w[1] for xi in x_fig]
ax.plot(x_fig, y_fig)
ax.set_ylim(-2.5,2.5)
ax.legend()
plt.show()
Ceci est également classé comme bon.
Ceci est un résumé de la régression logistique, qui est relativement importante dans le monde de l'apprentissage automatique. La théorie est devenue plus difficile à partir d'ici.
Recommended Posts