← 返回 Physics-informed GNN 课程

Physics-informed GNN · 第 5 模块

GNN 入门 · 图、特征与消息传递

上一章 AI 入门用 MLP 学习输入—输出关系。微电网还包含一类重要信息:哪些节点经由什么线路相互连接? 本章把这些关系放入计算过程,再通过一个透明的电压学习任务,训练小型图神经网络 GNN。

本章目标:读懂图的节点表与边表,手算一条消息,解释一层网络能看到多远,并运行可训练的小型 GNN。交互例子会区分图结构、隐藏特征、电压读出和物理参考。

1. 图描述“谁与谁相连”

预备知识:向量、加权求和,以及上一章的 tanh、MSE 和梯度下降。潮流基础有助于理解物理例子,但计算消息本身并不需要先掌握潮流求解器。

节点(node)表示对象,边(edge)表示对象之间的关系。在本例中,节点是电气母线,边是线路或联络线。换一个任务,节点也可以是原子或人,特征含义随之改变。节点编号用于识别表格中的行,本身不是一个物理测量或空间坐标。

普通 MLP 可以接收拼接起来的节点向量,但需要预先约定节点顺序和连接关系的表示方式。消息传递 GNN 显式使用邻居关系,并在每个节点复用同一局部计算规则。这是一种结构选择,不意味着所有任务上 GNN 都一定优于 MLP。

1 · 图结构母线与当前可用的电气连接。
2 · 特征节点 X、线路属性 E 与开关状态。
3 · 消息邻居信息 → 聚合 → 节点更新。
4 · 读出逐节点预测,或汇总为整图输出。

电气连接是无向的,计算消息可以有方向

一条串联线路连接两个节点,并没有预先规定实际功率的方向。这里把它作为一条无向物理边。为了让两端交换信息,再生成 j → i、i → j 两条计算弧。五节点辐射网有四条接通的物理线路,因此有八条计算弧。图中的消息箭头表示数据传播方向,不表示电流或有功功率的正负。

二值邻接矩阵 A 记录当前邻居:相连时 Aᵢⱼ = 1,否则为 0。它与 Ybus 不同:A 记录连接关系,Ybus 是复数物理网络算子。本例 A 不添加自环,节点自身的信息由更新公式里的独立项保留。

2. 给节点与线路添加特征

先介绍五节点微电网,再给特征赋值:节点 1 是唯一的外部参考源;节点 2 是带负荷的分支点;节点 3、5 带负荷;节点 4 同时有负荷和光伏逆变器。默认线路为 1–2、2–3、2–4、4–5;常开的联络线 3–5 可以提供另一条路径。

物理假设与输入约定

  • 三相平衡稳态,线路采用串联阻抗,设备采用指定净 PQ。
  • 三相容量基准为 1 MVA,线电压基准为 0.4 kV;阻抗基准为 Zbase = 0.16 Ω。
  • 节点 P、Q 以净消耗为正,即负荷减发电。光伏按固定 PQ 发有功,Q = 0,不调节电压,也不自动维持断开的孤岛。
  • 节点 1 的参考电压为 1∠0 pu。其输入 P = Q = 0 是占位值,不是求解得到的电源出力;另用参考标记表示它的角色。
节点倍率 1 时的负荷 P / Q发电默认净 P / Q
1参考节点外部电源输入占位值 0 / 0
280 kW / 30 kvar无80 kW / 30 kvar
3100 kW / 40 kvar无100 kW / 40 kvar
460 kW / 25 kvar光伏 50 kW10 kW / 25 kvar
5100 kW / 40 kvar无100 kW / 40 kvar

负荷倍率作用于全部负荷,包括“节点 5 基准负荷”滑块;光伏独立设置。节点 5 的负荷保持 Q/P = 0.4。交互面板会显示控件对应的物理量与归一化输入。

节点矩阵 X

以节点 2 为例,80 kW = 0.08 pu,30 kvar = 0.03 pu,因此 x₂ = [0.4, 0.3, 0]。归一化常数是固定教学尺度,不从验证标签中拟合。求解得到的电压是预测目标,不放入输入特征。节点编号和图上的绘制坐标也不放入 X。

边表与稀疏索引

