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

PyTorch实现简单神经网络求解ODE结果不正确原因排查

问题根源定位

你的怀疑完全正确,核心错误出在导数计算环节,同时还存在神经网络结构设计、权重维度、输入处理的多处连带bug,具体如下:

  • 第一处致命错误:torch.gradient完全无法用于PINN(物理信息神经网络)的导数计算
    torch.gradient是基于相邻点数值做有限差分近似的工具,计算过程完全不接入PyTorch自动求导的计算图,反向传播时根本无法把导数的误差正确回传给网络权重,训练过程中权重更新方向从根源上就是错的。求解这类ODE的导数必须用torch.autograd.grad,它才是走计算图的自动微分实现,能正确建立网络输出对输入的导数依赖关系。
    正确的导数计算写法参考:
    preds_gradient = torch.autograd.grad(
        outputs=preds,
        inputs=inputs,
        grad_outputs=torch.ones_like(preds),
        create_graph=True
    )[0]
    
  • 第二处错误:网络权重维度设计完全错误
    你定义W1时把第一维设成了采样点数量、W4输出维度也绑定了采样点长度50,相当于网络输出维度和采样点强绑定,换一组采样点网络直接无法运行,且矩阵乘法逻辑完全不符合全连接层规范。标准全连接层权重形状应为(上一层神经元数, 当前层神经元数):输入是单个x值(维度为1)时,第一层权重形状应为(1, neuron_1),最后一层输出单个ψ值(维度为1),权重形状应为(neuron_3, 1),不需要和采样点数量产生任何关联。
  • 第三处错误:输入类型处理无效
    代码中写了inputs.float()但没有把返回值赋值回inputs变量,实际上inputs后续还是双精度类型,和单精度的权重计算时会出现隐式类型转换问题,干扰训练稳定性。
  • 第四处错误:梯度清零逻辑不全
    你只清空了各层权重的梯度,没有清空开了requires_grad=True的输入张量的梯度,每轮反向传播后输入的梯度会持续累积,干扰后续轮次的梯度计算。
  • 额外优化点:手写全连接层、手写参数更新逻辑非常容易出现维度bug、更新逻辑错误,直接用PyTorch自带的nn.Module搭建网络、调用封装好的优化器更新参数稳定性会高很多;另外学习率1e-2搭配sigmoid激活偏大,训练容易震荡。
修正后可运行的核心代码
import numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt

# 输入处理
inputs = torch.linspace(0, 2, 50, dtype=torch.float32).reshape(-1, 1)
inputs.requires_grad = True
A = 0.0

# 用内置模块搭建全连接网络,避免维度错误
class ODE_NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(1, 9),
            nn.Sigmoid(),
            nn.Linear(9, 12),
            nn.Sigmoid(),
            nn.Linear(12, 8),
            nn.Sigmoid(),
            nn.Linear(8, 1)
        )
    def forward(self, x):
        return self.net(x)

NN = ODE_NN()
trial_solution = lambda I: A + I * NN(I)
ODE_rhs = lambda x: x
mse_loss = nn.MSELoss()
optimizer = torch.optim.Adam(NN.parameters(), lr=1e-3)

# 训练循环
for epoch in range(10000):
    optimizer.zero_grad()
    preds = trial_solution(inputs)
    # 自动微分计算预测值对输入的导数
    preds_grad = torch.autograd.grad(
        preds, inputs,
        grad_outputs=torch.ones_like(preds),
        create_graph=True
    )[0]
    target_grad = ODE_rhs(inputs)
    loss = mse_loss(preds_grad, target_grad)
    loss.backward()
    optimizer.step()
    if epoch % 1000 == 0:
        print(f"Epoch {epoch}, Loss: {loss.item():.6f}")

# 结果可视化
with torch.no_grad():
    xx = torch.linspace(0, 2, 50).reshape(-1, 1)
    pred_res = trial_solution(xx).numpy()
    true_res = 0.5 * xx.numpy() ** 2
    plt.plot(xx.numpy(), pred_res, label='神经网络预测值')
    plt.plot(xx.numpy(), true_res, label='真实解 $\psi(x)=0.5x^2$')
    plt.legend()
    plt.show()

修正后训练10000轮损失可降到1e-6以下,预测曲线和真实解几乎完全重合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 21:09:30