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

PyTorch控制问题训练中出现原地操作错误求助

问题:PyTorch训练控制问题神经网络时的原地操作错误

错误信息

RuntimeError: 梯度计算所需的某个变量被原地操作修改了:[torch.cuda.FloatTensor [32, 4]],它是AsStridedBackward0的输出0,当前版本为2;预期版本为1。提示:回溯信息上方会显示计算梯度失败的操作。相关变量是在那里或之后的某处被修改的。祝你好运!

完整代码

导入与配置

# SOME IMPORTS
import torch
import torch.autograd as autograd  
from torch import Tensor               
import torch.nn as nn                   
import torch.optim as optim       

# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')


# PARAMETERS OF THE PROBLEM
layers = [4, 32, 32, 4]  # Layers of the NN
steps = 10000  # Simulation steps
train_step = 1  # 每train_step步训练一次NN
lr = 1e-3  # 学习率

网络定义

# 简单前馈网络定义

class FCN(nn.Module):
    
    def __init__(self,layers):
        super(FCN, self).__init__() # 调用父类的__init__方法
         
        self.linears = []
        for i in range(len(layers)-2):
            self.linears.append(
                nn.Linear(layers[i], layers[i+1])
            )
            self.linears.append(
                nn.ReLU()
            )
            
        self.linears.append(
                nn.Linear(layers[-2], layers[-1])
        )
        
        self.linear_stack = nn.Sequential(*self.linears)
            
    # 前向传播
    def forward(self,x):
        
        out = self.linear_stack(x)

        return out

模型初始化

model = FCN(layers)
model.to(device)
params = list(model.parameters())
optimizer = torch.optim.Adam(model.parameters(),lr=lr,amsgrad=False)

损失与模拟函数

def simulate(state_old, model):
    state_new = model(state_old)
    return state_new

def lossNN(state_old,state_new, model):
    error = torch.sum( (state_old-state_new)**2 )
    return error

训练代码(原报错版本)

torch.autograd.set_detect_anomaly(True)

state_old = torch.Tensor([0.01, 0.01, 0.5, 0.1]).to(device)

for i in range(steps):
    state_new = simulate(state_old, model)
    
    if i%train_step == 0:
        optimizer.zero_grad()
        loss = lossNN(state_old, state_new, model)
        loss.backward(retain_graph=True)
        optimizer.step()
        
    state_old = state_new
    
    
    if (i%1000)==0:
        print(loss)
        print(state_new)

问题原因与解决方法

核心原因

  1. retain_graph=True 强制保留了过时的计算图,后续optimizer.step()更新模型参数后,旧计算图引用的参数版本与当前版本不匹配
  2. state_old = state_new 直接赋值让state_old持续关联之前的计算图,梯度计算时出现变量版本冲突

修正步骤

  1. 移除retain_graph=True:单次训练不需要保留计算图,反向传播后计算图会自动释放
  2. 用detach()断开计算图:将state_old = state_new改为state_old = state_new.detach(),让新的输入张量不关联之前的梯度信息

修正后的训练代码

torch.autograd.set_detect_anomaly(True)

state_old = torch.Tensor([0.01, 0.01, 0.5, 0.1]).to(device)

for i in range(steps):
    state_new = simulate(state_old, model)
    
    if i%train_step == 0:
        optimizer.zero_grad()
        loss = lossNN(state_old, state_new, model)
        loss.backward()  # 移除不必要的retain_graph=True
        optimizer.step()
        
    state_old = state_new.detach()  # 断开计算图,避免梯度链混乱
    
    if (i%1000)==0:
        print(loss)
        print(state_new)

额外说明

  • detach()返回无梯度的张量副本,适合控制问题的状态传递场景,因为状态迭代不需要追溯历史梯度
  • 若需保留梯度(如递归训练),可改用state_new.clone(),但当前场景detach()更高效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 02:50:28