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

PyTorch自动求导计算报TypeError,求修复方案

修复PyTorch自动求导中的TypeError: 'NoneType' object is not subscriptable错误

问题场景

在使用PyTorch对Burgers方程的解执行自动求导计算时,触发如下错误:

TypeError: 'NoneType' object is not subscriptable

相关代码如下:

自动求导代码

import torch
import numpy as np

x2 = torch.tensor(x, requires_grad=True)
t2 = torch.tensor(t, requires_grad=True)
def mr():
    for k in range(n):
        z01 = solve_burgers(torch.tensor([x2[k]]), 0.25, 0.01/np.pi)[0]
        z01.backward(retain_graph=True)
        u_xr = x2.grad[k]
        u_tr = t2.grad[k]
    return u_xr, u_tr, u_xxr

Burgers方程求解函数

from scipy.integrate import quad

def solve_burgers(X, t, nu):
    def f(y):
        return np.exp(-np.cos(np.pi * y) / (2 * np.pi * nu))
    def g(y):
        return np.exp(-(y**2) / (4 * nu * t))
    def fun(eta):
        return torch.sin(torch.pi * (x - eta)) * f(x - eta) * g(eta)
    def fun1(eta):
        return f(x - eta) * g(eta)
    U = torch.zeros_like(X)
    for i in range(len(X)):
        x = X[[[i]]]
        uxt = -quad(fun, -torch.inf, torch.inf)[0]
        uxt2 = torch.tensor(uxt, requires_grad=True)
        uxt30 = quad(fun1, -np.inf, np.inf)[0]
        uxt3 = torch.tensor(uxt30, requires_grad=True)
        U[i] = uxt2 / uxt3
    return U

错误根源与修复方案

错误核心原因

  1. t2从未被传入solve_burgers函数参与计算,导致t2.grad始终为None,执行t2.grad[k]时触发下标访问错误。
  2. solve_burgers中大量混用numpy与PyTorch运算,且手动用torch.tensor包装积分结果,直接切断了计算图,导致x2.grad也可能为None。
  3. SciPy的quad函数不支持PyTorch张量的自动求导,无法生成有效的计算图链路。

具体修复步骤

1. 让t2参与计算图传递

  • 修改solve_burgers的g(y)函数,用PyTorch运算替代numpy:
    def g(y):
        return torch.exp(-(y**2) / (4 * nu * t))  # 替换np.exp为torch.exp,确保t是PyTorch张量
    
  • 调用solve_burgers时传入t2而非固定数值:
    z01 = solve_burgers(torch.tensor([x2[k]]), t2, 0.01/np.pi)[0]
    

2. 修复计算图断裂问题

  • 将solve_burgers中所有numpy函数替换为PyTorch对应函数,确保计算链路完全在PyTorch中:
    def f(y):
        return torch.exp(-torch.cos(torch.pi * y) / (2 * torch.pi * nu))  # 替换np.cos、np.exp
    
  • 移除手动创建uxt2、uxt3的代码,直接使用积分结果(需替换SciPy的quad为PyTorch兼容的积分方式)。例如用数值采样+梯形积分替代:
    def solve_burgers(X, t, nu):
        def f(y):
            return torch.exp(-torch.cos(torch.pi * y) / (2 * torch.pi * nu))
        def g(y):
            return torch.exp(-(y**2) / (4 * nu * t))
        def fun(eta):
            return torch.sin(torch.pi * (x - eta)) * f(x - eta) * g(eta)
        def fun1(eta):
            return f(x - eta) * g(eta)
        
        U = torch.zeros_like(X)
        # 用数值采样近似积分,范围和点数可根据精度调整
        eta_samples = torch.linspace(-10, 10, 10000, requires_grad=False)
        d_eta = eta_samples[1] - eta_samples[0]
        
        for i in range(len(X)):
            x = X[[[i]]]
            # 梯形法数值积分
            uxt = -torch.trapz(fun(eta_samples), eta_samples)
            uxt30 = torch.trapz(fun1(eta_samples), eta_samples)
            U[i] = uxt / uxt30
        return U
    

3. 正确管理梯度累积

每次调用backward前清空梯度,避免累积导致的错误:

def mr():
    # 初始化梯度为0
    x2.grad.zero_()
    t2.grad.zero_()
    u_xr_list = []
    u_tr_list = []
    for k in range(n):
        z01 = solve_burgers(torch.tensor([x2[k]]), t2, 0.01/np.pi)[0]
        z01.backward(retain_graph=True)
        u_xr_list.append(x2.grad[k].item())
        u_tr_list.append(t2.grad[k].item())
        # 循环后清空梯度,避免下一次计算时累积
        x2.grad.zero_()
        t2.grad.zero_()
    # 若需要返回张量,可转换为torch.tensor
    return torch.tensor(u_xr_list), torch.tensor(u_tr_list), u_xxr  # 需补充u_xxr的计算逻辑

4. 补充u_xxr的定义

原代码中mr函数返回u_xxr但未实现,需补充二阶导数的计算逻辑(例如对一阶导数再执行一次自动求导),否则会引发新的未定义错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:24:54