gpt4 book ai didi

python - PyTorch 向后函数发生 RuntimeError

转载 作者:行者123 更新时间:2023-12-02 02:17:14 26 4
gpt4 key购买 nike

我正在尝试计算 PyTorch 中变量的梯度。然而,有一个运行时错误告诉我输出和梯度的形状必须相同。然而,就我而言,输出和梯度的形状不能相同。这是我要重现的代码:

import numpy as np
import torch
from torch.autograd import Variable as V

ne = 3
m, n = 79, 164
G = np.random.rand(m, n).astype(np.float64)
w = np.random.rand(n, n).astype(np.float64)
z = -np.random.rand(n).astype(np.float64)

G = V(torch.from_numpy(G))
w = V(torch.from_numpy(w))
z = V(torch.from_numpy(z), requires_grad=True)
e, v = torch.symeig(torch.diag(2 * z - torch.sum(w, dim=1)) + w, eigenvectors=True, upper=False)
ssev = torch.sum(torch.pow(e[-ne:] * v[:, -ne:], 2), dim=1)
out = torch.sum(torch.matmul(G, ssev.reshape((n, 1))))
out.backward(z)
print(z.grad)

错误消息是:RuntimeError: 形状不匹配:grad_output[0] 的形状为 torch.Size([164]) ,output[0] 的形状为 torch.Size([])

TensorFlow中允许类似的计算,我可以成功得到我想要的梯度:

import numpy as np
import tensorflow as tf

m, n = 79, 164
G = np.random.rand(m, n).astype(np.float64)
w = np.random.rand(n, n).astype(np.float64)
z = -np.random.rand(n).astype(np.float64)

def tf_function(z, G, w, ne=3):
e, v = tf.linalg.eigh(tf.linalg.diag(2 * z - tf.reduce_sum(w, 1)) + w)
ssev = tf.reduce_sum(tf.square(e[-ne:] * v[:, -ne:]), 1)
return tf.reduce_sum(tf.matmul(G, tf.expand_dims(ssev, 1)))

z, G, w = [tf.convert_to_tensor(_, dtype=tf.float64) for _ in (z, G, w)]
z = tf.Variable(z)
with tf.GradientTape() as g:
g.watch(z)
out = tf_function(z, G, w)
print(g.gradient(out, z).numpy())

我的tensorflow版本是2.0,我的PyTorch版本是1.14.0。我使用的是Python3.6.9。在我看来,当输出和变量具有不同形状时计算梯度是非常合理的,我认为我没有犯任何错误。任何人都可以帮助我解决这个问题吗?我真的很感激!

最佳答案

首先,你不需要使用 numpy 然后转换为 Variable (顺便说一下,这已被弃用),你可以只使用 G = torch.rand(m, n) 等其次,当您编写 out.backward(z) 时,您将 z 作为 gradient 传递。 out,即 out.backward(gradient=z),可能是由于“out.backward(z)”计算梯度的误解z,即dout/dz”。相反,对于某些函数 f(例如损失函数),此参数应为 gradient = d[f(out)]/dout,并且它是用于计算的张量vector-Jacobian product dout/dz * df/dout。因此,您收到错误的原因是因为您的 out (及其梯度 df/dout)是标量(零维张量)和 z 是大小为 n 的张量,导致形状不匹配。

要解决这个问题,正如您自己已经弄清楚的那样,只需将 out.backward(z) 替换为 out.backward(),这相当于out.backward(gradient=torch.tensor(1.)),因为在您的情况下 out 是一个标量,并且 f(out) = out,所以d[f(out)]/dout = d(out)/d(out) = 张量(1.)。如果您的 out 是非标量张量,则 out.backward() 将不起作用,而您必须使用 out.backward(torch.ones (out.shape)) (再次假设 f(out) = out)。无论如何,如果您需要将 gradient 传递给 out.backward(),请确保它与 out 具有相同的形状.

关于python - PyTorch 向后函数发生 RuntimeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60700062/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com