J'ai trois questions simples.
requires_grad = True
pour cette variable? ou ça n'a pas d'importance? Si cela n'a pas d'importance, alors pourquoi?forward
. Quelle approche est préférable, écrire une fonction ou un calque? Pourquoi?J'ai besoin d'une explication claire et agréable de ces questions pour résoudre mes confusions. Veuillez aider.
Laisse-moi essayer.
Cela dépend de ce que vous entendez par "non différenciable". La première définition qui a du sens ici est que PyTorch ne sait pas calculer les gradients. Si vous essayez néanmoins de calculer des gradients, cela générera une erreur. Les deux scénarios possibles sont:
a) Vous utilisez une opération PyTorch personnalisée pour laquelle les dégradés n'ont pas été implémentés, par ex. torch.svd()
. Dans ce cas, vous obtiendrez un TypeError
:
import torch
from torch.autograd import Function
from torch.autograd import Variable
A = Variable(torch.randn(10,10), requires_grad=True)
u, s, v = torch.svd(A) # raises TypeError
b) Vous avez implémenté votre propre opération, mais vous n'avez pas défini backward()
. Dans ce cas, vous obtiendrez un NotImplementedError
:
class my_function(Function): # forgot to define backward()
def forward(self, x):
return 2 * x
A = Variable(torch.randn(10,10))
B = my_function()(A)
C = torch.sum(B)
C.backward() # will raise NotImplementedError
La deuxième définition qui a du sens est "mathématiquement non différenciable". De toute évidence, une opération qui n'est pas mathématiquement différenciable ne devrait pas avoir une méthode backward()
implémentée ou un sous-gradient sensible. Considérez par exemple torch.abs()
dont la méthode backward()
renvoie le sous-gradient 0 à 0:
A = Variable(torch.Tensor([-1,0,1]),requires_grad=True)
B = torch.abs(A)
B.backward(torch.Tensor([1,1,1]))
A.grad.data
Pour ces cas, vous devez vous référer directement à la documentation PyTorch et extraire directement la méthode backward()
de l'opération respective.
Ça n'a pas d'importance. L'utilisation de requires_grad
Permet d'éviter les calculs inutiles de gradients pour les sous-graphiques. S'il existe une seule entrée pour une opération qui nécessite un gradient, sa sortie nécessitera également un gradient. Inversement, seulement si toutes les entrées ne nécessitent pas de dégradé, la sortie ne le requiert pas non plus. Le calcul en arrière n'est jamais effectué dans les sous-graphiques, où toutes les variables ne nécessitaient pas de dégradés.
Puisqu'il y a très probablement quelques Variables
(par exemple les paramètres d'une sous-classe de nn.Module()
), votre loss
variable nécessitera également des gradients automatiquement. Cependant, vous devez noter que pour le fonctionnement exact de requires_grad
(Voir ci-dessus à nouveau), vous ne pouvez de toute façon modifier que requires_grad
Pour les variables feuille de votre graphique.
Toutes les fonctions de perte PyTorch personnalisées sont des sous-classes de _Loss
Qui est une sous-classe de nn.Module
. Voir ici. Si vous souhaitez vous en tenir à cette convention, vous devez sous-classer _Loss
Lors de la définition de votre fonction de perte personnalisée. Outre la cohérence, un avantage est que votre sous-classe lèvera un AssertionError
, si vous n'avez pas marqué vos variables cibles comme volatile
ou requires_grad = False
. Un autre avantage est que vous pouvez imbriquer votre fonction de perte dans nn.Sequential()
, car c'est un nn.Module
Je recommanderais cette approche pour ces raisons.