[PYTHON] Implémentation de la méthode de gradient 1

introduction

Cela fait environ un mois que j'ai réservé ce jour sur le calendrier de l'Avent, et c'est presque Noël. D'une certaine manière, je sens que cette année s'est écoulée plus rapidement que d'habitude. Cette fois, pour ceux qui peuvent écrire Python dans une certaine mesure mais ne savent pas quel type d'implémentation sera concrètement fait par l'apprentissage automatique, je vais m'envoyer cela comme cadeau de Noël de ma part d'une manière facile à comprendre. Puisque la partie théorique et la partie pratique sont mélangées, veuillez ne prendre et ne manger que la partie que vous pouvez comprendre. Peut-être que vous pouvez toujours en avoir une idée. Veuillez également vous référer à ici pour une image intuitive de l'apprentissage automatique dans l'article précédent.

Quelle est la méthode du gradient?

La méthode du gradient est l'une des méthodes utilisées pour l'optimisation. Cette méthode de gradient est souvent utilisée pour trouver le poids $ W $ qui donne la sortie optimale.

Plus précisément, précédent erreur de somme carrée affichée

\frac{1}{N} \sum_{n=1}^{N}\|\|\boldsymbol{y}\_{n}(\boldsymbol{x}\_{n},W)-\boldsymbol{t}_{n} \|\|^{2} \tag{1}

L'une des méthodes à minimiser est la méthode du gradient, qui utilise la différenciation pour trouver la valeur minimale.

Mise en œuvre de la différenciation

Commençons par implémenter une différenciation unidimensionnelle. Fonction de $ x $ Différenciation de $ f (x) $ $ f ^ {\ prime} (x) $ $ f ^ {\ prime} (x) = \ lim_ {h → 0} \ frac {f (x + h) --f (x)} {h} \ tag {2} $. La différenciation signifie la pente de la fonction $ f (x) $ au point $ x $. Par exemple, lorsque la fonction est $ f (x) = x ^ 2 $ $ f ^ {\ prime} (x) = \ lim_ {h → 0} \ frac {(x + h) ^ 2-x ^ 2} {h} = 2x \ tag {3} $. L'implémentation est, par exemple: (Puisque seul le code ci-dessous est écrit pour la destination d'importation principale, ne l'oubliez pas après cela.)

numerical_differentiation.py


import numpy as np
import matplotlib.pylab as plt

def nu_dif(f, x):
	h = 1e-4
	return (f(x + h) - f(x))/(h)

def f(x):
	return x ** 2
	
x = np.arange(0.0, 20.0, 0.1)
y = nu_dif(f, x)

plt.xlabel("x")
plt.ylabel("y")
plt.plot(x,y)
plt.show() 

Le graphique ci-dessous $ y = f \ ^ {\ prime} (x) = 2x $ doit maintenant être tracé. [3382ED86-34E1-4011-BE99-ADE6A8E1E530.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535913/d1b7deeb-6e5f-6070-6bb3-b234e3b27432 .jpeg)

$ h $ vaut environ 10 $ \ ^ {-4} $ pour éviter les erreurs d'arrondi.

prime

Dans le calcul numérique ci-dessus, $$ f ^ {\ prime} (x) = \ lim_ {h → 0} \ frac {f (x + h) --f (x --h)} {2h} \ tag {4} $ Un calcul comme $ améliorera la précision.

def nu_dif(f, x):
	h = 1e-4
	return (f(x + h) - f(x-h))/(2 * h)

Différenciation partielle

Maintenant que nous avons implémenté la différenciation unidimensionnelle, implémentons la différenciation multidimensionnelle. Ici, par souci de simplicité, nous allons différencier en deux dimensions. Pour une fonction à deux variables $ f (x, y) $, la différenciation entre $ x et y $, c'est-à-dire la différenciation partielle $ f_x, f_y , est définie comme suit. $ f_x \ equiv \ frac {\ partial f} {\ partial x} = \ lim_ {h → 0} \ frac {f (x + h, y) --f (x, y)} {h} \ tag { 5} $ $ f_y \ equiv \ frac {\ partial f} {\ partial y} = \ lim_ {h → 0} \ frac {f (x, y + h) --f (x, y)} {h } \ tag {6} $$ Disons que la fonction ici est $ f (x, y) = x ^ 2 + y ^ 2 $. 32CD418B-824A-49C2-A87B-A2271759D8DD.jpeg

