[PYTHON] J'ai aussi appris + init, class, qui a essayé de trouver la valeur minimale de la fonction quadratique en faisant la méthode d'optimisation (SGD, momentum, AdaGrad) en apprentissage profond par moi-même.

introduction

De nouveaux algorithmes sont créés chaque jour pour les méthodes d'optimisation des réseaux de neurones. Dans l'article précédent, j'ai résumé comment il a été développé de SGD à ADAM.

https://qiita.com/Fumio-eisan/items/798351e4915e4ba396c2

Dans cet article, j'aimerais mettre en œuvre cette technique d'optimisation et voir à quelle vitesse elle converge dans un réseau de neurones! .. Cette fois, j'aimerais appliquer cette méthode d'optimisation à une simple fonction quadratique. Dans les manuels, etc., prenez essentiellement une image numérique manuscrite telle que MNIST comme exemple et confirmez que la valeur de la fonction de perte diminue. Cependant, étant donné que la fonction de perte dans le réseau neuronal est très compliquée, il est difficile de déterminer si la valeur minimale est dérivée. Par conséquent, cette fois, je voudrais prendre une fonction quadratique comme exemple et voir comment elle se dirige vers la valeur minimale.   De plus, j'ai implémenté la définition et le chargement de la classe moi-même, mais je noterai ce que j'ai compris ici.

Ceci est un aperçu.

Objectif de la fonction cible et méthode d'optimisation

Voici le but de la fonction quadratique et de la méthode d'optimisation ciblée cette fois.

image.png

J'ai décidé de trouver la valeur minimale d'une fonction très simple à comprendre. Puisque $ y = x ^ 2 $, $ y $, qui prend la valeur minimale, devient $ y = 0 $ lorsque $ x = 0 $. Je voudrais utiliser cette fonction, qui est facile à comprendre à la fois sensuellement et visuellement, pour continuer à mettre à jour $ x $ et confirmer qu'elle s'approche de $ y = 0 $.

Détails d'implémentation

Cette fois, le programme qui définit la fonction est stocké dans optimizers.py. Ensuite, la fonction est lue dans sample.ipynb, calculée et illustrée. Par conséquent, lors de sa mise en œuvre, nous apprécierions que vous puissiez stocker ces deux programmes dans le même dossier et les exécuter.

Mettre en œuvre SGD (méthode de descente de gradient probabiliste)

Le premier est le SGD de base. La formule est présentée ci-dessous.

\mathbf{x}_{t + 1} \gets \mathbf{x}_{t} - \eta g_t\\
g_t = 2 *\mathbf{x}_{t} 

$ \ eta $ est le taux d'apprentissage et $ g_t $ est le gradient de la fonction. $ g_t $ vaut $ 2 * \ mathbf {x} _ {t} $ cette fois, donc c'est pratique.

Ensuite, nous mettrons en œuvre cette technique.

optimizers.py


class SGD:

    def __init__(self, lr = 0.01,x=100):
        self.lr = 0.01
        self.x =100.0

    def update(self,x):
        x+= -self.lr * 2*x 
        return x

La formule elle-même est simple, donc je pense qu'elle est facile à comprendre en regardant le programme. C'est une fonction qui calcule $ x $ à l'étape suivante et renvoie $ x $. $ \ Eta $ s'écrit ici comme $ lr $.

Maintenant, voici un programme qui calcule à plusieurs reprises $ x $ pour trouver réellement la valeur minimale.

sample.ipynb


max_iterations = 100

y7=[]
y8=[]
y9=[]

v7=[]
v8=[]
v9=[]
optimizer = optimizers.SGD()

x = 100
optimizer.lr =0.1
for i in range(max_iterations):
    x = optimizer.update(x)
    y7.append(x)
    v7.append(optimizer.lr)
    
x = 100
optimizer.lr =0.01
for i in range(max_iterations):
    x = optimizer.update(x)
    y8.append(x)
    v8.append(optimizer.lr)

x = 100
optimizer.lr =0.9
for i in range(max_iterations):
    x = optimizer.update(x)
    y9.append(x)
    v9.append(optimizer.lr)

Voyons comment la convergence de la fonction change lorsque nous changeons $ \ eta $ en 0.1,0.01,0.9.

sample.ipynb



x = np.arange(max_iterations)
plt.plot(x, y7, label='lr=0.1')
plt.plot(x, y8, label='lr=0.01')
plt.plot(x, y9, label='lr=0.9')
plt.xlabel("iterations")
plt.ylabel("y")
plt.ylim(-5, 120)
plt.legend()
plt.show()

005.png

Vous pouvez voir que plus la valeur de $ y $ sur l'axe vertical s'approche de 0, plus elle converge.

Si $ \ eta $ vaut 0,01, il faudra du temps pour converger. Au contraire, si $ \ eta $ est trop grand jusqu'à 0.9, vous pouvez voir qu'il passe à la convergence en chassant. Si cette valeur est 1 ou plus dans cette fonction, elle diverge. Par conséquent, on voit que $ \ eta $ est une bonne valeur autour de 0,1, ce qui converge rapidement et supprime la divergence.

Mettre en œuvre Momentum

