PyTorch: 变量和autograd

译者:@yongjay13@speedmancs

校对者:@bringtree

本例中的全连接神经网络有一个隐藏层, 后接ReLU激活层, 并且不带偏置参数. 训练时通过最小化欧式距离的平方, 来学习从x到y的映射.

在实现中, 我们将使用PyTorch变量的函数来进行前向计算, 并用PyTorch的autograd计算梯度

PyTorch变量是PyTorch张量的封装, 表示计算图中的一个节点. 如果x是变量, 那么x.data就是 表示其值的张量, 而x.grad则是另一个变量, 其中包含某个标量关于x的梯度.

PyTorch变量的API和张量是一样的: 几乎所有Tensor上能做的操作, 你在变量上也可以调用. 区别 在于用变量时, autograd可以自动计算梯度.

  1. import torch
  2. from torch.autograd import Variable
  3. dtype = torch.FloatTensor
  4. # dtype = torch.cuda.FloatTensor # 取消注释以在GPU上运行
  5. # N 批量大小; D_in是输入尺寸;
  6. # H是隐藏尺寸; D_out是输出尺寸.
  7. N, D_in, H, D_out = 64, 1000, 100, 10
  8. # 创建随机张量来保存输入和输出,并将它们包装在变量中.
  9. # 设置requires_grad = False, 因为在后向传播时, 我们并不需要计算关于这些变量的梯度
  10. x = Variable(torch.randn(N, D_in).type(dtype), requires_grad=False)
  11. y = Variable(torch.randn(N, D_out).type(dtype), requires_grad=False)
  12. # 为权重创建随机张量,并将其包装在变量中.
  13. # 设置requires_grad = True, 因为在后向传播时, 我们需要计算关于这些变量的梯度
  14. w1 = Variable(torch.randn(D_in, H).type(dtype), requires_grad=True)
  15. w2 = Variable(torch.randn(H, D_out).type(dtype), requires_grad=True)
  16. learning_rate = 1e-6
  17. for t in range(500):
  18. # 正向传递:使用变量上的运算来计算预测的y; 这些
  19. # 与我们用于计算使用张量的正向传递完全相同,
  20. # 但我们不需要保留对中间值的引用,
  21. # 因为我们没有实现向后传递.
  22. y_pred = x.mm(w1).clamp(min=0).mm(w2)
  23. # 使用变量上的操作计算和打印损失.
  24. # 现在损失是形状变量 (1,) 并且 loss.data 是形状的张量
  25. # (1,); loss.data[0] 是持有损失的标量值.
  26. loss = (y_pred - y).pow(2).sum()
  27. print(t, loss.data[0])
  28. # 使用autograd来计算反向传递.
  29. # 该调用将使用requires_grad = True来计算相对于所有变量的损失梯度.
  30. # 在这次调用之后 w1.grad 和 w2.grad 将是变量
  31. # 它们分别相对于w1和w2保存损失的梯度.
  32. loss.backward()
  33. # 使用梯度下降更新权重; w1.data 和 w2.data 是张量,
  34. # w1.grad 和 w2.grad 是变量并且 w1.grad.data 和 w2.grad.data
  35. # 是张量.
  36. w1.data -= learning_rate * w1.grad.data
  37. w2.data -= learning_rate * w2.grad.data
  38. # 更新权重后手动将梯度归零
  39. w1.grad.data.zero_()
  40. w2.grad.data.zero_()