[PYTHON] Algorithme d'apprentissage automatique (résumé de régression linéaire et régularisation)

introduction

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, en résumé de l'édition de régression linéaire, je résumerai l'approximation linéaire en utilisant le noyau gaussien, et les régularisations L1 (Lasso) et L2 (Ridge) qui suppriment le surentraînement et lui.

Les sites suivants ont été mentionnés cette fois. Merci beaucoup.

À propos de l'approximation du noyau

Plus tôt, quand j'ai écrit sur Généralisation de la régression linéaire, j'ai écrit que "la fonction de base peut être n'importe quoi". Même dans la régression proprement dite, il n'est pas toujours possible de faire une approximation avec une ligne droite, et il est également nécessaire de faire une approximation telle qu'une fonction polymorphe ou une fonction triangulaire.

Par exemple, considérons $ y = -xsin (x) + \ epsilon $ avec du bruit ajouté à $ y = -xsin (x) $.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

%matplotlib inline

fig, ax = plt.subplots()

t = np.linspace(0, 2*np.pi, 100)
y1 = - t * np.sin(t)

n=40
np.random.seed(seed=2020)
x = 2*np.pi * np.random.rand(n)
y2 = - x * np.sin(x) + 0.4 * np.random.normal(loc=0.0, scale=1.0, size=n)

ax.scatter(x, y2, color='blue', label="sample(with noise)")
ax.plot(t, y1, color='green', label="-x * sin(x)")
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, fontsize=11)

plt.show()
gaussian_regression_1.png

Les points bleus sont des échantillons avec du bruit et les lignes vertes pleines indiquent les fonctions attendues. Le bruit a été ajouté avec des nombres aléatoires, mais la valeur de départ des nombres aléatoires a été fixée de manière à ce que le même résultat soit obtenu à chaque fois.

Cette fois, il est normal de connaître la fonction objectif, mais nous devons estimer à partir de l'état où nous ne savons pas si l'échantillon est un polynôme ou une autre fonction.

À propos du noyau gaussien

Le noyau gaussien est défini comme suit:

k(\boldsymbol{x}, \boldsymbol{x'})=\exp(-\beta||\boldsymbol{x}-\boldsymbol{x'}||^2)

||\boldsymbol{x}-\boldsymbol{x'}||^2Est la distance entre les vecteurs,$\sqrt{\sum_{j=1}^{n}(x_j-x'_j)^2} $Il est également exprimé comme.

Cette fonction a la forme suivante, et en déplaçant ou en modifiant la taille du centre de cette fonction, elle revient à la chaîne de données cible.

ガウスカーネル

Régression linéaire utilisant le noyau gaussien

Maintenant la fonction souhaitée

