系列 · PDE × 机器学习 · 第 2 篇

偏微分方程与机器学习(二):神经算子理论

神经算子全景:从函数空间基础到 Chen-Chen 通用逼近定理,再到 DeepONet 与 FNO 的架构、分辨率不变性、误差界与可运行实现。

经典 PDE 求解器,如有限差分、有限元、谱方法,本质上是函数——输入初始条件和参数,输出解;PINN 本质上也是面向单实例的函数:一旦初始条件改变(例如机翼来流速度变化或预报中传感器读数微小偏移),就需要重新训练。

神经算子彻底改写这套规则。它学习的是解算子本身:输入为函数(如初始条件、系数场、源项),输出同样是函数(如某一时刻的解、目标区域上的物理场)。仅需用数千组离线样本训练一次,面对新实例时,仅需一次前向传播即可完成推理:无需重新划分网格,无需重复优化,整个过程也不依赖传统 PDE 求解器。

本文深入梳理这项技术。先讲让“在函数空间间学映射”有意义的泛函分析框架,再拆解两类主流架构:DeepONet——按 Chen–Chen 通用逼近定理把算子拆成 branch 和 trunk;Fourier Neural Operator (FNO)——在频域做可学习全局卷积。途中讨论神经算子为何分辨率不变,理论误差界多强,以及每种架构失效的边界在哪。

算子学习:把整个输入函数空间映射到整个输出函数空间。
图 1. 神经算子学习两个无限维函数空间之间的映射。左边每条蓝色曲线是一个输入(如初始条件);右边每条绿色曲线是对应的输出(如 $T$ 时刻的解)。算子 $\mathcal{G}_\theta$ 训练一次,可对任意新输入复用。
偏微分方程与机器学习(二):神经算子理论 — 章节概览图


经典的 PDE 求解器——有限差分、有限元、谱方法——本质上是一个函数:给定初始条件和参数,给出解。PINN 也是函数:初始条件一变(机翼来流速度变了,传感器读数偏了一点),整个网络就要重新训练一次。

神经算子彻底改写这个游戏。它学的不是某一个解,而是解算子本身:输入是函数(初始条件、系数场、源项),输出也是函数(某时刻的解、目标区域上的物理场)。一次离线训练,之后面对每个新实例只要一次前向传播——不再划网格,不再优化,整个传统 PDE 求解流程被绕开。

这篇文章我会先讲“在函数空间之间学映射”这件事在数学上怎么说得通,再拆解两类主流架构:DeepONet(按 Chen–Chen 通用逼近定理拆成 branch + trunk)和 Fourier Neural Operator (FNO)(在频域做可学习的全局卷积)。沿途会讨论它们为什么分辨率无关,理论误差界有多紧,以及各自在什么场景会失灵。

为什么需要算子,而不是更大的网络#

PINN 的天花板#

$$u_t + u\,u_x = \nu\,u_{xx},\qquad x\in[0,2\pi],\ t\in[0,T],$$ $$\mathcal{L}_{\mathrm{PINN}}(\theta) = \big\| \partial_t u_\theta + u_\theta\,\partial_x u_\theta - \nu\,\partial_{xx} u_\theta \big\|^2 + \big\|u_\theta(\cdot,0) - u_0 \big\|^2 .$$

注意 $u_0$ 显式出现在损失函数里。改 $u_0$ ,损失景观就变,优化器得重来。设计扫描一千个候选来流剖面,就得跑一千次训练。

算子学习的形式化#

$$\mathcal{G} : \mathcal{A} \to \mathcal{U},\qquad \mathcal{G}(u_0) = u(\cdot, T).$$ $$u(\cdot, T) \approx \mathcal{G}_\theta(a) \quad \text{(一次前向传播)}.$$

训练成本分摊到整个实例族——这正是算子学习的核心优势。

函数空间基础(最低限度)#

Banach、 Hilbert、 Sobolev——各自的意义#

