PyTorch RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

with torch.set_grad_enabled(True):

最近在跑一个项目时,遇到了标题中提到的报错。
报错代码片段如下:

X = X.clone().detach().requires_grad_(True).cuda()
pred = model(X, timesteps=timesteps)
mask = pred.argmax(-1).eq(y) # stop attacking when misclassified
if (mask == False).all(): 
    return X.detach() # stop loop when all samples are misclassified
loss = nn.CrossEntropyLoss(reduction='none')(pred, y)
loss = torch.mean(loss)
grad, = torch.autograd.grad(loss, [X])

即使在计算梯度之前已经设置了 X.requires_grad_(True),并且在调试过程中检查到 loss.requires_gradTrue,依然报错:

报错内容

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

报错原因分析:

虽然代码中 X 设置了 requires_grad_(True),并且 lossrequires_grad 属性在调试时显示为 True,但 PyTorch 的自动求导机制在某些情况下默认禁用梯度计算。例如,当程序在测试或推理模式下运行时,梯度计算可能被禁用。这通常发生在没有明确设置为训练模式时(如在验证或推理时),或者是在训练代码块外进行的操作。此时即便 requires_gradTrue,也不会触发梯度计算,从而导致 torch.autograd.grad() 无法正确计算梯度。

核心原因在于某些场景下,PyTorch 默认禁用了全局的梯度计算,导致 requires_grad 设置无效化。


解决方法:

为了确保在所有情况下都启用梯度计算,可以在报错的代码前添加以下代码:

with torch.set_grad_enabled(True):
    X = X.clone().detach().requires_grad_(True).cuda()
    pred = model(X, timesteps=timesteps)
    mask = pred.argmax(-1).eq(y) # stop attacking when misclassified
    if (mask == False).all(): 
        return X.detach() # stop loop when all samples are misclassified
    loss = nn.CrossEntropyLoss(reduction='none')(pred, y)
    loss = torch.mean(loss)
    grad, = torch.autograd.grad(loss, [X])

torch.set_grad_enabled(True) 明确地打开了全局的梯度计算,确保即使在推理模式下(例如,在 model.eval() 或验证阶段)也可以正常计算梯度。
此设置尤其适用于像攻击算法或其他需要手动控制梯度的情况,确保整个代码块中的计算可以正确追踪梯度。


这样不仅解决了报错,还确保了在任何模式下,计算图都能被构建并计算梯度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值