
1. 先聊透所谓“用 AI 替代方程求解”到底替代的是什么做计算仿真这些年最常被问的一句话是“现在 AI 这么热能不能直接把方程求解器替换掉”我的回答通常很直接看你手里是什么方程、要算几次、精度要求多高。不是打太极是因为我确实见过两种极端有人在流体仿真项目里用神经网络把参数扫描耗时从几小时压到几秒爽得不行也有人非要让 AI 解一个毫秒级就能算完的线性方程结果折腾两周精度还不如传统求解器。“用 AI 替代方程求解”这句话严格来说容易误导人。AI 不是把 Newton 迭代法、有限差分、有限元这些老伙计一脚踢开而是用神经网络去逼近“方程的解”或“从参数到解的映射”。以目前最常见的物理信息神经网络PINNPhysics-Informed Neural Network为例你把偏微分方程的控制方程残差、边界条件和初始条件直接写进损失函数让网络在训练中自己去“学会”满足这些物理约束。训练完以后输入一个坐标网络立刻输出这个坐标上的解不需要再去剖分网格、组装刚度矩阵、迭代求解。另一种更接近“替代求解器”思路的是算子学习Operator Learning。它不求解单个方程而是学习一个算子给定不同的方程系数、边界条件或源项网络直接输出对应的解场。这相当于把“求解一遍方程”这件事编码进了网络权重里换一个新参数前向传播一次就能拿到结果。所以我更愿意把“替代”理解为“在特定场景下替代传统求解器的重复劳动”。它替代的不是数学本身而是人力、时间、网格重构和反复求解的成本。1.1 传统求解器哪里不好传统数值方法本身很成熟误差估计、稳定性分析都有一套完善理论。但工程中真正不舒服的地方在于重复求解。举个例子你要做一个结构优化每次改变一个几何参数有限元模型就要重新划分网格、重新装配矩阵、重新求解。单次求解可能只要 30 秒但优化算法要跑几百次一晚上就没了。更难受的是反问题场景从观测数据反推方程系数比如根据温度分布推断热源位置每迭代一步都要调用一次正问题求解器整个反演过程慢到让人怀疑人生。还有一类问题传统方法几乎无解——高维方程。当空间维度超过 4、5 维网格数量是指数增长的有限差分、有限元直接爆掉。神经网络虽然没有严格摆脱维度诅咒但在处理某些高维问题上表现出了惊人的能力这也是这两年很多人涌进来研究 PINN 的原因之一。1.2 AI 解方程的技术路线大致分两类第一类是物理驱动损失函数里主要包含方程残差比如 PINN、Deep Ritz、WAN 等。这类方法不需要大量标签数据理论上只要方程形式确定就能训练出满足物理规律的解。优点是数据需求少缺点是对训练技巧要求高多目标损失很难平衡。第二类是数据驱动 / 混合驱动用传统求解器生成一批“参数-解”样本训练神经网络学习这个映射关系代表方法就是 DeepONet、Fourier Neural OperatorFNO。这类方法本质是监督学习训练数据怎么来很关键。数据质量高效果就惊艳数据覆盖不足换个工况就翻车。实操中两类经常混着用先用传统求解器生成少量样本再用物理损失做约束既保证泛化又降低对数据量的依赖。1.3 一句话总结适用场景如果这个方程你只需要解一次或者解起来几百毫秒就完事别用 AI。如果这个方程要解一百次、一千次参数一变就要重新跑或边界条件永远在变这时候 AI 才值得考虑。这个判断标准虽然粗暴但非常实用。我见过太多人把“AI 替代方程求解”当成了万能锤子什么钉子都想砸结果砸坏了手。下一章我展开说说什么场景才是真正值得上的。2. 哪些方程真正适合交给 AI别拿导弹打蚊子先泼盆冷水系数不变的线性 Poisson 方程、小规模线性方程组、只需要算一次的稳态热传导这些用传统求解器又快又准。你说你用 PINN 解一个二维 Laplace 方程精度好不容易到 1e-3传统有限差分法 0.1 秒就能到 1e-8这种项目“为了 AI 而 AI”纯属给自己找罪受。那什么情况真正适合我把自己的筛选标准列出来。2.1 适合交给 AI 的三种场景场景一参数化仿真与实时预测。这是最肥的一块应用。方程本身不变但系数、边界条件、源项在不停变化比如多个设计方案的流场预测、不同工况下的温度分布。传统流程是每个参数点跑一次 CFD / 有限元AI 的做法是训练一个代理模型输入参数直接输出解场。这个场景下前期花半天训练网络后期每次预测只需毫秒级前向传播收益极其明显。场景二反问题求解。从少数观测点反推方程中的未知参数或未知部分。传统反演算法需要反复调用正问题求解器每一轮迭代都是一次完整数值求解。用 AI 替代时通常有两种思路一种是直接把参数映射到解然后通过梯度下降反推输入另一种是训练一个端到端的反演网络。这里 AI 的核心价值不是取代正问题求解器而是绕开正问题求解器频繁调用的瓶颈。场景三高维方程或复杂几何上的近似求解。传统方法受限于网格生成成本三维复杂几何的网格划分可能就得花一天。PINN 不需要网格只需要在求解域内采样点几何越复杂、维度越高相对优势越明显。当然代价是收敛性和精度都很难保证。2.2 不适合的典型场景以下几类我基本不碰对精度要求到机器精度的问题。比如需要 1e-10 误差的线性系统AI 目前很难做到这么严格的误差控制。只有少量采样点且没有参考解的问题。PINN 虽然不需要标签但训练过程仍然需要验证没有参考解你很难判断网络是不是学到了一个“看着合理但其实不对”的解。实时性要求极高且计算资源受限的嵌入式场景。神经网络前向传播虽然快但也不是免费的。如果设备上连 GPU 都没有还不如一个 C 写的稀疏求解器来得实在。2.3 成本与收益的第一笔账我自己算过一笔账。一个典型的二维不可压缩流场仿真传统 CFD 单次求解约 10 分钟。你需要扫描 200 组参数总耗时约 33 小时。AI 方案先用传统求解器跑 30 组参数当训练数据耗时 5 小时训练神经网络 2 小时预测剩下 170 组参数每组 0.01 秒总耗时约 7 小时。总成本接近传统方案的 1/5而且后续再加新参数预测基本零成本。但如果只算一组参数传统方案 10 分钟搞定AI 方案至少要六七个小时那就完全不划算。所以先算清楚“求解次数”这笔账再决定要不要上 AI。这是我给所有咨询者的第一条建议。3. 主菜用 PINN 求解一维 Poisson 方程的完整实操下面进入最核心的部分。我用一个最简单但完整的一维 Poisson 方程来演示 PINN 的全部流程保证你看完能自己在 PyTorch 里跑起来。方程是这个-u(x) f(x), x in (0, 1) u(0) 0, u(1) 0取 f(x) π² sin(πx)精确解就是 u(x) sin(πx)。选这个例子是因为它简单、有解析解方便你验证网络学得对不对。3.1 PINN 的原理拆解PINN 的核心思想很直接神经网络本身是一个万能函数逼近器我们用网络 u_θ(x) 来表示方程的解。训练的时候不再把“预测值”和“标签”做比较而是把网络输出代入方程看它满足方程和边界条件的程度。具体来说定义两个损失项方程残差损失让网络输出关于输入的自动微分结果代回方程左边和零之间的均方误差越小说明越满足方程。边界条件损失让网络在 x0 和 x1 处的输出逼近 0。总损失就是这两项的加权和L λ_r * MSE( -u_θ(x) - f(x) ) λ_b * MSE( u_θ(0), u_θ(1) )在大部分场景下λ 取相等也能收敛但真正难调的问题里权重非常敏感这个后面再讲。为什么这样能行因为神经网络的训练本质是优化一个非凸目标函数而 PINN 通过把物理规律写进损失函数把“找解”变成了“找一组让物理残差最小的网络参数”。一旦训练收敛u_θ(x) 就会逼近真实解 u(x)。由于整个过程只依赖坐标点 x 而不需要网格处理复杂几何时很有优势。3.2 搭建网络与损失函数的核心代码下面是我常用的最小实现。网络结构很简单4 层全连接每层 50 个神经元激活函数用 tanh。import torch import torch.nn as nn import numpy as np # 1. 定义一个简单的 MLP class PINN(nn.Module): def __init__(self, layers[1, 50, 50, 50, 1]): super().__init__() self.activation nn.Tanh() self.linears nn.ModuleList() for i in range(len(layers) - 1): self.linears.append(nn.Linear(layers[i], layers[i 1])) # 初始化 nn.init.xavier_uniform_(self.linears[-1].weight) nn.init.zeros_(self.linears[-1].bias) def forward(self, x): for i, layer in enumerate(self.linears): x layer(x) if i len(self.linears) - 1: x self.activation(x) return x # 2. 定义损失函数 def pde_loss(model, x): x.requires_grad_(True) u model(x) # 一阶导数 du torch.autograd.grad(u, x, grad_outputstorch.ones_like(u), create_graphTrue)[0] # 二阶导数 d2u torch.autograd.grad(du, x, grad_outputstorch.ones_like(du), create_graphTrue)[0] # 方程-u pi^2 sin(pi x) f torch.pi**2 * torch.sin(torch.pi * x) residual -d2u - f return torch.mean(residual**2) def bc_loss(model): x_bc torch.tensor([[0.0], [1.0]], requires_gradTrue) u_bc model(x_bc) return torch.mean((u_bc - 0.0)**2) # 3. 训练 model PINN() optimizer torch.optim.Adam(model.parameters(), lr1e-3) # 在区间 (0,1) 内采样 200 个点作为配点 x_collocation torch.rand(200, 1) * 1.0 for epoch in range(20000): optimizer.zero_grad() loss pde_loss(model, x_collocation) bc_loss(model) loss.backward() optimizer.step() if epoch % 2000 0: print(fEpoch {epoch}, Loss {loss.item():.6e})有一点必须提醒上面的x_collocation是我在训练前一次性采好的训练中每个 epoch 都用同一批点。这在小问题上没问题但一旦遇到边界层、激波这类局部剧烈变化的解固定采样点会导致结果在未采样的区域彻底跑偏。后面会讲自适应重采样怎么做。3.3 训练参数与收敛技巧网络层数和宽度不是越大越好。对于一维问题4 层 50 神经元已经非常够用再加深反而容易出现梯度消失。激活函数我几乎只用tanh因为 ReLU 虽然在很多任务里表现好但它的二阶导是 0除了不可导点直接用它算 PDE 残差会丢失大量物理信息训练很难收敛。优化器方面先用 Adam 跑个几千步把损失压下来再切到 L-BFGS 做精细收敛这是一种被很多人验证过的组合。L-BFGS 对光滑损失函数收敛很快而且不需要手动调学习率。我常用的策略是 Adam 跑 10000 步接着 L-BFGS 跑 200 步# 先 Adam 粗调 for epoch in range(10000): optimizer.zero_grad() loss pde_loss(model, x_collocation) bc_loss(model) loss.backward() optimizer.step() # 切 L-BFGS 精调 optimizer torch.optim.LBFGS(model.parameters(), lr1.0, max_iter200) def closure(): optimizer.zero_grad() loss pde_loss(model, x_collocation) bc_loss(model) loss.backward() return loss optimizer.step(closure)这个组合在多数 PINN 问题上都能比单一 Adam 快一个数量级。3.4 结果验证别只看训练损失很多新手看到训练损失降到 1e-6 就欢呼胜利结果拿网络去求某一坐标的解一对比精确解误差大到离谱。为什么因为 PINN 的损失函数是隐式约束不像分类任务的交叉熵那样直接反映精度。训练损失低只说明网络在采样点上满足方程和边界条件不代表它在没采样的位置也对。我一般做三步验证在区间内重新生成一组密集的均匀测试点比如 1000 个不要用训练时的采点。计算网络输出与解析解的 L2 相对误差公式是||u_pred - u_exact|| / ||u_exact||。画一下残差分布看看是不是在某些位置突然暴涨。如果残差集中在边界附近多半是边界层没学好。对于一维 Poisson 这个例子训练充分后 L2 相对误差能轻松到 1e-4 以下。如果你发现到了 1e-2 就再也降不下去不是网络不行而是训练没收敛或采样不合格。4. 进阶让 AI 从“求解单个方程”变成“替代一个求解器”PINN 解决的是“给定方程和边界条件求一个解”的问题。但在真正的工程环境里我们要面对的是同一类方程、不断变化的参数。每次参数变化都重新训练一次 PINN本质上没有省多少时间因为训练成本在那摆着。所以进阶思路是训练一个模型让它能够针对一系列不同参数直接输出解这就叫算子学习。这一部分我用比较容易理解的方式讲清楚。4.1 算子学习的基本想法传统求解器是一个黑盒子输入方程的系数函数、边界条件、几何信息输出解函数。我们可以把“求解器”本身看成一个算子 G把输入函数映射成输出函数。DeepONet 的思路是用两个子网络分别编码“输入函数在若干点的取值”和“待预测解的坐标”再把两个子网络的输出拼接起来得到该坐标上的解。这样训练好之后换一个新的输入函数不用重新训练一次前向传播就能得到整个解场。FNO 的思路更激进直接在 Fourier 空间做卷积把函数离散成网格后通过快速傅里叶变换在频域学习映射关系。它天然适合均匀网格上的数据在流体和气象问题中表现很出色。这两个方向各有各的受众。DeepONet 更灵活对网格要求低FNO 在均匀网格上精度高、训练快但换几何、换网格就比较麻烦。如果你只是想快速上手我建议先尝试 DeepONet因为它实现起来更直观。4.2 DeepONet 与 FNO 怎么选我把两者的核心差异列成一张表方便你决策对比项DeepONetFNO核心机制两个子网络编码函数输入与输出坐标Fourier 域卷积对网格的依赖低可以在任意点上做预测高训练数据必须在统一网格上几何适应性较强较弱换几何基本要重训实现难度相对简单需要处理傅里叶变换和频域参数典型应用多物理场、变系数方程流体模拟、气象预报从我的经验看工程上很多问题属于“边界复杂、参数变化、参考解很难大量生成”这种场景 DeepONet 更稳妥。数据量充足且算力充沛想要跑大尺度流场FNO 的上限更高。4.3 一个最小可行的算子学习流程不管用哪种方法流程骨架是一样的用传统求解器生成数据集准备 M 组不同的方程参数比如热传导方程的热源位置和强度不同用有限差分或有限元求出对应的解场。数据预处理把参数函数在采样点上的值归一化解场也归一化划分训练集和测试集。训练网络输入参数函数表示和预测坐标输出解值用预测解和真实解的均方误差做损失。验证在测试集上比较不同参数下的解场误差重点看泛化能力。这里有个容易被忽略的点训练数据必须覆盖参数空间的关键区域。如果你的参数变化范围是 [0, 10]但训练样本只集中在 [0, 3]模型对后半段的预测基本就是瞎猜。生成数据时最好用 Sobol 序列或拉丁超立方采样保证参数空间被均匀覆盖而不是简单随机抽。5. 翻车现场我在实际求解中反复踩过的坑这部分是全文含金量最高的地方。我踩过的坑你可以直接拿来当避雷指南。5.1 损失函数权重怎么调PINN 的损失函数由方程残差、边界条件、初始条件等多部分组成这些 loss 的分量级可能差出好几个数量级。如果网络权重一视同仁边界条件很容易被方程残差“淹没”最终解满足方程但完全不符合边界。举个真实例子我之前在某个传热模拟中初始条件损失是 1e-2 量级方程残差是 1e-5 量级。两边直接相加初始条件几乎不起作用结果训练出来温度场完全偏离物理事实。解决办法是给每一项乘一个权重系数比如边界条件和方程残差的权重设成 10:1。常用的权重调节思路有两种手动试错先让每项损失归一化到同一量级再根据效果微调。自适应加权用梯度幅度或不确定性来动态调整权重。这部分实现稍复杂但对复杂问题提升明显。我建议新手先手动把每项损失输出到日志里观察各自的量级然后手动配平。在确认基础逻辑没问题之前先别上花哨的自适应算法。5.2 为什么有时训练很顺结果却是错的这种情况最可怕损失曲线平平稳稳往下掉没有任何报错但验证的时候发现结果完全不对。我遇到过两类典型原因第一类是采样点固定导致的盲区。PINN 只在训练采过的配点上计算残差如果这些点没有覆盖某个区域比如高梯度区、间断附近网络在那个区域就会“自由发挥”。解决方法每训练一定步数后重新根据当前残差分布采样残差大的地方多撒点这就是残差自适应重采样。一维问题很容易实现高维问题可以用贪婪采样策略。第二类是自动微分在边界处失真。当边界点本身作为输入参与训练而网络输出在边界处强行被拉到某个值会在边界附近产生一个很陡的过渡层。为了满足边界条件网络倾向于在边界区域快速扭曲导致导数在边界处异常。缓解方法是额外在边界附近加密采样点或者构造一个“硬约束”的网络输出让边界条件自动满足而不是通过损失函数软约束。所谓硬约束就是通过网络输出乘以一个在边界上等于 0 的因子加上边界函数来强制满足这样边界条件就不需要参与损失优化了。5.3 常见问题速查表把最容易出问题的几个点整理成一张表遇到问题直接查阅。现象可能原因处理办法损失下降缓慢学习率太低 / 网络太深调大学习率或减少层数训练损失低但测试误差大采样点分布不均匀使用自适应重采样解在边界附近剧烈振荡边界条件权重太弱加大边界损失权重或改成硬约束梯度爆炸二阶自动微分计算量大使用梯度裁剪或用 L-BFGS训练到后期不收敛Adam 学习率退化不足切换 L-BFGS 或做学习率衰减激活函数用了 ReLU二阶导信息丢失换成 tanh 或 swish我最想说的一点是遇到 PINN 不收敛别急着换网络结构。先把问题简化、把数据归一化、把损失权重配平大多数问题都能解决。有些同学一来就上 10 层残差网络、几百种采样策略最后反而是最基础的配置跑通了。6. 收尾几句掏心窝子的话如果让我给一条最朴素的建议别急着把现有求解器扔掉。我在多个模拟项目里最稳妥的做法是先用传统数值方法把高质量参考解算出来再用神经网络去拟合从参数到解的映射部署阶段 AI 负责实时快速预测关键工况回到传统求解器做校核。这套混合流程远比“全盘 AI 替代”靠谱既拿到速度又不至于把精度安全完全交给一个黑盒。另外做 AI 解方程一定要养成记录实验日志的习惯。我曾经把同一套 PINN 代码跑出两个截然不同的结果最后发现是随机种子不同导致初始化不一样。神经网络本身是随机算法不同初始化可能收敛到不同的局部最优而这个局部最优对应的“解”可能差得十万八千里。所以每个实验固定随机种子记录采样方式、网络结构、损失权重否则出了问题根本无法定位。最后分享一个小技巧任何 AI 解方程的项目都要先找一个有解析解或高精度数值解的简单测试用例把整套流程验证通过后再上真实问题。这就像写代码先写单元测试一样能在前期拦截掉 80% 的隐藏 bug。别嫌简单用例浪费时间它是我见过最能救命的一步。