我正在阅读PyTorch的文档,并找到了他们编写的示例
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
其中x是一个初始变量,从中构造y(一个3向量)。问题是,渐变张量的0.1,1.0和0.0001参数是什么?文档不是很清楚。
对于神经网络,我们通常使用loss
来评估网络学习对输入图像(或其他任务)进行分类的程度。 loss
术语通常是标量值。为了更新网络的参数,我们需要计算loss
wrt到参数的梯度,这实际上是计算图中的leaf node
(顺便说一句,这些参数主要是各种层的权重和偏差,如卷积,线性等)。
根据链规则,为了计算loss
w.r.t到叶节点的梯度,我们可以计算loss
w.r.t的一些中间变量的导数,并将中间变量w.r.t的梯度计算到叶变量,做一个点积并将所有这些加起来。
gradient
的Variable
方法的backward()
论证用于计算变量w.r.t leaf Variable的每个元素的加权和。这些权重只是最终loss
w.r.t中间变量的每个元素的推导。
让我们用一个具体而简单的例子来理解这一点。
from torch.autograd import Variable
import torch
x = Variable(torch.FloatTensor([[1, 2, 3, 4]]), requires_grad=True)
z = 2*x
loss = z.sum(dim=1)
# do backward for first element of z
z.backward(torch.FloatTensor([[1, 0, 0, 0]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_() #remove gradient in x.grad, or it will be accumulated
# do backward for second element of z
z.backward(torch.FloatTensor([[0, 1, 0, 0]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_()
# do backward for all elements of z, with weight equal to the derivative of
# loss w.r.t z_1, z_2, z_3 and z_4
z.backward(torch.FloatTensor([[1, 1, 1, 1]]), retain_graph=True)
print(x.grad.data)
x.grad.data.zero_()
# or we can directly backprop using loss
loss.backward() # equivalent to loss.backward(torch.FloatTensor([1.0]))
print(x.grad.data)
在上面的例子中,第一个print
的结果是
2 0 0 0 [火炬.FloatTensor大小1x4]
这正是z_1 w.r.t到x的导数。
第二个print
的结果是:
0 2 0 0 [火炬.FloatTensor大小1x4]
这是z_2 w.r.t到x的导数。
现在,如果使用[1,1,1,1]的权重来计算z w.r.t到x的导数,则结果为1*dz_1/dx + 1*dz_2/dx + 1*dz_3/dx + 1*dz_4/dx
。所以毫不奇怪,第3个print
的输出是:
2 2 2 2 [火炬.FloatTensor大小1x4]
应该注意的是,权重向量[1,1,1,1]恰好是loss
w.r.t到z_1,z_2,z_3和z_4的导数。 loss
w.r.t到x
的导数计算如下:
d(loss)/dx = d(loss)/dz_1 * dz_1/dx + d(loss)/dz_2 * dz_2/dx + d(loss)/dz_3 * dz_3/dx + d(loss)/dz_4 * dz_4/dx
因此第4个print
的输出与第3个print
相同:
2 2 2 2 [火炬.FloatTensor大小1x4]
通常,您的计算图有一个标量输出,如loss
。然后你可以计算loss
w.r.t的梯度。 w
的重量(loss.backward()
)。 backward()
的默认参数是1.0
。
如果您的输出具有多个值(例如loss=[loss1, loss2, loss3]
),则可以计算w.r.t的损失梯度。 loss.backward(torch.FloatTensor([1.0, 1.0, 1.0]))
的重量。
此外,如果您想为不同的损失添加权重或重要性,您可以使用loss.backward(torch.FloatTensor([-0.1, 1.0, 0.0001]))
。
这意味着同时计算-0.1*d(loss1)/dw, d(loss2)/dw, 0.0001*d(loss3)/dw
。
这里,forward()的输出,即y是3矢量。
这三个值是网络输出的梯度。如果y是最终输出,它们通常设置为1.0,但也可以设置其他值,尤其是如果y是更大网络的一部分。
例如。如果x是输入,y = [y1,y2,y3]是一个中间输出,用于计算最终输出z,
然后,
dz/dx = dz/dy1 * dy1/dx + dz/dy2 * dy2/dx + dz/dy3 * dy3/dx
所以这里,向后的三个值是
[dz/dy1, dz/dy2, dz/dy3]
然后向后()计算dz / dx