f({\bf x})=\sum_{i=1}^{N} \alpha k({\bf x}^{(i)}, {\bf x}')

Et. Soit la valeur de l'échantillon $ \ hat {y} $

\hat{y} =
\left(\begin{matrix}
k({\bf x}^{(1)}, {\bf x}) & k({\bf x}^{(2)}, {\bf x}) & \cdots & k({\bf x}^{(N)}, {\bf x})
\end{matrix}\right)
\left(\begin{matrix}
\alpha_0 \\
\alpha_1 \\
\vdots \\
\alpha_N
\end{matrix}\right)

Suivant,

{\bf y} = 
\left(\begin{matrix}
y^{(1)} \\
y^{(2)} \\
\vdots \\
y^{(N)}
\end{matrix}\right)
,\;
K=\left(\begin{matrix}
k({\bf x}^{(1)}, {\bf x}^{(1)}) & k({\bf x}^{(2)}, {\bf x}^{(1)}) & \cdots & k({\bf x}^{(N)}, {\bf x}^{(1)}) \\
k({\bf x}^{(1)}, {\bf x}^{(2)}) & k({\bf x}^{(2)}, {\bf x}^{(2)}) & & \vdots \\
\vdots & & \ddots & \vdots \\
k({\bf x}^{(1)}, {\bf x}^{(N)}) & \cdots & \cdots & k({\bf x}^{(N)}, {\bf x}^{(N)})
\end{matrix}\right) 
,\;
{\bf \alpha}
=
\left(\begin{matrix}
\alpha^{(1)} \\
\alpha^{(2)} \\
\vdots \\
\alpha^{(N)}
\end{matrix}\right)

Il sera développé comme ça (je suis désolé pour cette étrange copie). Ici, $ K $ est appelé ** matrice gramme **. L'erreur carrée $ L $ entre $ f ({\ bf x}) $ et $ \ hat {y} $ est

L=({\bf y}- K {\bf \alpha})^{\mathrm{T}}({\bf y}- K {\bf \alpha})

Et en résolvant ceci pour $$ alpha , $ {\ bf \ alpha} = (K ^ {\ mathrm {T}} K) ^ {-1} K ^ {\ mathrm {T}} {\ bf y} = K ^ {-1} {\ bf y} $$. En d'autres termes, si la matrice inverse de la matrice gramme peut être calculée, il est possible d'obtenir $ \ alpha $. Si le nombre d'échantillons observés est trop grand, il sera difficile d'obtenir cette matrice inverse, donc une autre méthode doit être choisie.

Implémentation en python

J'ai implémenté la classe KernelRegression en utilisant la formule ci-dessus telle quelle.

class KernelRegression: #Pas de régularisation
  def __init__(self, beta=1):
    self.alpha = np.array([])
    self.beta = beta

  def _kernel(self, xi, xj):
    return np.exp(- self.beta * np.sum((xi - xj)**2))

  def gram_matrix(self, X):
    N = X.shape[0]
    K = np.zeros((N, N))
    for i in range(N):
      for j in range(N):
        K[i][j] = self._kernel(X[i], X[j])
        K[j][i] = K[i][j]

    return K

  def fit(self, X, Y):
    K = self.gram_matrix(X)
    self.alpha = np.linalg.inv(K)@Y

  def predict(self, X, x):
    Y = 0
    for i in range(len(X)):
      Y += self.alpha[i] * self._kernel(X[i], x)
    return Y

Faisons une approximation en utilisant le premier échantillon.

model = KernelRegression(beta=20)
model.fit(x, y2)

xp = np.linspace(0, 2*np.pi, 100)
yp = np.zeros(len(xp))

for i in range(len(xp)):
  yp[i] = model.predict(x, xp[i])


fig, ax = plt.subplots()

plt.ylim(-3,6)
ax.plot(xp, yp, color='purple', label="estimate curve")
ax.scatter(x, y2, color='blue', label="sample(with noise)")
ax.plot(t, y1, color='green', label="-x*sin(x)")
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, fontsize=11)

plt.show()
gaussian_regression_2.png

Il semble qu'il passe sur l'échantillon donné, mais c'est compliqué. C'est complètement différent de la courbe verte.

À propos du surajustement

Comme indiqué ci-dessus, le fait que le résultat d'apprentissage soit fidèle aux données de l'enseignant mais éloigné de la réalité est appelé ** surapprentissage **. Est-ce similaire à un test de mathématiques que vous pouvez résoudre si vous rencontrez le même problème qu'un manuel, mais que vous ne pouvez pas le résoudre dès que vous le arrangez un peu?

Les modèles surentraînés sont également qualifiés de médiocres ** performances de généralisation **. La précision de la prédiction est faible. Pour éviter cela, nous avons besoin du concept de ** régularisation **.

Régularisation

Dans l'exemple ci-dessus, le paramètre $ \ bf {\ alpha} $ est devenu extrêmement grand, résultant en une courbe violemment violente pour forcer les points d'un échantillon donné à passer. Après cela, il semble que cela se produise souvent lorsque le nombre de données est extrêmement petit ou qu'il y a de nombreuses variables.

Pour éviter cela, lors du calcul de $ \ alpha $, cela peut être réalisé en limitant la plage de $ \ alpha $ en ajoutant ** terme de régularisation ** à l'erreur carrée de la régression du noyau. La régularisation L1 (Lasso) et la régularisation L2 (Ridge) sont célèbres dans l'apprentissage automatique. Le mélange des deux s'appelle la régularisation Elastic Net.

Régularisation L2

Commencez par L2 au lieu de L1. Plus tôt\alphaL'erreur quadratique entre la fonction objectif et l'échantillon lorsqueLJ'ai dit,\lambda||{\bf \alpha}||_2^2Ajoutée

L=({\bf y}- K {\bf \alpha})^{\mathrm{T}}({\bf y}- K {\bf \alpha})+\lambda||{\bf \alpha}||_2^2

Optimiser. Le plus grand $ \ lambda $, le plus restreint $ \ alpha $, résultant en une courbe plus douce (?). Si cela est partiellement différencié par $ \ alpha $ et mis à 0, et résolu pour $ \ alpha $,

{\bf \alpha} = (K+\lambda I_N)^{-1}{\bf y}

Ce sera. Ceci est facile à changer car tout ce que vous avez à faire est d'ajouter la matrice unitaire à la matrice gramme et de calculer la matrice inverse.

Implémentation en python

J'ai changé la partie de la classe KernelRegression qui demande $ \ alpha $. Le reste est presque le même.

