Le code original que je n'ai plus trouvé sur le site Web de PyTorch.
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
Le problème avec le code ci-dessus, il n'y a pas de fonction basée sur quoi calculer les gradients. Cela signifie que nous ne savons pas combien de paramètres (arguments la fonction prend) et la dimension des paramètres.
Pour bien comprendre cela, j'ai créé un exemple proche de l'original:
Exemple 1:
a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
b = torch.tensor([3.0, 4.0, 5.0], requires_grad = True)
c = torch.tensor([6.0, 7.0, 8.0], requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients,retain_graph=True)
print(a.grad) # tensor([3.0000e-01, 3.0000e+00, 3.0000e-04])
print(b.grad) # tensor([1.2000e+00, 1.6000e+01, 2.0000e-03])
print(c.grad) # tensor([1.6667e-02, 1.4286e-01, 1.2500e-05])
J'ai supposé que notre fonction est y=3*a + 2*b*b + torch.log(c)
et que les paramètres sont des tenseurs avec trois éléments à l'intérieur.
Vous pouvez penser gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
à ce que c'est l'accumulateur.
Comme vous pouvez l'entendre, le calcul du système d'autogradation PyTorch est équivalent au produit Jacobien.
Au cas où vous auriez une fonction, comme nous l'avons fait:
y=3*a + 2*b*b + torch.log(c)
Jacobien serait [3, 4*b, 1/c]
. Cependant, ce Jacobien n'est pas la façon dont PyTorch fait les choses pour calculer les gradients à un certain point.
PyTorch utilise la différenciation automatique (AD) en mode passe avant et arrière en tandem.
Il n'y a pas de mathématiques symboliques impliquées et aucune différenciation numérique.
La différenciation numérique serait de calculer δy/δb
, pour b=1
et b=1+ε
où ε est petit.
Si vous n'utilisez pas de dégradés dans y.backward()
:
Exemple 2
a = torch.tensor(0.1, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(0.1, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward()
print(a.grad) # tensor(3.)
print(b.grad) # tensor(4.)
print(c.grad) # tensor(10.)
Vous simplement obtenir le résultat à un point, en fonction de la façon dont vous définissez votre a
, b
, c
tenseurs initialement.
Soyez prudent lorsque vous initialisez votre a
, b
, c
:
Exemple 3:
a = torch.empty(1, requires_grad = True, pin_memory=True)
b = torch.empty(1, requires_grad = True, pin_memory=True)
c = torch.empty(1, requires_grad = True, pin_memory=True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(a.grad) # tensor([3.3003])
print(b.grad) # tensor([0.])
print(c.grad) # tensor([inf])
Si vous utilisez torch.empty()
et n'utilisez pas, pin_memory=True
vous pouvez avoir des résultats différents à chaque fois.
De plus, les dégradés de notes sont comme des accumulateurs, alors mettez-les à zéro si nécessaire.
Exemple 4:
a = torch.tensor(1.0, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(1.0, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward(retain_graph=True)
y.backward()
print(a.grad) # tensor(6.)
print(b.grad) # tensor(8.)
print(c.grad) # tensor(2.)
Enfin, quelques conseils sur les conditions d'utilisation de PyTorch:
PyTorch crée un graphe de calcul dynamique lors du calcul des gradients en passe avant. Cela ressemble beaucoup à un arbre.
Ainsi, vous entendrez souvent que les feuilles de cet arbre sont des tenseurs d'entrée et la racine est un tenseur de sortie .
Les dégradés sont calculés en traçant le graphique de la racine à la feuille et en multipliant chaque dégradé de la manière en utilisant la règle de la chaîne . Cette multiplication se produit lors de la passe arrière.