PyTorch手动实现极小化器迭代时q.grad为None报错如何解决
PyTorch自定义极小化器梯度报错解决方案
你的推测完全正确,直接执行q = q - eta * q.grad赋值操作后,新的q会变成计算图中的普通中间节点,不再是叶子节点,因此第二次迭代反向传播后无法获取梯度值,才会抛出float和NoneType无法相乘的报错。
方案1:手动实现梯度下降(无需调用内置优化器)
需要满足三个核心要求:
- 初始化q时必须指定
requires_grad=True开启梯度追踪 - 参数更新操作要放在
torch.no_grad()上下文内执行,避免更新逻辑被计入计算图 - 每次迭代反向传播前要清空上一轮累加的梯度
import torch import torch.nn.functional as F # 初始化q时开启梯度追踪,替换为你的实际初始值 q = torch.tensor([1.0, 2.0], dtype=torch.float32, requires_grad=True) eta = 0.01 v = # 替换为你的输入张量 v_target = # 替换为你的目标张量 for i in range(10): print('i =', i, ' q =', q) v_trans = transform_dq(v, q) loss = F.mse_loss(v_trans, v_target) # 清空上一轮梯度 if q.grad is not None: q.grad.zero_() # 反向传播计算梯度 loss.backward() # 关闭梯度计算后更新参数,用inplace操作保留q的叶子节点属性 with torch.no_grad(): q -= eta * q.grad print('Final q = ', q)
方案2:使用PyTorch内置SGD优化器(更稳定不易出错)
直接调用官方封装的优化器逻辑,自动处理梯度清空、参数更新的细节:
import torch import torch.nn.functional as F # 初始化q时开启梯度追踪,替换为你的实际初始值 q = torch.tensor([1.0, 2.0], dtype=torch.float32, requires_grad=True) eta = 0.01 v = # 替换为你的输入张量 v_target = # 替换为你的目标张量 optimizer = torch.optim.SGD([q], lr=eta) for i in range(10): print('i =', i, ' q =', q) v_trans = transform_dq(v, q) loss = F.mse_loss(v_trans, v_target) # 清空梯度 optimizer.zero_grad() # 反向传播 loss.backward() # 更新参数 optimizer.step() print('Final q = ', q)
两种方案都可以保证q始终是计算图的叶子节点,每次迭代都能正常获取梯度值,不会再出现梯度为None的报错。
内容的提问来源于stack exchange,提问作者Notin_sensus
相关产品推荐
相关产品推荐