class KernelRegression: #Régularisation L2
  def __init__(self, beta=1, lam=0.5):
    self.alpha = np.array([])
    self.beta = beta
    self.lam = lam

  def _kernel(self, xi, xj):
    return np.exp(- self.beta * np.sum((xi - xj)**2))

  def gram_matrix(self, X):
    N = X.shape[0]
    K = np.zeros((N, N))
    for i in range(N):
      for j in range(N):
        K[i][j] = self._kernel(X[i], X[j])
        K[j][i] = K[i][j]

    return K

  def fit(self, X, Y):
    K = self.gram_matrix(X)
    self.alpha = np.linalg.inv(K + self.lam * np.eye(X.shape[0]))@Y

  def predict(self, X, x):
    Y = 0
    for i in range(len(X)):
      Y += self.alpha[i] * self._kernel(X[i], x)
    return Y

Essayez de faire une approximation en utilisant le même échantillon que s'il n'était pas régularisé. Les valeurs de $ \ beta $ et $ \ lambda $ ont été décidées de manière appropriée.

model = KernelRegression(beta=0.3, lam=0.1)
model.fit(x, y2)

xp = np.linspace(0, 2*np.pi, 100)
yp = np.zeros(len(xp))

for i in range(len(xp)):
  yp[i] = model.predict(x, xp[i])


fig, ax = plt.subplots()

plt.ylim(-3,6)
ax.plot(xp, yp, color='purple', label="estimate curve")
ax.scatter(x, y2, color='blue', label="sample(with noise)")
ax.plot(t, y1, color='green', label="-x*sin(x)")
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, fontsize=11)

plt.show()
gaussian_regression_3.png

Cette fois, c'était un match parfait. En fait, la forme change en dehors de la plage affichée, mais vous pouvez voir qu'une courbe d'approximation assez proche peut être dessinée dans une plage spécifique.

$ \ Beta $ et $ \ lambda $ sont appelés ** hyperparamètres **, et vous devez en fait les optimiser en les changeant petit à petit pour minimiser la valeur de la fonction de perte.

Régularisation L1

En régularisation L2, comme terme de régularisation,$\lambda ||{\bf \alpha}||^2_{2} A été ajouté, mais dans la régularisation L2 comme terme de régularisation\lambda||{\bf \alpha}||_1$Ajouter.

Trouver une solution est un peu compliqué car le terme de régularisation ne peut pas être différencié dans la régularisation L1. Il semble que scikit-learn soit implémenté par une méthode appelée Coordinate Descent, mais je ne la comprends pas encore, alors j'aimerais utiliser scikit-learn docilement dans cet article.

La régularisation L1 permet à une partie significative du paramètre $ \ alpha $ d'être nulle (obtenant une solution clairsemée), ce qui permet de supprimer les paramètres indésirables.

Implémentation en python

Je vais l'implémenter docilement avec scicit-learn.

from sklearn.metrics.pairwise import rbf_kernel
from sklearn.linear_model import Lasso

kx = rbf_kernel(x.reshape(-1,1), x.reshape(-1,1))
KX = rbf_kernel(xp.reshape(-1,1), x.reshape(-1,1))

clf = Lasso(alpha=0.01, max_iter=10000)
clf.fit(kx, y2)

yp = clf.predict(KX)

fig, ax = plt.subplots()
plt.ylim(-3,6)
ax.plot(xp, yp, color='purple', label="estimate curve")
ax.scatter(x, y2, color='blue', label="sample(with noise)")
ax.plot(t, y1, color='green', label="-x*sin(x)")
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, fontsize=11)

plt.show()

print("coef: ", clf.coef_)

coef:  [-0.          0.          0.         -0.         -0.79703436 -0.
 -0.         -0.          0.         -0.         -0.          3.35731837
  0.         -0.         -0.77644607  0.         -0.          0.
 -0.         -0.19590705  0.         -0.          0.         -0.
  0.          0.         -0.         -0.         -0.          0.
 -0.          0.         -0.         -0.          0.          0.58052561
  0.3688375   0.         -0.          1.75380012]
gaussian_regression_4.png

Ceci est également très similaire à la fonction d'origine. Vous pouvez également voir qu'une partie significative du paramètre (coef) est 0.

Elasticnet La régularisation L1 et la régularisation L2 ajoutent un terme de régularisation à la fonction de perte, mais chacune peut être considérée indépendamment et vous pouvez décider laquelle et dans quelle mesure adopter, ce qui s'appelle ** ElasticNet **. Je vais. En fait, l'implémentation scikit-learn a défini les paramètres ElasticNet comme Lasso et Ridge.

Résumé

