[PYTHON] pyTorch optim SGD explication approfondie

2020/1/27 Publié

0. Qui est la cible de cet article

1.Tout d'abord

De nos jours, la recherche principale sur l'apprentissage automatique se fait dans le langage python, car python dispose de nombreuses bibliothèques (appelées modules) pour l'analyse et le calcul de données à grande vitesse. Parmi eux, cette fois, nous utiliserons un module appelé ** pyTorch **, et expliquerons comment mettre à jour les paramètres en utilisant la méthode de descente de gradient probabiliste (SGD) ** Comment le gérer dans le programme **. Cependant, cet article est comme votre propre mémo, et je souhaite que vous l'utilisiez comme référence uniquement, et il se peut que vous utilisiez des expressions ou des phrases incorrectes par souci de concision, mais comprenez cela. Je veux que tu le fasses. De plus, je ne donnerai pas d'explication vraiment détaillée sur SGD, donc si cela vous intéresse, apprenez par vous-même.

De plus, dans cet article, nous n'apprendrons pas réellement à utiliser Network. Si cela vous intéresse, veuillez vous référer au lien ci-dessous.

Explication approfondie des CNN avec pyTorch

2. Installez pyTorch

Si vous utilisez pyTorch pour la première fois, vous devez l'installer avec cmd car pyTorch n'est pas encore installé en python. Allez au lien ci-dessous, sélectionnez celui de votre environnement avec "QUICK START LOCALLY" en bas de la page, et entrez la commande qui apparaît avec cmd etc. (Vous devriez pouvoir copier et exécuter la commande).

site officiel de pytorch

3. Types spéciaux fournis par pyTorch

Tout comme numpy a un type appelé ndarray, pyTorch a un type appelé "** Tensor type **". Comme le type ndarray, il peut effectuer des calculs matriciels et est assez similaire les uns aux autres, mais le type Tensor est supérieur en apprentissage automatique en ce sens qu'il peut utiliser le GPU. En effet, l'apprentissage automatique nécessite une quantité considérable de calculs et utilise un GPU avec une vitesse de calcul élevée. De plus, le type Tensor est très facile à différencier pour les mises à jour des paramètres d'apprentissage automatique. La clé de cet article est la facilité avec laquelle il est possible de le faire.

Veuillez vous référer au lien ci-dessous pour les opérations et les explications de type Tensor.

Quel est le type Tensor de pyTorch

Veuillez vous référer au lien ci-dessous pour savoir comment la différenciation est réalisée.

Résumé des exemples qui ne peuvent pas être pyTorch à l'envers

4. Qu'est-ce que le gradient stochastique (SGD)?

C'est ce qu'on appelle la méthode de descente de gradient stochastique, qui est simplement une méthode de mise à jour des paramètres. Il existe de nombreuses explications mathématiques à ce sujet, je ne vais donc pas l'expliquer ici.

5. pyTorch SGD

5-1. Importation de pyTorch

Tout d'abord, importez pour pouvoir utiliser pyTorch. À partir de là, écrivez dans le fichier python au lieu de cmd, etc. Utilisez le module en écrivant le code suivant.

filename.rb


import torch
import torch.optim as optim

La deuxième ligne "** import torch.optim as optim **" est le module prêt à utiliser SGD.

5-2. optim.SGD Tout d'abord, les arguments de SGD seront expliqués. L'utilisation est écrite comme suit.

filename.rb


op = optim.SGD(params, lr=l, momentum=m, dampening=d, weight_decay=w, nesterov=n)

Explication des arguments suivants

--params: transmettez le paramètre à mettre à jour. Ce paramètre doit être divisible. --lr: taux d'apprentissage. Passez un type float. --momentum: Momentum. Passe un type float. --dampening: Manipule la quantité de mouvement. Passe le type float. --weight_decay: De combien ajouter la norme L2 des paramètres comme régularisation. Passez le type float. --neserov: appliquez l'élan nesterov comme élan ou passez Vrai ou Faux.

Cette fois, les informations supplémentaires momentum, amortissement, weight_decay et nestrov sont utilisées comme valeurs initiales (toutes sont 0 ou False) afin de voir le comportement de SGD.

5-3. Utilisation de SGD

Le programme lui-même est très simple et un exemple de calcul est présenté comme une préparation préliminaire.

filename.rb