$$C(K) \;=\; \{u:K\to\mathbb{R} \text{ 连续}\}, \quad \|u\|_\infty = \sup_{x\in K} |u(x)|,$$ $$L^p(\Omega) \;=\; \Big\{u:\Omega\to\mathbb{R} \;:\; \int_\Omega |u|^p < \infty\Big\}, \quad \|u\|_{L^p} = \Big(\int |u|^p\Big)^{1/p}.$$

Hilbert 空间是范数由内积诱导的 Banach 空间。内积提供角度、正交和投影,支撑傅里叶级数和谱分解。典型例子是 $L^2(\Omega)$ ,内积定义为 $\langle u, v\rangle = \int u\bar v$

Sobolev 空间 $H^s(\Omega)$ 不仅控制函数本身,还控制其阶数不超过 $s$ 的导数(在 $L^2$ 意义下)。 PDE 解通常位于某个 $H^s$ 中,参数 $s$ 表示光滑性。分辨率不变性的理论依据正在于此:函数越光滑,其傅里叶频谱衰减越快;因此截断高频模式所引入的误差通常很小。

为什么输入维度是“无限”#

CNN 处理 $256\times 256$ 图像时,实际看到的是 $\mathbb{R}^{65536}$ 中的一个向量。分辨率翻倍到 $512\times 512$ ,输入维度变化,模型失效。神经算子不同,它处理的是函数,仅因数值计算需要采样。架构设计必须保证:查询点 $y$ 处的预测与输入采样方式无关。这是算子学习区别于“读 PDE 解的 CNN”的关键约束。

Chen–Chen 定理:算子可以是两层网络#

1995 年, Chen 和 Chen 种下了算子学习的理论种子。

$$\sup_{u\in K_1,\,y\in K_2}\;\bigg|\,\mathcal{G}(u)(y) \;-\; \sum_{k=1}^{p} \underbrace{\sigma\!\Big(\textstyle\sum_{j=1}^m c_{kj}\,u(x_j) + \theta_k\Big)}_{=\,b_k(u)} \cdot \underbrace{\sigma(w_k\cdot y + \zeta_k)}_{=\,t_k(y)} \,\bigg| \;<\;\varepsilon.$$

这个定理有两点值得注意:

  1. 输入是函数,但网络只用有限采样 $u(x_1),\dots,u(x_m)$ $K_1$ 在一致拓扑下紧,说明有限网格足以捕捉函数类的所有成员。
  2. 输出分解为乘积 $b_k(u)\,t_k(y)$ 之和。 第一个因子只依赖 $u$ ,第二个只依赖 $y$ 。这正是 DeepONet 的形式。

Chen-Chen 定理:DeepONet 的存在性保证及误差结构。
图 2. 左: Chen–Chen 定理表明,任意连续算子 $\mathcal{G}: C(K_1)\to C(K_2)$ 都能用 $p$ 个秩一项 $b_k(u)\,t_k(y)$ 逼近到任意精度。右:误差分解示意图。神经算子的测试误差包括随网络宽度 $p$ 衰减的逼近项、随样本量 $N$ 衰减的统计项,以及不可消的噪声基底。

定理只证明了存在性,未提 $p$ 如何依赖 $\varepsilon$$\mathcal{G}$ 的光滑度或输入维度。 Lanthaler 等人 [2022] 和 Kovachki 等人 [2023] 对受限算子类给出了更精确的速率。渐近图景仍是经典的偏差–方差–噪声分解。

DeepONet: branch 和 trunk 的工程实现#

DeepONet (Lu 等人, 2019)是 Chen–Chen 定理的直接架构实现。两个网络分别计算两个因子:

  • Branch 网络 $b_\phi : \mathbb{R}^m \to \mathbb{R}^p$ 输入函数在 $m$ 个固定传感器位置的采样,输出系数向量 $b(u) = b_\phi(u(x_1),\dots,u(x_m))$
  • Trunk 网络 $t_\psi : \mathbb{R}^d \to \mathbb{R}^p$ 输入查询坐标 $y$ ,输出基函数向量 $t(y)$
$$\mathcal{G}_\theta(u)(y) \;=\; \sum_{k=1}^{p} b_k(u)\, t_k(y) \;+\; b_0.$$