Toute fonction peut être sélectionnée comme fonction de base dans la régression linéaire. Puisque le noyau gaussien (non limité à) a un degré de liberté élevé et a tendance à être surappris, il est possible de créer un modèle de régression avec des performances de généralisation plus élevées en le limitant par régularisation L1 ou régularisation L2.

J'ai résumé la série de régression plusieurs fois, mais pour vous aider à comprendre le contenu de la régression dans la feuille de triche scikit-learn N'est-ce pas?

Tsukkomi est le bienvenu car je l'ai résumé de manière appropriée.

Recommended Posts

Algorithme d'apprentissage automatique (résumé de régression linéaire et régularisation)
Algorithme d'apprentissage automatique (généralisation de la régression linéaire)
Machine Learning: Supervision - Régression linéaire
Algorithme d'apprentissage automatique (régression logistique)
Les débutants en apprentissage automatique essaient la régression linéaire
Algorithme d'apprentissage automatique (analyse de régression multiple)
Algorithme d'apprentissage automatique (analyse de régression unique)
<Cours> Machine learning Chapitre 1: Modèle de régression linéaire
Résumé de la classification et de la mise en œuvre des algorithmes d'apprentissage automatique
Résumé du didacticiel d'apprentissage automatique
Apprentissage automatique ⑤ Résumé AdaBoost
Régression logistique d'apprentissage automatique
EV3 x Python Machine Learning Partie 2 Régression linéaire
Python Scikit-learn Analyse de régression linéaire Analyse de régression simple non linéaire Apprentissage automatique
Comprendre l'apprentissage automatique ~ régression de crête ~.
Résumé de l'article sur l'apprentissage automatique (auto-écrit)
Coursera Machine Learning Challenge en Python: ex1 (régression linéaire)
Algorithme d'apprentissage automatique (perceptron simple)
Machine learning supervisé (classification / régression)
Algorithme d'apprentissage automatique (machine vectorielle de support)
Apprentissage automatique ④ Résumé du K-plus proche voisin
Modèle d'empilage d'apprentissage automatique (retour)
Programmation Python Machine Learning Chapitre 2 Problèmes de classification - Résumé de la formation à l'algorithme d'apprentissage automatique
<Course> Machine learning Chapitre 6: Algorithme 2 (k-means)
Algorithme d'apprentissage automatique (prise en charge de l'application de machine vectorielle)
Apprentissage automatique ① Résumé SVM (Support Vector Machine)
Apprentissage automatique ③ Résumé de l'arbre de décision
Classification et régression dans l'apprentissage automatique
Algorithme d'apprentissage automatique (méthode de descente de gradient)
Apprentissage automatique: analyse discriminante linéaire supervisée
[Apprentissage automatique] Comprendre la régression linéaire simple à partir de scikit-learn et des mathématiques
Apprentissage automatique
Régression linéaire
[Apprentissage automatique] Comprendre la régression multiple linéaire à partir de scikit-learn et des mathématiques
<Subject> Machine learning Chapitre 3: Modèle de régression logistique
scikit-learn Comment utiliser le résumé (apprentissage automatique)
Apprentissage automatique avec python (2) Analyse de régression simple
Note récapitulative sur la programmation d'apprentissage automatique Python (Jupyter)
Algorithme d'apprentissage automatique (implémentation de la classification multi-classes)
<Cours> Machine learning Chapitre 2: Modèle de régression non linéaire
Prévision du cours des actions à l'aide de l'apprentissage automatique (édition de retour)
[Apprentissage automatique] Analyse de régression à l'aide de scicit learn
(Apprentissage automatique) J'ai essayé de comprendre attentivement la régression linéaire bayésienne avec l'implémentation
Algorithme EM modèle mixte gaussien [apprentissage automatique statistique]
Algorithme d'apprentissage du dictionnaire
Résumé des fonctions d'évaluation utilisées dans l'apprentissage automatique
[Memo] Apprentissage automatique
Classification de l'apprentissage automatique
Exemple d'apprentissage automatique
Résumé des diapositives de la session de lecture ronde de la série professionnelle d'apprentissage automatique
Défis d'apprentissage automatique de Coursera en Python: ex2 (retour logistique)
Résumé du site pour apprendre l'apprentissage automatique avec une vidéo en anglais
Résumé du flux de base de l'apprentissage automatique avec Python
Parlez de l'amélioration du goulot d'étranglement des algorithmes d'apprentissage automatique avec Cython
Apprentissage automatique sur le surapprentissage
Apprentissage automatique: supervisé - AdaBoost
Machine de vecteur de support d'apprentissage automatique
Étudier l'apprentissage automatique ~ matplotlib ~
Mémo du cours d'apprentissage automatique