x = torch.tensor(5.0, requires_grad = True)
c = torch.tensor(3.0, requires_grad = True)
b = torch.tensor(2.0)
d = 4.0
y = c*3*torch.exp(x) + b*x + d
print(y)

------------Sortie ci-dessous---------------
tensor(1349.7185, grad_fn=<AddBackward0>)

Si vous écrivez ce programme comme une expression

y = 3 c e^{x} + bx + d

Dans $ x = 5 $, $ c = 3 $, $ b = 2 $, $ d = 4 $. En outre, "** requires_grad = True **" est défini de sorte que seules les variables ** x ** et ** c ** puissent être calculées de manière différentielle. À partir de là, nous passons à SGD pour mettre à jour ces deux variables. Ce qui suit est un exemple.

filename.rb


op = optim.SGD([x,c], lr=1.0)

Notez que l'argument qui passe à la partie ** params ** de SGD est "** [x, c] ", mais les paramètres passés de cette manière sont la liste " [] **". Je dois faire grand. C'est bien sûr ** la même chose lorsqu'il n'y a qu'une seule variable de paramètre **. De plus, lorsque vous créez un réseau par apprentissage automatique, etc., vous pouvez entrer les paramètres de ce modèle, mais dans ce cas, vous n'avez pas besoin de cette parenthèse. Dans un peu plus de détails, params s'attend à ce que l'itération vienne comme argument, et les paramètres du modèle sont sous forme d'itération, donc nous n'en avons pas besoin. Voir l'explication de CNN présentée ci-dessus pour un exemple d'insertion d'un modèle.

De plus, cette variable ** op ** a maintenant la fonction de SGD, mais lorsque vous la sortez réellement, le contenu de SGD apparaît.

filename.rb


print(op)

------------Sortie ci-dessous---------------
SGD (
Parameter Group 0
    dampening: 0
    lr: 1.0
    momentum: 0
    nesterov: False
    weight_decay: 0
)

La différenciation réelle des paramètres est la suivante.

filename.rb


y.backward()
print(x.grad)
print(c.grad)

------------Sortie ci-dessous---------------
tensor(1337.7185)
tensor(445.2395)

La valeur différentielle de chaque variable peut être visualisée en tapant "** nom de la variable.grad ". De cette manière, " y.backward () **" différencie automatiquement les variables liées à la sortie finale ** y **. Ensuite, mettez à jour les paramètres comme suit.

filename.rb


op.step()
print(x)
print(c)

------------Sortie ci-dessous---------------
tensor(-1332.7185, requires_grad=True)
tensor(-442.2395, requires_grad=True)

De cette façon, "** op.step () **" est utilisé pour mettre à jour en utilisant les informations différentielles de chaque variable. En d'autres termes, vous pouvez voir que la mémoire des variables réelles ** x ** et ** c ** correspond à la mémoire de ces valeurs dont SGD dispose. La formule de mise à jour dans les conditions actuelles est la suivante.

x \leftarrow x - \eta\frac{\partial y}{\partial x}

$ \ Eta $ est le taux d'apprentissage, qui est maintenant de 1,0. Réécrire la formule ci-dessus avec la valeur réelle de la variable et la valeur différentielle

-1332.7185 \leftarrow 5.0 - 1.0\times 1337.7185

Cela correspond certainement.

5-4. Réécriture du contenu de SGD

La variable ** op ** avec la fonction SGD a été sortie ci-dessus, mais des informations détaillées telles que les paramètres ne sont pas sorties. La sortie détaillée doit être la suivante. Cependant, le programme suivant est exécuté avec les données avant le calcul différentiel et la mise à jour effectuée ci-dessus (les variables x et c restent les mêmes).

filename.rb


print(op.param_groups)