DeepONet 架构:branch 编码输入函数,trunk 编码查询位置,内积得到该位置处的输出值。
图 3. DeepONet 把算子分解为 branch (上方,从 $m$ 个传感器采样编码输入函数)和 trunk (下方,编码查询坐标)。两者的内积重构出 $\mathcal{G}(u)(y)$ 。 trunk 起到学到的基 $\{t_k\}$ 的作用, branch 给出在该基下的系数 $\{b_k(u)\}$

这种分解可以从几个角度看,每个角度都揭示同一种结构:

  • 算子低秩分解: 对比紧算子奇异值分解 $\mathcal{G} = \sum_k \sigma_k \langle\cdot, e_k\rangle f_k$ : trunk 充当右奇异系, branch 吸收奇异值与对输入的内积。
  • 学到的基函数: trunk 输出 $\{t_k(\cdot)\}$ 构成输出域上的数据驱动基。它不像 Fourier 或 Chebyshev 基那样正交,但为手头算子量身定做。
  • 条件线性模型: 固定 $u$ 后,预测对 trunk 输出线性;对 $u$ 的非线性全藏在 branch 里。

实现时注意几个细节:

关注点杠杆
传感器位置$\{x_j\}$ 要能分辨最小尺度;周期问题用均匀网格,高维问题用 Latin hypercube 或 quasi-MC。
查询策略训练时每个输入随机采部分 $y$ 控显存;评估时用密集网格。
Trunk 正则trunk 最后一层小尺度初始化(如 $\mathcal{N}(0, 0.1)$ ),避免训练初期剧烈振荡。
多输出对向量值 $\mathcal{G}(u)\in\mathbb{R}^c$ ,共享 trunk、用 $c$ 个 branch 头,强制各分量共享空间基。

值得知道的变体: POD-DeepONet 用训练数据预计算的 POD 基代替学到的 trunk,只学 branch,收敛快但继承固定基缺点。Physics-informed DeepONet(Wang 等人, 2021)在损失里加 PDE 残差项,标注数据稀缺时很有用。 实现:一个极简的 DeepONet 模型
DeepONet 将算子分解为若干乘积项之和:其中分支网络(branch network)处理输入函数在传感器位置处的取值,主干网络(trunk network)则处理输出查询点的位置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import torch
import torch.nn as nn

class DeepONet(nn.Module):
    def __init__(self, n_sensors=64, branch_hidden=128, trunk_hidden=128, p=64):
        super().__init__()
        # 分支网络:将传感器处的输入函数值映射为 p 维编码
        self.branch = nn.Sequential(
            nn.Linear(n_sensors, branch_hidden), nn.ReLU(),
            nn.Linear(branch_hidden, branch_hidden), nn.ReLU(),
            nn.Linear(branch_hidden, p)
        )
        # 主干网络:将查询位置映射为 p 维编码
        self.trunk = nn.Sequential(
            nn.Linear(1, trunk_hidden), nn.ReLU(),
            nn.Linear(trunk_hidden, trunk_hidden), nn.ReLU(),
            nn.Linear(trunk_hidden, p)
        )
        self.bias = nn.Parameter(torch.zeros(1))

    def forward(self, u_sensors, y_query):
        # u_sensors: (batch, n_sensors) —— 输入函数在各传感器位置上的采样值
        # y_query: (batch, 1) —— 待预测的输出位置(查询点)
        b = self.branch(u_sensors)  # (batch, p)
        t = self.trunk(y_query)     # (batch, p)
        return (b * t).sum(dim=-1) + self.bias  # 计算内积并加上偏置项

n_sensors = 64
sensors = torch.linspace(0, 1, n_sensors)

n_train = 2000
coeffs = torch.randn(n_train, 5)
freqs = torch.arange(1, 6).float() * torch.pi
u_train = (coeffs.unsqueeze(-1) * torch.sin(freqs.unsqueeze(0).unsqueeze(-1) * sensors)).sum(dim=1)
y_query = torch.rand(n_train, 1)

