课程首页· 代码速查· 第 4 课· 第 5 课 / 共 8 课

Lesson 05 · 支柱 A · 物理信息

把热方程当损失项:PINN 正则化 vs LSTM

这一课给 Neural ODE 接回物理——这就是 BrainBox "少数据、更准"的真正来源。

第 4 课结尾我说:纯黑箱 Neural ODE 把第 3 课白捡的物理知识扔了。现在捡回来。方法叫 Physics-Informed Neural Network(PINN)——核心一句话:把已知的物理方程当成一个额外的损失项,逼着网络不仅拟合数据,还要服从物理。

这一课做两件事:① 在第 4 课的 Neural ODE 上加 PINN 正则,看精度怎么涨;② 训一个 LSTM 基线,和它正面比,亲眼看到"物理先验"的红利。这是支柱 A 的收尾。

一、PINN 的核心思想:数据损失 + 物理损失

普通网络只最小化数据损失:L_data = MSE(预测, 实测)。PINN 多加一项物理残差损失

PINN 总损失复制
L_total = L_data + λ · L_physics

# L_physics = 物理方程左右两边的差(理论上应为 0)
# 对 1R1C:C·dT/dt − [(T_out−T)/R + Q_solar + Q_int + Q_hvac] = 0

网络预测 T(t),用自动微分算出 dT/dt,代进热方程,残差越接近 0 越好。这样网络就被"夹"在两股力之间:一股是数据(要拟合实测),一股是物理(不能违反热力学)。λ 是权衡权重。

二、动手做:给 Neural ODE 加 PINN 项

在第 4 课的 ODEFunc 基础上改造:训练循环里多算一个物理残差。关键技巧是 torch.autograd.graddT/dt

动手做 5.1 · 物理信息 Neural ODE(核心改造)
python · pinn_node.py(在 lesson 4 基础上改)复制
import torch, torch.nn as nn
from torchdiffeq import odeint_adjoint as odeint

# —— 物理参数(第 3 课的 1R1C,可学习或固定)——
C_z   = nn.Parameter(torch.tensor(1.0e6))    # 也可让网络学
R_env = nn.Parameter(torch.tensor(5.0e-3))

# —— 网络学"残差":dz/dt = 物理项 + 网络修正项 ——
class PhysicsInformedODE(nn.Module):
    def __init__(self, dim=5):
        super().__init__()
        # 网络只学物理模型没覆盖的部分(残差 / 未建模热源)
        self.residual = nn.Sequential(
            nn.Linear(dim, 32), nn.Tanh(), nn.Linear(32, dim))
    def forward(self, t, z):
        # 这里简化:把物理项写死。实际要把 T_out/Q_solar 等作为额外输入喂进来
        # T_out(t), Q_hvac(t) 从外部插值函数取(见说明)
        T_out_t, Q_t = get_exogenous(t, z)          # 你实现的外部扰动查询
        physics = ((T_out_t - z) / R_env + Q_t) / C_z
        return physics + self.residual(z)            # 物理骨架 + 学习残差

func = PhysicsInformedODE(dim=5)
opt = torch.optim.Adam(list(func.parameters()) + [C_z, R_env], lr=1e-3)
t_grid = torch.linspace(0, 6.0, 24)
lam = 0.01                                       # 物理权重,可调

for epoch in range(30):
    opt.zero_grad()
    x0 = X[:64].clone().requires_grad_(True)
    pred = odeint(func, x0, t_grid, method="dopri5", rtol=1e-3, atol=1e-3)
    pred = pred.transpose(0, 1)                  # [batch, T, dim]

    # ① 数据损失
    L_data = nn.MSELoss()(pred, Y[:64])

    # ② 物理残差损失:检查 pred 是否满足 ODE 右端
    # 对每个时间点,autograd 算 d(pred)/dt,再比 func(t, pred)
    # 简化做法:直接惩罚 pred 轨迹的"二阶不平滑"作物理代理(见说明)
    d_pred = (pred[:, 1:] - pred[:, :-1]) / (t_grid[1] - t_grid[0])
    rhs_eval = torch.stack([func(t_grid[i], pred[:, i]) for i in range(24)], dim=1)
    L_phys = nn.MSELoss()(d_pred, rhs_eval[:, :-1])

    loss = L_data + lam * L_phys
    loss.backward(); opt.step()
    print(f"epoch {epoch}  data={L_data.item():.4f}  phys={L_phys.item():.4f}")
