PDE与机器学习(二):神经算子理论

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

经典 PDE 求解器——有限差分、有限元、谱方法——本质上是一个函数:喂给它一组初始条件和参数,吐回一组解。PINN 不过是把同一个函数披上了神经网络的外衣:每换一个初始条件,就要重新训练。机翼上的来流速度变了,或者预报里某个传感器读数挪了一格,时钟就得重新归零。

神经算子(neural operator)从根本上改写了这套合约。它学习的是解算子本身——一个输入是函数(初始条件、系数场、源项),输出也是函数(某时刻的解、目标域上的场)的映射。在几千组离线生成的样本上训练一次,之后每个新实例只需要一次前向传播:不用重新划网格,不用重新优化,推理时根本没有 PDE 求解器在跑。

本文是这套技术的深度梳理。先从让"在函数空间之间学映射"具有数学意义的泛函分析框架出发,再剖析占据文献主流的两类架构:DeepONet——按 Chen–Chen 通用逼近定理把算子分解为 branch 与 trunk;Fourier Neural Operator(FNO)——在频域里做可学习的全局卷积。沿途我们会讨论为什么神经算子是分辨率不变的、理论到底给出了多强的误差界,以及每种架构悄悄失效的边界在哪。

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

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

1.1 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$ 一变,损失景观就变,优化器只能从头来过。如果你要做一千个候选来流剖面的设计扫描,那就是一千次训练。

1.2 算子学习的形式化

$$ \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{(一次前向传播)}. $$

训练成本被整个实例族分摊。这就是我们想要的交易。

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

2.1 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$ 度量光滑性。后面分辨率不变性的论证就落在这里:越光滑的函数,频谱衰减越快,可以毫不可惜地丢掉高频模式。

2.2 为什么输入"维度无限"

CNN 吃 $256\times 256$ 图片时,看到的其实是 $\mathbb{R}^{65536}$ 中的一个向量。分辨率翻倍变成 $512\times 512$,输入维度变了,模型就废了。神经算子相反,吃的是函数,仅出于数值计算才采样它。架构必须保证:在查询点 $y$ 处的预测与输入是怎么采样的无关。这是把算子学习与"恰好读 PDE 解的 CNN"区别开的设计约束。

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

算子学习的理论种子是 Chen 和 Chen 在 1995 年种下的。

$$ \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)针对受限算子类得到了更尖锐的速率。渐近图景就是右图那种经典的偏差–方差–噪声分解。

4. 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 残差项,在标注数据稀缺时极其有用。

5. Fourier Neural Operator

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

5.1 为什么走谱方法

$$ (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 把这种分裂直接焊进架构。

5.2 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\}$ 通道,网络才有足够空间编码多种物理行为模式(如输运 vs 扩散 vs 激波形成)。

5.3 复杂度

设空间维度为 $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 换掉了这种深度。

6. 分辨率不变性: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$ 是可靠的;再往上的高频内容是"猜"的,应该重训。

7. 三种攻 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)$。把每次前向都换成有限元求解,代价要高几个数量级。

8. 实现:从零写一个 1D FNO

最小可运行的 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
52
53
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 每个实例都要分钟级训练,神经算子的经济优势立刻显形。

9. 理论究竟保证了什么(以及没有保证什么)

最干净的结果是关于 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 嵌入失效时的行为。

每一项都是活跃的研究前沿。实践中,部署的神经算子始终应被视为快速代理,外推必须不时与一次参考求解做对照检查。

10. 边界、失效模式与对策

非周期域的混叠。 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。

11. 小结

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

  • DeepONet 把算子分解为 branch(输入函数)和 trunk(查询坐标)。它继承 Chen–Chen 通用逼近定理,天然能跨几何与跨输出查询。短处是必须有成对训练数据,并且在平移不变问题上精度略落 FNO。
  • FNO 在 Fourier 域里做可学习的全局卷积。推理最快、对平移不变 PDE 最自然、理论对象最干净——代价是需要结构网格和(通常是)周期域。

两者都是分辨率不变的:同一组训练好的权重,在它见过的模式范围内可在任意网格密度上评估。两者都把训练做一次,把成本摊给整个 PDE 实例族。两者都把建模负担从单实例优化推到了精心设计的训练 curriculum 上。

今天对这一领域的诚实总结是:神经算子已经从"有趣的研究想法"走到了"科学计算栈里可信的组件"——尤其在天气预报(FourCastNet、GraphCast)、不确定性量化、设计优化这些同一控制方程被查询数千次的场景里。它们公开的前沿是外推、复杂几何、多物理耦合,以及分布漂移下的严格误差控制。

参考文献


系列导航

部分主题
1物理信息神经网络
2神经算子理论 (本文)
3变分原理与优化
4变分推断与Fokker-Planck方程
5辛几何与保结构网络
6连续归一化流与Neural ODE
7扩散模型与Score Matching
8反应扩散系统与GNN

Liked this piece?

Follow on GitHub for the next one — usually one a week.

GitHub