Maintenant, implémentons également une différenciation partielle. $ f_x = 2x, f_y = 2y $.

numerical_differentiation_2d.py


def f(x, y):
	return x ** 2 + y ** 2

def nu_dif_x(f, x, y):
	h = 1e-4
	return (f(x + h, y) - f(x - h, y))/(2 * h)
	
def nu_dif_y(f, x, y):
	h = 1e-4
	return (f(x, y + h) - f(x, y - h))/(2 * h)

Pente

L'opérateur de gradient (nabla) pour la fonction à trois variables $ f (x, y, z) $ en coordonnées cartésiennes tridimensionnelles est $ \ nabla f = \ bigg (\ frac {\ partial f} {\ partial x}, \ Il est défini par frac {\ partial f} {\ partial y}, \ frac {\ partial f} {\ partial z} \ bigg) \ tag {7} $. L'application de Nabla $ \ nabla $ à la fonction scalaire donne une quantité vectorielle. Par exemple, lorsque $ f (x, y, z) = x ^ 2 + y ^ 2 + z ^ 2 $, alors $ \ nabla f = (2x, 2y, 2z) $. ** $ - \ nabla f $ pointe sur la valeur minimale de $ f $ (strictement la valeur minimale). ** De plus, Nabla peut généralement être étendu à la dimension $ n $. Illustrer $ - \ nabla f = (-2x, -2y) $ pour $ f (x, y) = x ^ 2 + y ^ 2 $ pour une compréhension intuitive. ![4C8FF21E-D388-4D7B-BB47-C71C02B2052D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535913/90ce4f1a-0c0f-fbe9-a389-a8c5f5d40c06 .jpeg) Vous pouvez voir que le vecteur planaire $ xy $ $ - \ nabla f $ pointe vers l'origine en tout point. Et la valeur à l'origine est $ f (0,0) = 0 $, qui est la valeur minimale de $ f $. La taille de la flèche représente la magnitude de l'inclinaison à ce point.

Implémentation de la méthode du gradient

Je vous remercie pour votre travail acharné. Cela couvre toutes les bases mathématiques nécessaires pour implémenter une méthode de gradient simple. Maintenant, implémentons un programme qui trouve automatiquement la valeur minimale de la fonction. Point arbitraire À partir de $ \ boldsymbol {x} ^ {(0)} $ $$ \ boldsymbol {x} ^ {(k + 1)} = \ boldsymbol {x} ^ {(k)} - \ eta \ nabla Faites glisser vers le bas jusqu'au point $ \ boldsymbol {x} ^ * $ qui donne la valeur minimale selon f \ tag {8} $$. Ici $ \ eta $ est un hyperparamètre que les humains doivent spécifier dans une quantité appelée coefficient d'apprentissage. $ \ eta $ doit être ajusté de manière appropriée pour ne pas être trop grand ou trop petit. Cette fois, je vais omettre l'explication sur le coefficient d'apprentissage.

Maintenant, implémentez la méthode du gradient pour trouver le point $ \ boldsymbol {x} ^ * = (x ^ *, y ^ *) $ qui donne la valeur minimale de $ f (x, y) = x ^ 2 + y ^ 2 $ Faisons le. Comme vous le savez déjà, si vous obtenez $ \ boldsymbol {x} ^ * = (0,0) $, vous réussissez.

numerical_gradient.py


#Renvoie le gradient de f
def numerical_gradient(f, x):
	h = 1e-4
	grad = np.zeros_like(x)
	
	for i in range(x.size):
		tmp = x[i]
		x[i] = tmp + h
		f1 = f(x)
		x[i] = tmp - h
		f2 = f(x)
		grad[i] = (f1 - f2)/(2 * h)
		x[i] = tmp
		
	return grad	

#Méthode de gradient
def gradient_descent(f, x, lr = 0.02, step_num = 200):
	for i in range(step_num):
		grad = numerical_gradient(f, x)
		x -= lr * grad
		
	return x
	
#Définir f
def f(x):
	return x[0] ** 2 + x[1] ** 2

#Sortie x
print(gradient_descent(f, np.array([10.0, 3.0])))

