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 多加一项物理残差损失:
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.grad 算 dT/dt。
动手做 5.1 · 物理信息 Neural ODE(核心改造)
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}")
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)
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 | ? | ? | ? | ? |
五、支柱 A 收尾:你复刻到了什么程度
到这儿,BrainBox 三支柱里的预测支柱已经成型。对照一下:
| 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 的权重 λ 调得过大,最可能出什么问题?
对了。λ 是数据 vs 物理的权衡。λ 太大 → 物理压倒数据 → 模型死守(可能不准确的)物理方程,拟合不了真实扰动(人员、设备未建模热源)→ 欠拟合。λ 太小 → 退化成纯黑箱。实操上要扫几个值(0.001 / 0.01 / 0.1),看验证集表现定。物理方程本身不够准时,λ 尤其要小心。
- PINN 原始论文(Raissi 2019, JCP):sciencedirect.com/…/S0021999118307125 · arXiv 1711.10561
- PINN 作者代码:github.com/maziarraissi/PINNs
- 建筑 PINN 最新作(Sabbagh 2025):S0378778825013532
- 多区域 LSTM 温度预测(Fang 2021):hal.science/…
- MILA 建筑温控神经微分方程:mila.quebec/…