【问题标题】:Pytorch autograd.grad how to write the parameters for multiple outputs?Pytorch autograd.grad如何写多个输出的参数?
【发布时间】:2020-01-23 08:04:35
【问题描述】:

torch.autograd.graddocumentation中声明,对于参数,

参数:

outputs(张量序列)- 微分函数的输出。

inputs(张量序列)- 输入 w.r.t. 将返回哪个梯度(而不是累积到 .grad 中)。

我尝试以下方法:

a = torch.rand(2, requires_grad=True)
b = torch.rand(2, requires_grad=True)
c = a+b
d = a-b

torch.autograd.grad([c, d], [a, b]) #ValueError: only one element tensors can be converted to Python scalars
torch.autograd.grad(torch.tensor([c, d]), torch.tensor([a, b])) #RuntimeError: grad can be implicitly created only for scalar outputs

我想得到一个张量列表的梯度 w.r.t 另一个张量列表。输入参数的正确方法是什么?

【问题讨论】:

    标签: python-3.x deep-learning pytorch


    【解决方案1】:

    正如torch.autograd.grad 所提到的,torch.autograd.grad 计算并返回输出 w.r.t 的梯度总和。输入。由于您的cd 不是标量值,因此grad_outputs 是必需的。

    import torch
    
    a = torch.rand(2,requires_grad=True)
    b = torch.rand(2, requires_grad=True)
    
    a
    # tensor([0.2308, 0.2388], requires_grad=True)
    
    b
    # tensor([0.6314, 0.7867], requires_grad=True)
    
    c = a*a + b*b
    d = 2*a+4*b
    
    torch.autograd.grad([c,d], inputs=[a,b], grad_outputs=[torch.Tensor([1.,1.]), torch.Tensor([1.,1.])])
    # (tensor([2.4616, 2.4776]), tensor([5.2628, 5.5734]))
    

    说明: dc/da = 2*a = [0.2308*2, 0.2388*2] dd/da = [2.,2.] 所以第一个输出是dc/da*grad_outputs[0]+dd/da*grad_outputs[1] = [2.4616, 2.4776]。第二个输出的计算相同。

    如果你只想得到cd w.r.t 的梯度。输入,也许你可以这样做:

    a = torch.rand(2,requires_grad=True)
    b = torch.rand(2, requires_grad=True)
    
    a
    # tensor([0.9566, 0.6066], requires_grad=True)
    b
    # tensor([0.5248, 0.4833], requires_grad=True)
    
    c = a*a + b*b
    d = 2*a+4*b
    
    [torch.autograd.grad(t, inputs=[a,b], grad_outputs=[torch.Tensor([1.,1.])]) for t in [c,d]]
    # [(tensor([1.9133, 1.2132]), tensor([1.0496, 0.9666])),
    # (tensor([2., 2.]), tensor([4., 4.]))]
    

    【讨论】:

    • 这是我能找到的关于autograd.grad 多变量的唯一示例。但是,我认为第一个输出是由(dc/da)*grad_outputs[0] +(dd/da)*grad_outputs[1] = [2.4616, 2.4776] 计算的。
    【解决方案2】:

    给你 在您给出的示例中:

    a = torch.rand(2, requires_grad=True)
    b = torch.rand(2, requires_grad=True)
    loss = a + b
    

    由于 loss 是一个有 2 个元素的向量,所以不能一次执行 autograd 操作。

    通常,

    loss = torch.sum(a + b)
    torch.autograd.grad([loss], [a, b])
    

    这将为包含一个元素的损失张量返回正确的梯度值。 您可以将多个标量张量传递给 torch.autograd.grad 方法的输出参数

    【讨论】:

    • 所以输出只能是标量或标量列表?我们不能得到向量的导数(Hessian 矩阵)吗?
    • 是的,这就是我能找到的。即使在典型的神经网络中,我们总是在反向传播之前对所有小批量样本求和或平均损失。
    猜你喜欢
    • 2019-07-12
    • 2019-07-12
    • 2018-10-14
    • 2020-01-05
    • 2021-11-27
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多