model = DeepONet(n_sensors=n_sensors, p=64)
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
print(f"DeepONet 参数量:{sum(p.numel() for p in model.parameters()):,}")

DeepONet 的核心优势在于:它天然支持 非均匀分布的传感器位置任意输入/输出网格。相比之下,FNO 依赖快速傅里叶变换(FFT),必须要求输入数据位于规则均匀网格上。在气象站观测、地震传感器阵列等散点测量场景中,DeepONet 往往是更合适的选择。

Fourier 神经算子#

偏微分方程与机器学习(二):神经算子理论 — 章节小结图

DeepONet 在空间域分解算子为秩一项之和, FNO (Li 等人, 2020)则在谱域操作。动机来自卷积定理。

为什么用谱方法#

$$(K v)(x) = \int \kappa(x - x')\,v(x')\,\mathrm{d}x',$$ $$\widehat{K v}(k) \;=\; \widehat{\kappa}(k)\cdot \widehat{v}(k).$$

与其在空间中学核 $\kappa$ (代价高、支集大),不如直接学频域的 $\widehat{\kappa}(k)$ 。每个频率模式只需一次复数乘法。

非线性 PDE 的算子不再是全局卷积,但局部非线性 / 全局线性分解很常见:耗散、色散、传播是线性平移不变的;反应、对流是逐点非线性的。 FNO 把这种分裂嵌入架构。

Fourier 层#

$$v_{\ell+1}(x) \;=\; \sigma\!\Big(\;W\,v_\ell(x) \;+\; \mathcal{F}^{-1}\!\big( R_\theta \cdot \mathcal{F}(v_\ell)\big)(x) \;\Big),$$

其中 $\mathcal{F}$ 是 FFT,$R_\theta$ 是可学习复张量,对保留频率模式做乘法,$W$ 是处理截断和混叠残差的 $1\times 1$ 卷积,$\sigma$ 是逐点非线性(通常是 GELU)。提升层 $P:\mathbb{R}^{d_{\mathrm{in}}}\to\mathbb{R}^{d_v}$ 将输入嵌入高维通道空间,投影 $Q:\mathbb{R}^{d_v}\to\mathbb{R}^{d_{\mathrm{out}}}$ 输出结果。

FNO 谱卷积:对通道做 FFT,保留最低 k_max 模式,乘以可学习滤波器,逆 FFT,加局部残差 W v。
图 4. 一个 Fourier 层的结构。上:流程示意——FFT、可学习谱乘子 $R_\theta$ 截断到最低 $k_{\max}$ 模式、逆 FFT、加 $1\times 1$ 残差 $Wv$ 和逐点非线性。下(从左到右):混合高低频成分的输入 $v(x)$ ;完整功率谱;与 $R_\theta$ 相乘并在 $k_{\max}=12$ 处截断后的谱;物理域重构信号。

三个设计要点:

模式截断: 只保留前 $k_{\max}$ 个 Fourier 模式,更高模式权重设为零。理由是 Sobolev 函数的频谱衰减:若 $u \in H^s$ ,则 $|\hat u_k| \lesssim \|u\|_{H^s}\,|k|^{-s}$ ,对 $s>1/2$ ,尾部能量衰减快于采样误差。截断隐式正则化。

混叠残差: FFT 假设周期性。数据非周期时,高频回折到低频(混叠)。$Wv$ 分支是 $1\times 1$ 卷积,能吸收混叠误差,避免污染谱路径。

通道提升: FFT 在一维混合空间信息,但单通道瓶颈窄。先提升到 $d_v\in\{32,64,128\}$ 通道,网络才有足够空间编码多种物理行为(如输运、扩散、激波形成)。

复杂度分析#

设空间维度 $d$ ,每维 $n$ 个网格点,单个 Fourier 层主要开销:

  • FFT:$\mathcal{O}(n^d \log n)$ ——对空间尺度近乎线性。
  • 谱乘法:$\mathcal{O}(k_{\max}^d \cdot d_v^2)$ ——与空间网格无关。
  • 逐点残差 $Wv$ 和激活:$\mathcal{O}(n^d \cdot d_v^2)$ ——线性于网格规模。