线路r(pu)x(pu)默认状态
1–20.0400.025接通
2–30.0600.035接通
2–40.0500.030接通
4–50.0550.035接通
3–50.0800.050联络线断开

每条物理边记录 [r, x, status]。阻抗倍率同时缩放 r、x。开路线路仍保留在设备表中,但不会在消息图中产生计算弧。每条接通线路的两个计算方向使用相同的互易串联线路属性。

edge_index 的形状为 [2, 计算弧数],第一行是发送端,第二行是接收端。Python / PyG 常用零基索引,因此物理节点 1 对应数组索引 0。只考虑线路 1–2 时:

edge_index = [[0, 1],    # 发送:节点 1,节点 2
              [1, 0]]    # 接收:节点 2,节点 1

3. 消息 → 聚合 → 更新

一层消息传递先为每条接通计算弧构造消息,再以不依赖邻居排列顺序的方式聚合入站消息,最后更新接收节点的状态。这个结构可以对照 MPNN 原始论文与 PyG 官方消息传递教程阅读。

φ、ψ 可以由 MLP 构造,隐藏维度也可以逐层改变。Sum 保留贡献数量的影响,mean 则除以当前入站邻居数。两者都不依赖邻居在表格中的排列顺序,也没有一种在所有任务上都更合适。本例将空邻域的聚合定义为零。

邻居状态读取邻居的旧状态与连接线路的特征。
逐边消息每条接通计算弧使用同一规则。
聚合将入站消息向量求和或求平均。
更新结合自身信息,再经过 tanh。

一层是一跳,不是一个训练 epoch

每个接收端都读取上一层状态。如果直接原地依次修改节点,后处理的节点会读到已经更新的值,就不再是这里定义的同步层。一层局部消息可以依赖一跳邻居;K 层可以依赖最多 K 跳范围内的信息,前提是网络只做局部消息传递。整图 pooling 会引入另一类依赖,本例不在局部层中使用它。

相同参数作用于各个节点和计算弧。若一致地重新编号节点,节点输出也随之以同样方式重新排列,这称为置换等变性(permutation equivariance)。对节点表示做均值等对称的整图读出,则具有置换不变性。并不是任意标为 GNN 的实现都自动具有这些性质;输入表示和参数共享必须满足相应的重编号约定。

4. 手算一层真正执行的消息传递

为了让每次乘法都可检查,使用三个隐藏通道的简化 edge-weighted MPNN:

r、x 取 pu 数值,因此 aₑ 无量纲。这是人为选择的特征门控,不是电气导纳或功率传输定律。关闭阻抗门控后,接通边的 aₑ 全部变为 1,消息不再包含阻抗信息。α 保留旧状态,β 控制邻居消息的影响,γ 从原始输入保留跳连;tanh 对每个通道分别作用。

本教学模型让 α、β、γ 在通道、节点以及层与层之间共享。一般 GNN 可以使用矩阵或 MLP,并让各层参数不同。这里的共享更新使模型足够小,能够用可读源码完整推导与训练。

默认手动权重为 α = 0.5、β = 0.6、γ = 0.4。节点 2 在第一层收到:

计算弧门控发送端 h⁽⁰⁾消息 aₑh⁽⁰⁾
1 → 20.514563[0, 0, 1][0, 0, 0.514563]
3 → 20.418542[0.5, 0.4, 0][0.209271, 0.167417, 0]
4 → 20.461640[0.05, 0.25, 0][0.023082, 0.115410, 0]

Mean 聚合得到 [0.077451, 0.094276, 0.171521]。代入 h₂⁽⁰⁾ = x₂ = [0.4, 0.3, 0]:

第三个通道变为非零,是因为带有参考标记的邻居传入了信息。经过更新,这些通道已经是潜在特征(latent features),不能再逐项解释为 P、Q、电压。隐藏宽度仍为三,并不意味着物理含义原样保留。

5. 交互探索微电网图

从节点 2、第一层开始,把入站消息表与上面的例题对照。随后观察节点 1,并改变节点 5 的负荷:默认路径为 5–4–2–1,因此节点 1 的表示在第 3 层之前不能受到该变化影响。参考节点的电压读出另外固定为 1,做局部性实验时应看节点表示图。

