import torch
import torch.optim as optim
import torch.nn as nn
input = torch.tensor([1.,2.], requires_grad=True)
sigmoid = nn.Sigmoid()
interm = sigmoid(input)
optimizer = optim.SGD([input], lr=1, momentum=0.9)
for epoch in range(5):
optimizer.zero_grad()
loss = torch.linalg.vector_norm(interm - torch.tensor([2.,2.]))
print(epoch, loss, input, interm)
loss.backward(retain_graph=True)
optimizer.step()
print(interm.grad)
Então criei este exemplo simplificado com uma entrada entrando em um sigmóide como uma função de ativação intermediária.
Estou tentando encontrar a entrada que resulta em interm = [2.,2.]
Mas os gradientes não estão passando. Alguém sabe por quê?
Grados são calculados para tensores de folha. No seu exemplo,
input
é um tensor folha, enquantointerm
não é.Ao tentar acessar
interm.grad
, você deverá receber a seguinte mensagem de erro:UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at aten/src/ATen/core/TensorBody.h:486.)
Isso ocorre porque os graduados são propagados de volta para o tensor folha
input
, e não parainterm
. Você pode adicionarinterm.retain_grad()
se quiser obter a graduação dainterm
variável.No entanto, mesmo que você tenha feito isso, não há nada no seu exemplo que possa
interm
alterar o valor de. Cada etapa do otimizador altera oinput
valor, mas isso não resulta nointerm
recalculado. Se quiserinterm
ser atualizado, você precisa recalculá-lo a cada iteração com o novoinput
valor. ou seja:Há também um problema fundamental com o que você está tentando fazer. Você diz que quer que
input
isso resulte eminterm = [2., 2.]
. No entanto, você está computandointerm = sigmoid(input)
. A função sigmóide é limitada entre(0, 1)
. Não existe tal valorinput
que resultaria eminterm = [2., 2.]
, porque2
está fora do intervalo da função sigmóide. Se você executasse seu loop de otimização indefinidamente, obteriainput = [inf, inf]
einterm = [1., 1.]
.