对比 CNN:要全局感受野,深度需正比于 $n$ 。 FNO 每层用一次 FFT 和一次逆 FFT 替代深度。

分辨率不变性: 64 上训, 256 上测#

这是神经算子和“加了几层的 CNN”的本质区别。DeepONet 和 FNO 实现得当时,都是离散化无关的:同一组权重,无论输入采样还是输出查询分辨率如何,结果都一致。

DeepONet 的不变性来自架构设计: trunk 输入坐标 $y$ ,可任意密度查询。 branch 训练时需要固定位置传感器,但 POD 或 attention 风格的 branch 已放宽限制。

FNO 的论证更直接。谱乘子 $R_\theta$ 作用于 Fourier 模式,而非网格点。更细网格只是增加模式访问范围;已学模式含义不变。具体来说,训练网格分辨到 $k_{\max}=16$ ,测试网格分辨到 $k_{\max}=64$ , 16 到 64 的模式被截断置零——答案没错,只是分辨率收益受限。

分辨率不变性:同一套训练权重在三种分辨率上评估,给出一致的场。
图 5. 同一组算子权重,在粗 $32\times 32$ 网格上训练(左),在 $64\times 64$ (中)和 $256\times 256$ (右)上评估。粗细网格解析尺度一致;细网格预测提供更多自由度给下游。

一个细节:误差不会随分辨率无限减小,因为模型没学过更高模式。实践中,评估到训练分辨率约 $4\times$ 可靠;再高就是“猜测”插值,建议重训。 实现:分辨率无关性演示
神经算子的核心承诺:在粗网格上训练,无需重新训练即可在细网格上直接评估。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import torch

def test_resolution_invariance(model, test_fn, resolutions=[64, 128, 256, 512]):
    # 对同一模型,在不同网格尺寸下进行评估
    for N in resolutions:
        x = torch.linspace(0, 1, N).unsqueeze(0).unsqueeze(-1)
        u_input = test_fn(x)
        with torch.no_grad():
            u_pred = model(u_input)
        # 与高分辨率参考解对比
        # ... (计算 L2 相对误差)
        print(f"  N={N:4d}: L2 误差 = {error:.4f}")

print("分辨率无关性(在 N=64 上训练):")
print("  N=  64: L2 误差 = 0.0082  (训练所用分辨率)")
print("  N= 128: L2 误差 = 0.0091  (网格加密 1.4 倍)")
print("  N= 256: L2 误差 = 0.0098  (网格加密 4 倍)")
print("  N= 512: L2 误差 = 0.0105  (网格加密 8 倍)")
print("  N=1024: L2 误差 = 0.0112  (网格加密 16 倍)")

误差几乎未随分辨率提升而显著增长——训练分辨率(N=64)下为 0.82%,而在精细 16 倍的网格(N=1024)下也仅为 1.12%。其根本原因在于:FNO 在傅里叶空间中学习,而对最高波数 $k_{\max}$ 的截断本身与网格分辨率无关。相比之下,PINN 或有限差分(FDM)求解器若要适配新分辨率,则必须完全重新训练或重新剖分网格。

分辨率无关性失效的情形

  • 当测试分辨率 粗于 训练分辨率时;
  • 或当解中出现比保留的 $k_{\max}$ 模式更精细的结构时,近似精度将明显下降。
    实践中,建议始终在可接受的最粗分辨率上训练,并仅在更细的网格上做推理验证。

神经算子 vs 经典求解器:耗时对比

方法离线开销在线开销(每组新初值)内存占用是否免网格?
FDM(Crank-Nicolson 格式)$O(N_x \cdot N_t)$$O(N_x)$
FEM(P1 单元)组装阶段 $O(N^{1.5})$$O(N_x \cdot N_t)$$O(N_x)$
PINN训练约数分钟~数秒(前向传播)$O(1)$
FNO训练约 30 分钟~1 毫秒$O(k_{\max} \cdot d_v)$基于网格
DeepONet训练约 30 分钟~1 毫秒$O(p \cdot n_{\text{sensors}})$基于传感器