五节点微电网 · 图与消息实验

拖动参数、点击节点、逐层查看
圆圈内为节点编号,下方显示当前层的通道 1。橙色箭头表示流向所选节点的计算消息;绿色环表示当前层数能覆盖的节点。箭头不表示电功率方向。

手动模式可调整三个共享系数,读出层保持初始值。训练模式使用下方训练得到的全部 7 个参数;此时手动滑块暂停。

0 层是归一化输入;ℓ 层表示已完成 ℓ 次同步更新,不是训练了 ℓ 个 epoch。

各节点当前表示

通道 1通道 2通道 3

所选节点的更新

进入所选节点的逐条消息

方向aₑm₁m₂m₃

展开当前图数据:X、边特征、邻接矩阵与 edge_index
节点:物理量与归一化输入(负荷为正)
BusP (pu)Q (pu)refX₁X₂X₃
物理线路表:开路保留记录,但不产生消息弧
Liner (pu)x (pu)statusaₑ
A · 二值邻接矩阵(不是 Ybus)
Bus12345

edge_index · 零基索引

第一行发送端,第二行接收端。数据中 0 对应图中的节点 1。

再闭合 3–5 联络线,或者断开 2–4,重新检查邻居集合与覆盖范围。线路状态必须改变计算图;只把一条线路标成“断开”,却保留原来的邻接关系,会允许消息穿过不存在的连接。节点失去唯一电源后,图运算仍能得到数值,但这些数值不能证明存在供电运行点。

6. 加入读出层,并从数据中学习参数

消息层产生节点表示,再通过逐节点共享读出预测归一化电压降:

模型共有七个可训练标量:α、β、γ、w₁、w₂、w₃、b。训练会通过读出层和每一层消息传递反向传播,为在各层、各节点复用的参数累加梯度,并不只是固定节点表示后单独拟合读出层。

电压标签从哪里来?

为了聚焦 GNN 的计算过程,这里用小型平衡电压线性化模型生成标签,而不是调用一个隐藏的 AC 求解器。令 V = 1 + ΔV,参考端 ΔV₁ = 0,由串联线路构建 Ybus,忽略二阶功率项;以净负荷 Sload = P + jQ 为正:

负号来自“负荷消耗为正、向网络注入为负”的约定。按照接通线路构建 YLL,求解 ΔV 对应的实数分块线性方程。默认参考电压幅值为 [1, 0.985025, 0.977625, 0.977575, 0.970675] pu。该参考忽略损耗与非线性电压项,是教学近似,不是完整 AC 或不平衡潮流结果。

使用固定种子生成 32 个径向训练工况与另外 16 个径向验证工况:负荷倍率为 0.6–1.4,节点 5 基准负荷为 60–160 kW,节点 4 光伏为 0–100 kW,线路阻抗倍率为 0.8–1.2。两组都保持默认径向拓扑。标签生成器不进入 GNN 输入,只用于构造目标和评价预测。

每个训练 epoch 进行一次全批量更新,改变的是 θ,不是消息层数 K。固定 θ 后,输入一个新工况执行前向计算,才是推理。

训练一个小型 GNN,再改变运行工况

使用固定生成的 32 个径向工况训练,在另外 16 个径向工况上验证。训练样本独立于上方工况滑块;层数、聚合和阻抗门控决定模型设置。训练会更新 α、β、γ、w₁、w₂、w₃、b 全部参数。

尚未训练;上方显示手动权重的前向计算。

验证电压 MAE(pu)—
当前工况 MAE(pu)—
共享可训练参数7

当前工况:线性参考与 GNN 读出

线性参考GNN

训练与验证损失(log₁₀ MSE)

训练验证
Bus线性参考 puGNN 读出 pu|error| pu
查看当前使用的全部模型权重

节点 1 电压固定为 1 pu,不计入损失或 MAE。训练损失将电压降除以 0.05 pu 后计算 MSE;MAE 显示实际 pu 误差。改变拓扑属于此训练分布之外的演示,不是 N-1 泛化验证。

