首页 文章

在pytorch中,后向方法的第一个参数(渐变)是什么?

提问于
浏览
3

我们从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)

我们传递给后向方法的渐变参数究竟是什么?基于我们初始化它的内容?

1 回答

  • 1

    为了完全回答你的问题,它需要一个更长的解释,围绕Backprop或更基本的chain rule如何工作的细节演变 .

    简短的程序化答案是 Variable 的向后函数计算附加到 Variable 的计算图中所有变量的梯度 . (澄清一下:如果你有 a = b + c ,则计算图(递归地)首先指向 b ,然后指向 c ,然后指向如何计算等等)并在这些变量的 .grad 属性中累积存储(求和)这些梯度 . 然后,当您调用 opt.step() ,即优化器的一个步骤时,它会将该梯度的一小部分添加到这些变量的值中 .

    也就是说,从概念上看它有两个答案:如果你想训练机器学习模型,你通常希望有一些关于某些损失函数的梯度 . 在这种情况下,计算的梯度将使得在应用阶梯函数时总损失(标量值)将减小 . 在这种特殊情况下,我们希望将梯度计算为特定值,即单位长度步长(以便学习率将计算我们想要的梯度的分数) . 这意味着如果你有一个损失函数,并且你调用 loss.backward() ,这将计算与 loss.backward(torch.FloatTensor([1.])) 相同 .

    虽然这是DNN中backprop的常见用例,但它只是函数一般区分的一个特例 . 更一般地,符号微分包(在这种情况下为autograd,作为pytorch的一部分)可用于计算计算图的早期部分相对于您选择的任何子图的根的任何梯度的梯度 . 这是关键字参数 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]
    

相关问题