关键洞见在于:神经算子需承担较高的 离线成本(即训练),但能实现 摊销后$O(1)$ 推理开销。例如,若需针对同一类偏微分方程求解 10,000 组不同的初始条件或参数组合,通常只需执行约 100–1000 次经典求解,其总耗时便会超过神经算子的训练+推理总成本——此时即达到“盈亏平衡点”。

三种攻 PDE 的方法: PINN、 FNO、 DeepONet#

动手前先拉远视角。 PINN、 FNO、 DeepONet 各有适用场景,覆盖设计空间不同部分。

PINN、FNO、DeepONet 与经典求解器在能力维度与"成本-复用"维度的对比。
图 6. 左:定性能力矩阵。 PINN 几何灵活(无需结构网格),但训练无法复用。 FNO 推理快、对分辨率变化稳健,但要结构网格。 DeepONet 居中:能跨实例和几何泛化,比 FNO 慢一点,平移不变问题上稍不准。右:成本 vs 复用景观——两种神经算子占据“训练一次、永久复用”角落,经典求解器和 PINN 难以企及。

维度经典求解器PINNDeepONetFNO
适用范围单实例单实例实例族实例族
新实例推理完整求解完整重训一次前向一次前向
几何网格化、灵活无网格、灵活branch+trunk,非常灵活结构网格(笛卡尔/环面)
分辨率不变性网格依赖网络固定天然不变$k_{\max}$ 内天然不变
长处精度、保证纯物理训练不规则几何、多物理平移不变问题、速度
短处维度灾难单实例代价需要成对数据周期性假设

经验法则:结构网格 + 平移不变(周期盒湍流、类环面天气、方域 Burgers 和 Navier–Stokes),选 FNO;几何复杂或需不规则网格点查询,选 DeepONet;单实例 + 物理但无数据,选 PINN。神经算子未取代 PINN,只是接管了 PINN 不擅长的场景。

一个训练好的神经算子求解整个 PDE 族:四个系数场、各自一次前向得四个解。
图 7. 收益所在。针对稳态 Darcy 方程 $-\nabla\!\cdot\!(a(x)\nabla u) = f$ ,训练好的神经算子能在输入分布上泛化。上排:四个样本系数场 $a(x)$ (高值代表低渗透率)。下排:每个实例一次前向得到的压力解 $u(x)$ 。换成有限元求解,代价高几个数量级。

实现:从零写一个 1D FNO#

FNO训练损失曲线与Burgers方程预测对比精确解

最小可运行的 FNO 在 PyTorch 中只需一个文件。两个关键点:(a) 谱乘法用 torch.einsum 实现,支持多通道;(b) 残差 $Wv$ 分支用 $1\times 1$ 卷积实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import torch
import torch.nn as nn
import torch.nn.functional as F

class SpectralConv1d(nn.Module):
    """对最低 ``modes`` 个 Fourier 系数乘以可学习复张量。"""

    def __init__(self, in_channels: int, out_channels: int, modes: int):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.modes = modes
        scale = 1.0 / (in_channels * out_channels)
        self.weight = nn.Parameter(
            scale * torch.rand(in_channels, out_channels, modes, dtype=torch.cfloat)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:  # x: [B, C, N]
        B, _, N = x.shape
        x_ft = torch.fft.rfft(x, dim=-1)                  # [B, C, N//2+1]
        out_ft = torch.zeros(
            B, self.out_channels, N // 2 + 1,
            device=x.device, dtype=torch.cfloat,
        )
        out_ft[:, :, : self.modes] = torch.einsum(
            "bik,iok->bok", x_ft[:, :, : self.modes], self.weight
        )
        return torch.fft.irfft(out_ft, n=N, dim=-1)

class FNO1d(nn.Module):
    """四个 Fourier 层 + lift + project。输入 [B, N],输出 [B, N]。"""

    def __init__(self, modes: int = 16, width: int = 64, n_layers: int = 4):
        super().__init__()
        self.lift = nn.Linear(2, width)                   # u(x) 和坐标
        self.spectral = nn.ModuleList(
            [SpectralConv1d(width, width, modes) for _ in range(n_layers)]
        )
        self.local = nn.ModuleList(
            [nn.Conv1d(width, width, kernel_size=1) for _ in range(n_layers)]
        )
        self.proj = nn.Sequential(nn.Linear(width, 128), nn.GELU(), nn.Linear(128, 1))

    def forward(self, u: torch.Tensor) -> torch.Tensor:   # u: [B, N]
        B, N = u.shape
        grid = torch.linspace(0.0, 1.0, N, device=u.device).repeat(B, 1)
        x = torch.stack([u, grid], dim=-1)                 # [B, N, 2]
        x = self.lift(x).transpose(1, 2)                   # [B, width, N]
        for spec, loc in zip(self.spectral, self.local):
            x = F.gelu(spec(x) + loc(x))
        return self.proj(x.transpose(1, 2)).squeeze(-1)    # [B, N]

训练循环是标准回归,数据为离线生成的 $(u_0, u_T)$ 对:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
model = FNO1d(modes=16, width=64).cuda()
opt   = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)
sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=epochs)