先训练一次,再保留所得权重改变物理参数。改变 K、聚合方式或阻抗门控,则相当于改变模型设置,会清除此前训练结果。默认 400 轮后,验证电压 MAE 从约 0.01534 降为 0.00527 pu;该数字仅描述这个固定种子的线性参考实验。留出拓扑或非线性 AC 的评估需要另行设计。

距离 N-1 安全预测还差什么?

完整安全任务需要定义供电状态与电压、电流判据,使用准确标签,按场景与故障工况合理划分数据,并评估限值附近的误判。这里闭合联络线或断开线路,是展示图和输出如何变化;这些拓扑并未进入当前训练分布。模型即使具有置换等变性,也仍可能预测错误,更不会自动满足基尔霍夫定律。后续 physics-informed 训练可以在变量和单位明确后,加入指定的 AC 方程残差与约束。

7. 阅读、运行并修改 Python

网页实验与 Python 下载实现相同的图、公式、带种子工况、梯度与训练循环。可先展开模型源码检查依赖,或者从带注释的主程序中修改一个参数。代码面板绘制节点表示,因此物理参考不可用时,仍然可以检查图计算过程。

1 · case:当前工况、模型设置与权重

case 复制当前控件与实际使用的 θ。观察节点和查看层数只是显示选项,不会改变模型参数。Python 默认做一次完整前向计算;下方注释展示如何另外启动训练。

2 · 展开 model.py:图构建、消息、参考与完整反向传播

唯一依赖是标准库 math。build_graph() 构造 X 与边表;arcs() 生成双向计算弧;forward() 同步执行消息层;reference() 求线性电压参考;solve() 组织当前实验;loss_gradient() 与 train_model() 训练全部参数。无需隐藏的 PyG 模型或远程 API。

3 · main():复制输入 → 运行 → 检查 → 返回

主程序调用 solve(parameters),打印图尺寸、最终层的节点表示与电压参考状态。result = main() 将返回值交给下方特征图。改参数只影响 Python 实验。

下载完整模型

首次运行联网下载 Pyodide。计算在独立浏览器 Worker 中完成,可以停止;无第三方 Python 依赖。修改源码不改变上方 JavaScript 实验,刷新页面前可下载保存。

准备运行。

尝试 parameters["open23"] = True,确认 2–3 的两个方向计算弧同时消失;或复制并修改 theta,将 β 改为 0,切断邻居影响。下方 Notebook 包含节点重编号、局部性和全部七个梯度的中心差分检查。

8. 练习:先跟踪信息,再解释预测

  1. 写出两节点、单线路网络的 X 与两条计算弧。它们与 Ybus、求解电压有何区别?
  2. 手算例题中 h₂⁽¹⁾ 的第一个分量。把 mean 改为 sum,说明邻居数如何影响聚合。
  3. 在第 0、1、2、3 层观察节点 1,同时改变节点 5 的负荷;改变拓扑后再试。区分“可能依赖某节点”与“一定产生非零数值变化”。
  4. 把 β 设为 0,再关闭阻抗门控,两次分别移除了哪一类信息路径?
  5. 一致重排节点 X、边端点、参考标记与输出。为什么物理预测应该跟着同样的置换改变行位置?
  6. 联络线断开时退出 2–4,再闭合 3–5。解释为什么“隐藏表示有限”不等于“该节点仍由电源供电”。
  7. 训练模型,区分 400 个 epoch、K = 3、32 个训练图、16 个验证图和 7 个参数各自的作用。为未见故障设计一种评估划分。
自查与后续扩展

图提供连接,特征提供观测,共享消息与更新函数构造表示,读出层定义任务输出,训练则从带标签样本中学习参数。同步层形成局部覆盖范围;置换对称性讨论的是一致重编号,不是任意改变拓扑。更多层可以带来更远信息,也可能使优化或表示质量变差,深度不会自动带来改善。

更完整的模型可以用 MLP 替代标量更新,加入发电设备特征,预测逐相电压与支路量,并在受控拓扑划分下比较 MLP、GNN 基线。始终区分测量量、给定量与预测标签,避免标签泄漏。

9. 下载与继续阅读

下一章:Physics-informed GNN · 微电网 N-1 安全预测,把完整 AC 方程加入 loss,并进行故障筛查。