如何在PyTorch中手动应用渐变。

10
开始学习PyTorch,尝试做一些非常简单的事情,试图将一个随机初始化的大小为5的向量移动到目标向量[1,2,3,4,5]。
但是我的距离没有减小!而且我的向量x变得疯狂。不知道我漏掉了什么。
import torch
import numpy as np
from torch.autograd import Variable

# regress a vector to the goal vector [1,2,3,4,5]

dtype = torch.cuda.FloatTensor # Uncomment this to run on GPU

x = Variable(torch.rand(5).type(dtype), requires_grad=True)
target = Variable(torch.FloatTensor([1,2,3,4,5]).type(dtype), 
requires_grad=False)
distance = torch.mean(torch.pow((x - target), 2))

for i in range(100):
  distance.backward(retain_graph=True)
  x_grad = x.grad
  x.data.sub_(x_grad.data * 0.01)

我的答案解决了您的问题吗?为什么您不给任何反馈呢? - jdhao
1个回答

9

你的代码中有两个错误,导致你无法得到期望的结果。

第一个错误是你应该将距离计算放在循环中。因为在这种情况下,距离就是损失。所以我们必须在每次迭代中监控它的变化。

第二个错误是你应该手动将x.grad清零,因为PyTorch不会默认清零变量的梯度

以下是一个可以正常工作的示例代码:

import torch
import numpy as np
from torch.autograd import Variable
import matplotlib.pyplot as plt

# regress a vector to the goal vector [1,2,3,4,5]

dtype = torch.cuda.FloatTensor # Uncomment this to run on GPU

x = Variable(torch.rand(5).type(dtype), requires_grad=True)
target = Variable(torch.FloatTensor([1,2,3,4,5]).type(dtype), 
requires_grad=False)

lr = 0.01 # the learning rate

d = []
for i in range(1000):
  distance = torch.mean(torch.pow((x - target), 2))
  d.append(distance.data)
  distance.backward(retain_graph=True)

  x.data.sub_(lr * x.grad.data)
  x.grad.data.zero_()

print(x.data)

fig, ax = plt.subplots()
ax.plot(d)
ax.set_xlabel("iteration")
ax.set_ylabel("distance")
plt.show()

以下是迭代次数与距离的图表。

enter image description here

我们可以看到,模型在大约600次迭代后收敛。如果我们将学习率设置得更高(例如,lr=0.1),模型将会更快地收敛(大约需要60次迭代,见下图)。

enter image description here

现在,x 变成了类似以下的内容:

0.9878 1.9749 2.9624 3.9429 4.9292

这已经非常接近你的目标 [1, 2, 3, 4, 5] 了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接