Степень F.normalize в pytorch почти равна нулю.
Коды в python3 & pytorch == 1.3.0:
import torch
import torch.nn.functional as F
x = torch.autograd.Variable(torch.Tensor([[1, 0]]), requires_grad=True)
x_norm = F.normalize(x, dim=-1)
z = x_norm.mm(x_norm.t())
print('x_norm', x_norm)
print('z', z)
x.register_hook(lambda g: print(g))
x_norm.register_hook(lambda g: print(g))
z.register_hook(lambda g: print(g))
z.backward()
Вывод:
x_norm tensor([[1., 0.]], grad_fn=<DivBackward0>)
z tensor([[1.]], grad_fn=<MmBackward>)
tensor([[1.]]) # z grad
tensor([[2., 0.]]) # x_norm grad
tensor([[0., 0.]]) # x grad
Почему градус х равен нулю? 'x.grad' дает тот же результат.
Согласно правилу цепочки, я думаю, результат должен быть [-1, 1] * [2, 0] = [- 2, 0].
На самом деле, когда я использую приведенные выше коды во всей сети, градиент работает нормально.
Что-то не так с моими кодами?
Пробовал
x_norm = x / torch.sqrt((x[0, 0]**2 + x[0, 1]**2))
Тот же результат.
Пробовал CUDA, то же самое.
Пробовал следующие коды, заменяя x_norm
на y_norm
:
import torch
import torch.nn.functional as F
x = torch.autograd.Variable(torch.Tensor([[1, 0]]), requires_grad=True)
y = torch.autograd.Variable(torch.Tensor([[2, 0]]), requires_grad=True)
x_norm = F.normalize(x, dim=-1)
y_norm = F.normalize(y, dim=-1)
z = x_norm.mm(y_norm.t())
y.register_hook(lambda g: print(g))
x.register_hook(lambda g: print(g))
x_norm.register_hook(lambda g: print(g))
z.register_hook(lambda g: print(g))
z.backward()
Вывод:
tensor([[1.]]) # z grad
tensor([[2., 0.]]) # x_norm grad
tensor([[0., 0.]]) # y grad
tensor([[0., 0.]]) # x grad
Однако, если я заменю z = x_norm.mm(y_norm.t())
на z = x_norm.mm(y.t())
, y
будет иметь ненулевое значение, а x
- нет.
Также попытался поставить F.normalize
в середине кодов:
import torch
import torch.nn.functional as F
#x = torch.autograd.Variable(torch.randn(1, 2), requires_grad=True)
x = torch.autograd.Variable(torch.Tensor([[1,0]]), requires_grad=True).cuda() y = torch.autograd.Variable(torch.Tensor([[2,0]]), requires_grad=True).cuda()
x1 = x * 2
x1_norm = F.normalize(x1, dim=-1)
print('x1', x1)
z = x1_norm.mm(y.t())
print('x1_norm', x1_norm)
print('z', z)
y.register_hook(lambda g: print('y', g))
x.register_hook(lambda g: print('x', g))
x1.register_hook(lambda g: print('x1', g))
x1_norm.register_hook(lambda g: print('x1_norm', g))
z.register_hook(lambda g: print('z', g))
z.backward()
Вывод
x1 tensor([[2., 0.]], device='cuda:0', grad_fn=<MulBackward0>)
x1_norm tensor([[1., 0.]], device='cuda:0', grad_fn=<DivBackward0>)
z tensor([[2.]], device='cuda:0', grad_fn=<MmBackward>)
z grad tensor([[1.]], device='cuda:0') # z grad
x1_norm grad tensor([[2., 0.]], device='cuda:0') # (x*2)_norm grad
x1 grad tensor([[0., 0.]], device='cuda:0') # x*2 grad
y grad tensor([[1., 0.]], device='cuda:0') # y grad
x grad tensor([[0., 0.]], device='cuda:0') # x grad