pytorch中反向方法的第一个参数(梯度)是什么?
What is the first parameter (gradients) of the backward method, in pytorch?
我们从 pytorch 文档中获得了以下代码:
x = torch.randn(3)
x = Variable(x, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
我们传入backward方法的gradients参数到底是什么,我们根据什么初始化它?
要完全回答您的问题,需要更长的解释来围绕 Backprop or, more fundamentally, the chain rule 的工作原理进行详细说明。
简短的编程答案是 Variable
的向后函数计算附加到 Variable
的计算图中所有变量的梯度。 (澄清一下:如果你有 a = b + c
,那么计算图(递归地)首先指向 b
,然后指向 c
,然后指向它们的计算方式,等等)并累积存储(求和)这些变量的 .grad
属性中的这些梯度。当您随后调用 opt.step()
,即优化器的一个步骤时,它会将该梯度的一小部分添加到这些变量的值中。
也就是说,当您从概念上看时,有两个答案:如果您想训练机器学习模型,您通常希望获得关于某些损失函数的梯度。在这种情况下,计算的梯度将使得整体损失(标量值)在应用阶跃函数时减少。在这种特殊情况下,我们希望将梯度计算为特定值,即单位长度步长(以便学习率将计算我们想要的梯度分数)。这意味着如果你有一个损失函数,并且你调用 loss.backward()
,这将计算与 loss.backward(torch.FloatTensor([1.]))
.
相同的结果
虽然这是 DNN 中反向传播的常见用例,但它只是函数一般微分的特例。更一般地,符号微分包(在这种情况下为 autograd,作为 pytorch 的一部分)可用于计算计算图早期部分相对于根处的 any 梯度的梯度无论您选择什么子图。这是关键字参数 gradient
派上用场的时候,因为您可以在那里提供此 "root-level" 梯度,即使对于非标量函数也是如此!
为了说明,这里有一个小例子:
a = nn.Parameter(torch.FloatTensor([[1, 1], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.sum(a - b)
c.backward(None) # could be c.backward(torch.FloatTensor([1.])) for the same result
print(a.grad, b.grad)
打印:
Variable containing:
1 1
1 1
[torch.FloatTensor of size 2x2]
Variable containing:
-1 -1
-1 -1
[torch.FloatTensor of size 2x2]
同时
a = nn.Parameter(torch.FloatTensor([[1, 1], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.sum(a - b)
c.backward(torch.FloatTensor([[1, 2], [3, 4]]))
print(a.grad, b.grad)
打印:
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
Variable containing:
-1 -2
-3 -4
[torch.FloatTensor of size 2x2]
和
a = nn.Parameter(torch.FloatTensor([[0, 0], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.matmul(a, b)
c.backward(torch.FloatTensor([[1, 1], [1, 1]])) # we compute w.r.t. a non-scalar variable, so the gradient supplied cannot be scalar, either!
print(a.grad, b.grad)
打印
Variable containing:
3 3
3 3
[torch.FloatTensor of size 2x2]
Variable containing:
2 2
2 2
[torch.FloatTensor of size 2x2]
和
a = nn.Parameter(torch.FloatTensor([[0, 0], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.matmul(a, b)
c.backward(torch.FloatTensor([[1, 2], [3, 4]])) # we compute w.r.t. a non-scalar variable, so the gradient supplied cannot be scalar, either!
print(a.grad, b.grad)
打印:
Variable containing:
5 5
11 11
[torch.FloatTensor of size 2x2]
Variable containing:
6 8
6 8
[torch.FloatTensor of size 2x2]
我们从 pytorch 文档中获得了以下代码:
x = torch.randn(3)
x = Variable(x, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
我们传入backward方法的gradients参数到底是什么,我们根据什么初始化它?
要完全回答您的问题,需要更长的解释来围绕 Backprop or, more fundamentally, the chain rule 的工作原理进行详细说明。
简短的编程答案是 Variable
的向后函数计算附加到 Variable
的计算图中所有变量的梯度。 (澄清一下:如果你有 a = b + c
,那么计算图(递归地)首先指向 b
,然后指向 c
,然后指向它们的计算方式,等等)并累积存储(求和)这些变量的 .grad
属性中的这些梯度。当您随后调用 opt.step()
,即优化器的一个步骤时,它会将该梯度的一小部分添加到这些变量的值中。
也就是说,当您从概念上看时,有两个答案:如果您想训练机器学习模型,您通常希望获得关于某些损失函数的梯度。在这种情况下,计算的梯度将使得整体损失(标量值)在应用阶跃函数时减少。在这种特殊情况下,我们希望将梯度计算为特定值,即单位长度步长(以便学习率将计算我们想要的梯度分数)。这意味着如果你有一个损失函数,并且你调用 loss.backward()
,这将计算与 loss.backward(torch.FloatTensor([1.]))
.
虽然这是 DNN 中反向传播的常见用例,但它只是函数一般微分的特例。更一般地,符号微分包(在这种情况下为 autograd,作为 pytorch 的一部分)可用于计算计算图早期部分相对于根处的 any 梯度的梯度无论您选择什么子图。这是关键字参数 gradient
派上用场的时候,因为您可以在那里提供此 "root-level" 梯度,即使对于非标量函数也是如此!
为了说明,这里有一个小例子:
a = nn.Parameter(torch.FloatTensor([[1, 1], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.sum(a - b)
c.backward(None) # could be c.backward(torch.FloatTensor([1.])) for the same result
print(a.grad, b.grad)
打印:
Variable containing:
1 1
1 1
[torch.FloatTensor of size 2x2]
Variable containing:
-1 -1
-1 -1
[torch.FloatTensor of size 2x2]
同时
a = nn.Parameter(torch.FloatTensor([[1, 1], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.sum(a - b)
c.backward(torch.FloatTensor([[1, 2], [3, 4]]))
print(a.grad, b.grad)
打印:
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
Variable containing:
-1 -2
-3 -4
[torch.FloatTensor of size 2x2]
和
a = nn.Parameter(torch.FloatTensor([[0, 0], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.matmul(a, b)
c.backward(torch.FloatTensor([[1, 1], [1, 1]])) # we compute w.r.t. a non-scalar variable, so the gradient supplied cannot be scalar, either!
print(a.grad, b.grad)
打印
Variable containing:
3 3
3 3
[torch.FloatTensor of size 2x2]
Variable containing:
2 2
2 2
[torch.FloatTensor of size 2x2]
和
a = nn.Parameter(torch.FloatTensor([[0, 0], [2, 2]]))
b = nn.Parameter(torch.FloatTensor([[1, 2], [1, 2]]))
c = torch.matmul(a, b)
c.backward(torch.FloatTensor([[1, 2], [3, 4]])) # we compute w.r.t. a non-scalar variable, so the gradient supplied cannot be scalar, either!
print(a.grad, b.grad)
打印:
Variable containing:
5 5
11 11
[torch.FloatTensor of size 2x2]
Variable containing:
6 8
6 8
[torch.FloatTensor of size 2x2]