------------Sortie ci-dessous---------------
[{'params': [tensor(5., requires_grad=True), tensor(3., requires_grad=True)],
  'lr': 1.0,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

En faisant cela, vous pouvez voir les paramètres détaillés de SGD, et vous pouvez voir que les informations sont contenues dans le type de liste "** [] **". En d'autres termes, si vous souhaitez modifier le contenu, procédez comme suit.

filename.rb


op.param_groups[0]['lr'] = 0.1
print(op)

------------Sortie ci-dessous---------------
SGD (
Parameter Group 0
    dampening: 0
    lr: 0.1
    momentum: 0
    nesterov: False
    weight_decay: 0
)

Maintenant, le taux d'apprentissage ** lr ** a été réécrit à 0,1. Lorsque vous essayez réellement la sortie normale, vous pouvez voir qu'elle a été réécrite.

5-5. Réécriture de la variable à mettre à jour (côté SGD)

Comme ci-dessus, réécrivons les informations de la variable ** x ** en utilisant la réécriture des paramètres de SGD. Premièrement, les paramètres sont

filename.rb


print(op.param_groups[0]['params'])

------------Sortie ci-dessous---------------
[tensor(5., requires_grad=True), tensor(3., requires_grad=True)]

Est. Maintenant, réécrivez le 0ème élément du côté variable ** x ** de ceci.

filename.rb


op.param_groups[0]['params'][0] = torch.tensor(10., requires_grad=True)
print(op.param_groups)

------------Sortie ci-dessous---------------
[{'params': [tensor(10., requires_grad=True), tensor(3., requires_grad=True)],
  'lr': 0.1,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

Certainement réécrit. ** Mais regardons la valeur réelle de la variable. **

filename.rb


print(x)

------------Sortie ci-dessous---------------
tensor(5., requires_grad=True)

Le corps n'a pas du tout été réécrit. Quand je le mets à jour avec backward ()

filename.rb


y.backward()
op.step()
print(x)
print(x.grad)
print(op.param_groups)

------------Sortie ci-dessous---------------
tensor(5., requires_grad=True)
tensor(1337.7185)
[{'params': [tensor(10., requires_grad=True),
   tensor(-41.5240, requires_grad=True)],
  'lr': 0.1,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

Notez que la valeur de la variable c est différente de l'exemple ci-dessus car le taux d'apprentissage lr est de 0,1. De cette manière, ni la valeur de la variable x ni la valeur de x de SGD ne sont mises à jour. De plus, ** x.grad ** est calculé lorsque la variable ** x ** vaut 5. Cela est dû au fait que l'emplacement de la mémoire est différent lors de l'affectation de "** torch.tensor (10., requires_grad = True) **". Soyez très prudent lorsque vous modifiez la valeur d'une variable.

5-5. Réécriture de la variable que vous souhaitez mettre à jour (côté variable normal)

Ci-dessus, il a été constaté que lorsque les informations de variable SGD ont été réécrites, les variables et les paramètres SGD n'interagissaient pas entre eux. Il a dit que la raison était un décalage de mémoire. Réécrivons maintenant les variables.

filename.rb


op = optim.SGD([x,c], lr=1.0)
print(op.param_groups)

------------Sortie ci-dessous---------------
[{'params': [tensor(5., requires_grad=True), tensor(3., requires_grad=True)],
  'lr': 1.0,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

Pour cette variable ** x **

filename.rb


x = torch.tensor(10., requires_grad=True)
print(x)

------------Sortie ci-dessous---------------
tensor(10., requires_grad=True)

Et. Si vous regardez à nouveau les détails de la variable ** op ** ici

filename.rb


print(op.param_groups)

------------Sortie ci-dessous---------------
[{'params': [tensor(5., requires_grad=True), tensor(3., requires_grad=True)],
  'lr': 1.0,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

Les paramètres n'ont pas changé. Bien sûr, si vous mettez à jour avec backward () tel quel

filename.rb


y.backward()
op.step()
print(x)
print(x.grad)
print(op.param_groups)

------------Sortie ci-dessous---------------
tensor(10., requires_grad=True)
None
[{'params': [tensor(-1332.7185, requires_grad=True),
   tensor(-442.2395, requires_grad=True)],
  'lr': 1.0,
  'momentum': 0,
  'dampening': 0,
  'weight_decay': 0,
  'nesterov': False}]

Fait intéressant, rien n'a été fait pour les différentes variables de mémoire ** x **, et les paramètres de SGD ont été mis à jour. En conclusion, ** évitez de réécrire les variables que vous souhaitez mettre à jour inutilement **.

6. Un mot

Cette fois, j'ai expliqué le SGD de l'optimiseur en utilisant pyTorch, bien que ce soit simple. Étonnamment, il n'y avait aucun exemple d'application de SGD à autre chose que Network, donc je vais vous le présenter. Je pense qu'il y avait de nombreux points difficiles à lire, mais merci d'avoir lu.

Recommended Posts

pyTorch optim SGD explication approfondie
[PyTorch] Exemple ⑦ ~ package optim ~
Remarques sur l'optimisation à l'aide de Pytorch