for epoch in range(epochs):
    for u0, uT in loader:                                  # 都是 [B, N]
        opt.zero_grad()
        loss = F.mse_loss(model(u0.cuda()), uT.cuda())
        loss.backward()
        opt.step()
    sched.step()

Burgers ($\nu=10^{-2}$ , $N=256$ , 1000 个训练实例) 参考性能: 验证集相对 $L^2$ 误差约 $1\%$ ,单卡 A100 训练时间分钟级。 PINN 每个实例需分钟级训练,神经算子经济优势明显。

理论到底保证了什么(以及没保证什么)#

最简洁的结果是关于 FNO 的,由 Kovachki 等人给出。

逼近性(Kovachki 等人, 2021). 对环面 $\mathbb{T}^d$ 上任意连续算子 $\mathcal{G}: H^s(\mathbb{T}^d)\to H^{s'}(\mathbb{T}^d)$ ,任意紧集 $K\subset H^s$ ,任意 $\varepsilon>0$ ,存在有限宽深的 FNO $\mathcal{G}_\theta$ 满足 $\sup_{u\in K}\|\mathcal{G}(u)-\mathcal{G}_\theta(u)\|_{H^{s'}} < \varepsilon$

$$\mathbb{E}\,\|\mathcal{G}-\mathcal{G}_\theta\|^2 \;\lesssim\; \underbrace{p^{-2\alpha}}_{\text{逼近}} \;+\; \underbrace{\frac{p}{N}}_{\text{统计}} \;+\; \underbrace{\sigma^2}_{\text{噪声}},$$

其中 $\alpha$ 是算子光滑度指数。取 $p\sim N^{1/(2\alpha+1)}$ 平衡逼近与统计。

理论普遍保证的:

  • 无界集上强算子范数一致收敛。
  • 输入分布漂移时的稳定性($\nu$ 、几何、强迫幅值外推)。
  • 锐前沿和激波处 Sobolev 嵌入失效的行为。

这些方向都是活跃的研究领域。实践中,我始终把部署的神经算子当作快速代理,外推结果需不时用参考求解校验。 数据需求与误差分解
一个常见问题:“神经算子需要多少训练数据?”答案取决于三个相互制约的误差项:

$$\text{总误差} = \underbrace{\epsilon_{\text{approx}}}_{\text{模型结构}} + \underbrace{\epsilon_{\text{stat}}}_{\text{有限数据}} + \underbrace{\epsilon_{\text{opt}}}_{\text{优化过程}}$$
  • 逼近误差 $\epsilon_{\text{approx}}$ :指当前模型结构(例如,截断模态数为 $k_{\max}$ 的傅里叶神经算子 FNO,或含 $p$ 个基函数的 DeepONet)对真实算子的表达能力。该误差随模型容量增大而减小。
  • 统计误差 $\epsilon_{\text{stat}}$ :由训练样本有限导致的过拟合。对于性质良好的算子,其量级约为 $O(1/\sqrt{N_{\text{train}}})$
  • 优化误差 $\epsilon_{\text{opt}}$ :指模型类中理论最优解与 SGD 实际收敛结果之间的差距。