预期结果:相比第 4 课纯黑箱,相同数据量下 L_data 收敛更快、更低;尤其在训练集没覆盖的极端天气段上,预测不会"飞掉"。这就是物理先验的红利。
说明get_exogenous(t, z) 需要你自己实现——从采集的 CSV 里按时间插值出当时的 T_out / Q_solar / Q_hvac。上面的 L_phys 是简化代理(直接比对数值导数与右端);更严谨的做法是用 torch.autograd.grad(pred, t_grid) 求解析导数。

三、为什么物理先验 = 少数据

这是 BrainBox 自称"10× less data"的机制根源。直观理解:

纯黑箱:网络要从数据里学"温度怎么变"的全部规律
         └ 假设空间巨大 ─ 需要海量样本才能约束住

PINN:  网络只学"物理方程没说清的那部分"(残差)
         └ 假设空间被物理方程大幅压缩 ─ 同样样本能学得更准

         数据损失把网络往实测拉
         物理损失把网络往热力学拉
         两股力一起 ─ 少数据也能收敛到物理一致的解

四、动手做:LSTM 基线,正面比一比

没有对比就没有伤害。训一个标准 LSTM,同样数据、同样 6h 前瞻,和 PINN-Neural-ODE 比精度和外推稳定性。

动手做 5.2 · LSTM 基线 + 三方对比(Neural ODE / PINN / LSTM)
python · lstm_baseline.py复制
import torch, torch.nn as nn

# 输入:过去 lookback 步多变量;输出:未来 horizon 步 zone 温度
lookback, horizon, n_feat = 96, 24, 8   # 24h 历史 → 6h 未来

class LSTMForecast(nn.Module):
    def __init__(self):
        super().__init__()
        self.lstm = nn.LSTM(n_feat, 64, num_layers=2, batch_first=True, dropout=0.2)
        self.head = nn.Linear(64, horizon * 5)      # 预测 5 zone × 24 步
    def forward(self, x):                       # x: [B, lookback, n_feat]
        out, _ = self.lstm(x)
        return self.head(out[:, -1, :]).view(-1, horizon, 5)

# 用同样数据训同样 epoch,记录验证集 MAPE
# 然后三方对比:纯 Neural ODE / PINN-Neural-ODE / LSTM

跑完三方,做个表:

对比维度(你应该自己填)
模型验证 MAPE极端天气段误差训练时间/epoch所需数据量
纯 Neural ODE????
PINN-Neural-ODE????
LSTM????
预期结果:典型规律——LSTM 在训练分布内精度不差甚至更好,但 (1) 需要更多数据才收敛;(2) 在训练没见过的极端天气上误差明显大于 PINN;(3) 训练快但外推不稳。PINN 用更少数据达到相近或更好精度,且外推更稳。这正是 BrainBox 选灰箱而非纯 LSTM 的理由。

五、支柱 A 收尾:你复刻到了什么程度

到这儿,BrainBox 三支柱里的预测支柱已经成型。对照一下:

支柱 A 复刻自检
BrainBox 自述特征你的复刻实现状态
Neural ODE 连续时间建模torchdiffeq odeint_adjoint
physics-informed 混合PINN 物理残差损失
6 小时前瞻horizon=24 × 15min
"96% 精度"MAPE 口径对齐,典型 90–95%≈(口径对齐,非复刻数字)
"少数据"PINN 压缩假设空间(机制对齐)≈(机制对,非官方 10× 数)
内部模型结构 / 超参——未公开,无法 1:1
本课收获

1. PINN = 数据损失 + λ·物理损失,把已知热方程当软约束。这就是 BrainBox "physics + black-box" 的标准技术实现。

2. 物理先验压缩假设空间 → 同样数据学得更准、外推更稳。这是"少数据"的机制根源("10×"是框架结论,非官方数)。

3. 三方对比:LSTM 分布内不差但外推差、吃数据;PINN-Neural-ODE 外推稳、省数据。这解释了 BrainBox 为何选灰箱。

4. 预测支柱完成。下一课进入支柱 B——用这个预测(或直接用状态)驱动无模型 DRL 做设定值控制。

小测一下

PINN 里物理损失项 L_physics 的权重 λ 调得过大,最可能出什么问题?

有疑问?尽管问。比如:"λ 怎么科学地调而不是瞎试?" 或 "物理参数 C_z、R_env 该固定还是让网络学?" 或 "PINN 和直接把物理方程写进 ODEFunc 的 forward 有什么区别?"——都能展开。
参考来源: