You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch中含模型输入梯度的损失函数参数梯度计算问题

PyTorch中损失依赖输入梯度时的参数梯度计算问题

问题原因

当损失函数依赖模型对输入的梯度(du/dx)时,模型中的偏置参数会因为对输入x求导后导数为0,完全不参与最终loss的计算图。此时调用grad(loss, model.parameters())时,这些偏置参数的梯度不存在,触发One of the differentiated Tensors appears to not have been used in the graph报错。

而loss1直接使用模型输出u,偏置参与了u的计算,所有参数都在计算图中,不会报错;设置bias=False后模型无偏置参数,自然也不会出现未使用的张量问题。

解决方案

方法1:允许未使用参数并过滤无效梯度

调用grad时添加allow_unused=True参数,然后过滤掉返回结果中的None(对应未参与计算的参数的梯度):

import torch
import torch.nn as nn
from torch.autograd import grad

model = nn.Sequential(nn.Linear(1, 10), nn.Tanh(), nn.Linear(10, 1))

def loss2(x, u):
    d_u_x = grad(u, x, torch.ones_like(u), retain_graph=True, create_graph=True)[0]
    return torch.mean(d_u_x)

x = torch.randn(10, 1)
x.requires_grad_()
u = model(x)

loss = loss2(x, u)
# 添加allow_unused=True允许未使用的参数
d_loss_params = grad(loss, model.parameters(), retain_graph=True, allow_unused=True)
# 过滤掉无梯度的参数结果
valid_gradients = [grad for grad in d_loss_params if grad is not None]
# 若需要和参数对应,可同时保留参数与梯度
param_grad_pairs = [(param, grad) for param, grad in zip(model.parameters(), d_loss_params) if grad is not None]

方法2:手动筛选参与计算的可训练参数

针对当前场景,偏置参数未参与loss2的计算,可只提取模型的权重参数(不含偏置)计算梯度:

# 筛选所有线性层的weight参数(可训练且参与当前loss计算)
target_params = []
for module in model:
    if isinstance(module, nn.Linear):
        target_params.append(module.weight)

# 仅对筛选后的参数计算梯度
d_loss_params = grad(loss, target_params, retain_graph=True)

若模型结构复杂,也可通过named_parameters()筛选:

target_params = [param for name, param in model.named_parameters() if 'weight' in name]
d_loss_params = grad(loss, target_params, retain_graph=True)

注意事项

  • 若模型包含其他类型可训练参数(如BatchNorm的gamma/beta),需根据实际计算逻辑判断是否参与loss的计算图,再调整筛选规则。
  • allow_unused=True是通用解决方案,适合不确定哪些参数会参与计算的场景;手动筛选则更高效,适合明确知道有用参数的场景。

内容的提问来源于stack exchange,提问作者user2978125

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:03:27