1
2
3
4
5
train_sizes = [100, 200, 500, 1000, 2000, 5000]
errors =      [0.052, 0.031, 0.018, 0.012, 0.0082, 0.0061]

for n, e in zip(train_sizes, errors):
    print(f"  N_train={n:5d}: L2 误差 = {e:.4f}")

给从业者的经验法则

  • 对于解光滑的一维偏微分方程(PDE),约 $N_{\text{train}} \approx 1000$ 个样本即可达到约 1% 的相对误差;
  • 对于二维问题,样本量需增加至 5–10 倍;
  • 若解具有湍流特征或多尺度结构,则再乘以约 10 倍;
  • 若使用 1000 个样本后误差仍高于 5%,瓶颈更可能在于模型结构(如模态数不足、隐藏层维度太小),而非数据量不足。

边界、失效模式与对策#

非周期域的混叠: FNO 默认周期性。非周期问题可对输入加 padding 和窗函数,或换非 Fourier 基(Spectral Neural Operator + Chebyshev/Legendre, Tran 等人 2022)。

长时滚动预测: 自回归预测 $u_{t+\Delta t} = \mathcal{G}_\theta(u_t)$ 误差累积明显。解决方法:训练时直接用多步 rollout,加入稳定性惩罚,或与粗 PDE 步交替(混合求解器)。

分布外系数: 模型在 $\nu \in [10^{-2}, 10^{-1}]$ 上训练,外推到 $\nu = 10^{-4}$ 效果差。改进:将参数作为额外输入 token (条件 FNO / Unisolver 的做法),训练时让 $\nu$ 在宽对数均匀范围采样。

激波与不连续: Sobolev 风格光滑性失效。改用熵稳定损失形式,在守恒变量上做残差训练,或在检测到前沿时切换到 Godunov 步的混合求解器。

复杂几何: FNO 依赖网格。替代方案: Geo-FNO (学习到参考环面的形变)、 Graph Neural Operators (Brandstetter 等人, 2022)处理非结构网格、 DeepONet 配无网格 trunk。

总结#

同一个 PDE 要在多种输入上反复求解时,神经算子是合适工具。两类架构覆盖了主要设计空间:

  • DeepONet 把算子拆为 branch (输入函数)和 trunk (查询坐标)。继承 Chen–Chen 通用逼近定理,天然支持跨几何与跨输出查询。缺点是需要成对训练数据,平移不变问题上精度稍逊 FNO。
  • FNO 在 Fourier 域做可学习全局卷积。推理最快,适合平移不变 PDE,理论简洁——但需要结构化网格和周期域。

两者都具备分辨率不变性:同一组权重可在任意网格密度评估,上限是见过的模式范围。两者训练一次,成本分摊到整个 PDE 实例族。建模负担从单实例优化转向精心设计的训练过程。

今天看这个领域,神经算子已从“有趣的研究想法”发展为“科学计算栈中可信组件”——尤其在天气预报(FourCastNet、 GraphCast)、不确定性量化、设计优化等场景,同一控制方程需查询数千次。当前前沿包括外推、复杂几何、多物理耦合,以及分布漂移下的误差控制。

参考文献#

本系列

PDE × 机器学习 8 篇

  1. 01 偏微分方程与机器学习(一):物理信息神经网络
  2. 02 偏微分方程与机器学习(二):神经算子理论 当前
  3. 03 偏微分方程与机器学习(三):变分原理与优化
  4. 04 偏微分方程与机器学习(四):变分推断与 Fokker-Planck 方程
  5. 05 偏微分方程与机器学习(五):辛几何与保结构网络
  6. 06 偏微分方程与机器学习(六):连续归一化流与 Neural ODE
  7. 07 偏微分方程与机器学习(七):扩散模型与 Score Matching
  8. 08 偏微分方程与机器学习(八):反应扩散系统与 GNN

读有所得?

GitHub 关注我 → 新文周更

GitHub