Ensuite, nous mettrons en œuvre Momentum. Par rapport au SGD précédent, cet algorithme supprime les vibrations en considérant le mouvement de $ x $ lui-même.

\mathbf{x}_{t + 1} \gets \mathbf{x}_{t} + h_t\\
h_t=-\eta * g_t +\alpha * h_{t-1}

Définissez une fonction.

optimizers.py



class Momentum:

    def __init__(self,lr=0.01,alpha=0.8,v=None):
        self.lr = 0.01
        self.v = 0.0
        self.alpha = 0.8

    def update(self,x):
        self.v = self.v*self.alpha  - (2.0)*x*self.lr 
        x += + self.v
        return x

Et courir. Cette fois, nous évaluerons l'effet en changeant la valeur de $ \ alpha $ comme hyper paramètre. 006.png

On dit que le $ \ alpha $ standard est de 0,8. Même dans ce résultat, nous pouvons voir que 0.8 est une valeur qui semble juste. Si la valeur est supérieure à cela, vous chasserez beaucoup.

Mettre en œuvre AdaGrad

Eh bien, cette fois, le dernier est AdaGrad. Auparavant, le taux d'apprentissage $ \ eta $ était une constante. Cependant, la particularité est que ce taux d'apprentissage lui-même a pour effet de diminuer progressivement au fur et à mesure du nombre de calculs.

h_{0} = \epsilon\\
h_{t} = h_{t−1} + g_t^{2}\\
\eta_{t} = \frac{\eta_{0}}{\sqrt{h_{t}}}\\
\mathbf{x}_{t+1} = \mathbf{w}^{t} - \eta_{t}g_t

Définissez une fonction.

optimizers.py


class AdaGrad:

    def __init__(self,h0=10.0):
        self.v = 0.0
        self.h = 0.0
        self.h0 = 10.0

    def update(self,x):
        self.h += + (2.0*x)**2
        self.v = -self.h0/(np.sqrt(self.h)+1e-7)
        x += + self.v*2*x
        return x

Au fait, cette fois j'ai calculé en changeant la valeur initiale du taux d'apprentissage $ \ eta_0 $ (h0 dans le programme).

007.png

Il s'est avéré que $ \ eta_0 $ converge plus vite autour de 100 et ne diverge pas.

Compréhension de la classe et de l'init

Puisque je suis un débutant en Python, j'ai utilisé init dans ma classe avec une forte impression. Cette fois, j'ai trouvé ce qui suit.

en conclusion

Cette fois, la fonction a été minimisée par trois types de méthodes d'optimisation. Vous pouvez voir qu'il utilise l'idée de la formule graduelle apprise en mathématiques dites du secondaire. De plus, même si j'ai tout fait sauf numpy, cela m'a aidé à approfondir ma compréhension de la programmation elle-même. De plus, comme je l'ai appris dans le livre d'apprentissage profond d'O'Reilly, j'implémente en fait une méthode d'optimisation sur un réseau de neurones. Vous pouvez comprendre chaque contenu tel que la définition de fonctions et de petites variables, comment insérer une fonction d'activation, le calcul du gradient par la méthode de propagation d'erreur inverse, la détermination de la valeur initiale du paramètre de poids, etc. Cependant, quand il s'agit de le programmer, cela devient très compliqué.

** Une fois de plus, je me suis demandé si les programmeurs mettaient en œuvre une combinaison de ces nombreuses règles et connaissances structurelles, ce qui serait une tâche ardue. Sur la base de ces difficultés, je voudrais vous remercier de l'appeler comme une classe ou une méthode et d'utiliser la fonction facilement. ** **

Le programme complet est stocké ici. https://github.com/Fumio-eisan/optimizers_20200326

Recommended Posts

J'ai aussi appris + init, class, qui a essayé de trouver la valeur minimale de la fonction quadratique en faisant la méthode d'optimisation (SGD, momentum, AdaGrad) en apprentissage profond par moi-même.
Trouvez la valeur minimale de la fonction par la méthode d'optimisation du groupe de particules (PSO)
J'ai essayé d'afficher la valeur d'altitude du DTM dans un graphique
[Deep Learning from scratch] J'ai essayé d'expliquer la confirmation du gradient d'une manière facile à comprendre.
J'ai aussi essayé d'imiter la fonction monade et la monade d'état avec le générateur en Python
J'ai essayé de combattre le minimum local de la fonction Goldstein-Price
Je veux clarifier la question de la méthode "__init__" et de l'argument "self" de la classe Python.
J'ai essayé de trouver l'itinéraire optimal du pays des rêves par recuit (quantique)
J'ai essayé l'histoire courante de l'utilisation du Deep Learning pour prédire la moyenne Nikkei
J'ai essayé de vérifier le résultat du test A / B avec le test du chi carré
[Python & SQLite] J'ai analysé la valeur attendue d'une course avec des chevaux dans la fourchette 1x win ①
J'ai essayé de prédire le nombre de personnes infectées par le virus corona au Japon par la méthode du dernier article en Chine
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
J'ai essayé d'extraire le dessin au trait de l'image avec Deep Learning
J'ai essayé de prédire la présence ou l'absence de neige par apprentissage automatique.
J'ai essayé de prédire l'évolution de la quantité de neige pendant 2 ans par apprentissage automatique