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

torchdiffeq自适应求解器激活及步长未变化问题求助

问题修复:torchdiffeq自适应求解器步长无变化的问题

问题原因

你的代码存在两个核心问题:

  • ODE函数定义不符合要求:odefunc未使用状态变量z,当前定义的是仅依赖t的函数(dz/dt = f(t)),这类积分问题误差极低,自适应求解器会自动采用最大步长,导致输出结果和精确解几乎完全重合,让你误以为步长没有自适应调整。
  • 向量场绘制错误:绘制向量场时传入初始值z0而非网格点的Y值,无法正确反映ODE的变化趋势。

修复后的代码

以下是调整后的代码,我们将ODE修改为依赖状态变量的形式,修正向量场绘制逻辑,并添加了查看自适应求解器步长的选项:

!pip install torchdiffeq
import numpy as np
import torch
from torchdiffeq import odeint
from matplotlib import pyplot as plt

# 定义依赖状态变量z的ODE:dz/dt = -z + (-2*t³ + 12*t² -20t +8.5)
def odefunc(t, z):
    return -z + (-2*t**3 + 12*t**2 - 20*t + 8.5)

# 对应的精确解(齐次解+特解)
def exact_solution(t, z0):
    homogeneous = z0 * torch.exp(-t)
    particular = -0.5*t**4 + 4*t**3 - 10*t**2 + 8.5*t + 1 - torch.exp(-t)
    return homogeneous + particular

# 初始条件
z0 = torch.tensor([1.0])

# 求解时间点
t = torch.linspace(0., 4., 9)

# 固定步长求解(欧拉法)
z_fixed = odeint(odefunc, z0, t, method='euler')

# 自适应求解器(dopri5),添加options记录步长信息
options = {'record_steps': True}
z_adaptive, solver_info = odeint(odefunc, z0, t, method='dopri5', options=options)

# 打印自适应求解器实际使用的步长序列
print("自适应求解器实际使用的步长序列:")
print(solver_info['step_size'])

# 计算精确解
exact_z = exact_solution(t, z0)

# 绘制向量场(修正逻辑:传入网格点的Y值)
nx, ny = .25, .4
x = np.arange(0, 4.2, nx)
y = np.arange(0, 8.2, ny)
X, Y = np.meshgrid(x, y)

# 转换为张量计算导数
X_tensor = torch.tensor(X, dtype=torch.float32)
Y_tensor = torch.tensor(Y, dtype=torch.float32)
dy = odefunc(X_tensor, Y_tensor).numpy()
dx = np.ones(dy.shape)

# 归一化向量
dyu = dy / np.sqrt(dx**2 + dy**2)
dxu = dx / np.sqrt(dx**2 + dy**2)

plt.quiver(X, Y, dxu, dyu, color='grey')
plt.scatter([], [], marker=r'$\longrightarrow$', c="grey", s=200, label="向量场")

# 绘制结果对比
plt.plot(t.numpy(), z_fixed.numpy(), marker='o', label='欧拉法(固定步长)')
plt.plot(t.numpy(), z_adaptive.numpy(), marker='o', label='Dopri5(自适应步长)')
plt.plot(t.numpy(), exact_z.numpy(), label='精确解')
plt.xlabel('t')
plt.ylabel('z(t)')
plt.title('数值解与精确解对比')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.grid(True)
plt.show()

修复效果说明

  1. 自适应步长可见:通过options={'record_steps': True}可获取求解器实际使用的步长序列,能看到步长会根据ODE的变化自动调整(导数变化剧烈的区间步长会缩小)。
  2. 求解器差异明显:修改后的ODE依赖状态变量,欧拉法的误差会明显大于自适应求解器,图中能清晰看到两者的差异。
  3. 向量场正确:修正后的向量场能准确反映ODE在不同(t,z)点的变化趋势。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:15:59