Le résultat de la définition de $ \ boldsymbol {x} ^ {(0)} = (10,3), \ eta = 0,02, k = 0,1, \ ldots, 199 $ [ 0.00284608 0.00085382] Doit être sorti. Puisque $ x et y $ valent à la fois environ 10 $ ^ {-3} $, on peut dire qu'ils valent presque 0 $.

Méthode de gradient dans l'apprentissage automatique

Le contour et l'utilité de la méthode du gradient ont été expliqués ci-dessus. En apprentissage automatique, la clé est de savoir comment trouver le poids optimal $ \ boldsymbol {W} $. Le poids optimal est la fonction de perte $ \ boldsymbol {W} $ qui minimise $ L $. La méthode du gradient peut être utilisée comme l'une des méthodes pour y parvenir. Le poids $ \ boldsymbol {W} $ est, par exemple, une matrice $ 2 \ times2 $

\boldsymbol{W}=\left(\begin{array}{cc}
w_{11} & w_{12} \\
w_{21} & w_{22} 
\end{array}\right) \tag{9}

Pour la fonction de perte $ L $ donnée dans

\nabla L \equiv \frac{\partial L}{\partial \boldsymbol {W}}\equiv\left(\begin{array}{cc}
\frac{\partial L}{\partial w_{11}} & \frac{\partial L}{\partial w_{12}} \\
\frac{\partial L}{\partial w_{21}} & \frac{\partial L}{\partial w_{22}} 
\end{array}\right) \tag{10}

Calculer $ \ boldsymbol {W} ^ {(k + 1)} = \ boldsymbol {W} ^ {(k)} - \ eta \ nabla L \ tag {11} $ En appliquant la méthode du dégradé selon, vous trouverez $ \ boldsymbol {W} $ qui donne la valeur minimale de $ L $. Cependant, dans la plupart des cas, le $ \ boldsymbol {W} $ obtenu ne donne pas une valeur minimale de $ L $. C'est comme devenir accro à un piège avant d'arriver à destination. La surface courbe de $ L $ est souvent bosselée pour divers $ \ boldsymbol {W} $. Pour éviter cela, il existe d'autres moyens un peu plus compliqués. J'écrirai à ce sujet la prochaine fois.

Résumé

Merci d'avoir lu jusqu'ici. Cette fois, j'ai commencé par une simple implémentation différentielle unidimensionnelle utilisant Python et je l'ai étendue à plusieurs dimensions. Ensuite, j'ai présenté l'opérateur de gradient Nabla et appris la méthode de gradient pour trouver la valeur minimale d'une fonction arbitraire qui l'utilisait. Et enfin, je vous ai dit que l'utilisation de la méthode du gradient peut réduire la fonction de perte, c'est-à-dire améliorer la précision de l'apprentissage automatique. Cependant, bien que les poids ainsi obtenus soient souvent extrêmes, nous avons également constaté que le problème est que la fonction de perte n'est pas minimisée, ni optimisée. À partir de la prochaine fois, j'essaierai une autre approche à ce problème.

en conclusion

Cette fois, j'ai eu la chance d'être présenté par un ami et de poster sur ce calendrier de l'Avent de l'Université de Chiba 2019. C'était un peu difficile parce que je l'ai résumé à partir d'une partie assez rudimentaire, mais j'ai pu écrire plus longtemps que d'habitude et ressentir un sentiment de fatigue et d'accomplissement. En plus de mes messages, diverses personnes publient de merveilleux articles sur divers sujets à différents niveaux, alors jetez un œil.

Recommended Posts

Implémentation de la méthode de gradient 1
Liste des méthodes de descente de gradient (2020)
Résumé de la méthode d'implémentation Unity IAP
Implémentation Einsum de la méthode d'itération de valeur
Algorithme d'apprentissage automatique (méthode de descente de gradient)
Mise en œuvre et expérience de la méthode de clustering convexe
Recherche de points de selle à l'aide de la méthode du gradient
Mise en œuvre de la fermeture
Méthode binaire
Pensez grossièrement à la méthode de descente de gradient
Implémentation de SVM par méthode de descente de gradient probabiliste
Méthode spéciale
Méthode spéciale
Note récapitulative sur l'apprentissage profond -4.3 Méthode de gradient
Implémentation de la régression logistique avec la méthode d'optimisation des groupes de particules