想象你生活在一个巨大的村庄里,每家每户都是一个小气象站,知道自家门口的实时天气——气温、风力、湿度。但明天天气如何?没有人能只靠自家信息回答。聪明的办法是:全村人定期坐进会议厅,每个人把自己观测到的天气写在纸条上递给邻居;邻居看了纸条,更新自己的判断,再传给更远的邻居。经过几轮传递,每户人家都汇聚了远近邻里传来的信息,最终得出一个比单靠自己准确得多的预测。 这就是“图神经网络(GNN)”做天气预测的基本画面。Google DeepMind 提出的 GraphCast 把整个地球表面划分成一张巨大的“村庄地图”:103 万个网格单元(约 28 公里分辨率)就是 103 万个“村民”;空间上相邻的单元之间连上“道路”(边);大气状态——温度、风速、湿度、气压等——就是每位村民写在纸条上的观测数据。模型经过“编码器→处理器→解码器”三段式流水线,让信息沿边在节点之间层层流动,推出未来 6 小时、12 小时乃至 10 天的天气变化。 这个过程朴素却深刻:只用“数据+图结构+消息传递”,GraphCast 就能在全球 90% 以上的验证指标上超过欧洲中期天气预报中心(ECMWF)的顶级数值预报系统 HRES,而且一次 10 天预报只要约 60 秒。
掌握图神经网络天气建模的思路,是进入 AI for Science 领域的钥匙。你能理解如何把科学网格数据变成图、让信息在图上流动,并据此设计可扩展的并行训练方案——这正是气象、海洋、气候等地球系统科学项目中急需的 AI 技能。
目录
可视化演示
展示球面网格图构建与消息传递机制、多变量多气压层大气特征编码、数据并行与模型并行训练策略,交互切换核心环节。
本节配有交互动效(进入视口后自动加载,约 3KB)。
球面网格图构建与消息传递 地球表面球面网格节点构成图结构,边基于空间距离和球面拓扑连接 每个节点聚合邻居大气状态信息后更新自身,实现前向演化推演 h_i^{t+1} = UPDATE(h_i^t, AGGREGATE({h_j^t : j∈N(i)})) 消息传递是GNN天气模型的核心推演机制
图结构构建:画一张全村地图
要组织全村人互通天气,第一件事是画地图:把村庄分成一个个小院,每院标好位置,用道路把相邻的院落连起来。这张“院落为点、道路为线”的地图,就是图神经网络里说的“图结构”。没有地图,谁和谁相邻都说不清,消息传递更是无从谈起。
对应到 GraphCast,地图上的“院落”来自对地球表面的网格剖分。模型以 0.25° 经度×纬度为一个单元,把球面划分成 721×1440 个网格,约 103.8 万个节点;相邻网格之间连一条无向边,表示“这两个院落地理会相互影响”。每个节点用经纬度定位,就像一个院子在村庄中的坐标。
但地球上的天气系统尺度很大——台风的外围水汽可能来自数百公里外。光有细网格地图不够,GraphCast 于是又叠加了两档更粗的地图:1° 分辨率和 2.25° 分辨率。细地图上的短边照顾近邻,粗地图上的长边把信息送到更远,三层地图合在一起构成多尺度图。数学上,整张图可以写成:
有了这幅多层次的地图,信息就有了流动的通道。但下一个问题随之而来:每个村民的纸条上到底该写什么?这正是特征编码要回答的事。
- 节点集合 V把地球网格中每个单元当做一个节点,共约 103.8 万个节点。
- 边集合 E空间上相邻的节点之间连边,形成邻接关系。
- 多尺度图在 0.25°、1°、2.25° 三档分辨率上分别连线,兼顾近程与远程依赖。
特征编码方法:村民在纸条上写什么
地图画好了,村民拿起笔,把自家观测整理成一张标准纸条。纸条上的内容越丰富,邻居们做判断时依据就越充分。但也不能什么都往上写——写得太多、格式不统一,反而让人抓不住重点。
GraphCast 的“纸条”是一串气象变量向量:37 个气压层上的温度、相对湿度、东西向风速、南北向风速、重力位势,加上地表 2 米气温、10 米风速、海平面气压等,合计 189 个大气状态变量。此外还有海拔、海陆掩膜、纬度等“静态特征”——它们几乎不随时间变化,却决定了这个院落的先天属性,比如山区还是沿海、低海拔还是高海拔。
问题来了:温度的数值在十几到几十之间,气压的数值却在 1000 百帕量级。如果村民直接写原始数字,“大数字”会淹没“小数字”,模型很难公平地看待每个变量。所以大家先做归一化——减去历史均值、除以历史标准差:
纸条内容准备好了,村民还得把它翻译成“村里的统一语言”——也就是嵌入表示,这个细节留到编码器设计一节再展开。先看最关键的问题:纸条究竟是怎么在邻居之间传递的?
- 历史均值 μ_x从 39 年 ERA5 再分析资料中统计该变量的平均状态。
- 历史标准差 σ_x度量该变量在历史上的典型波动幅度。
- 归一化结果大部分值落在 0 附近 ±1 范围内,不同量纲的变量从此可以公平比较。
消息传递机制:纸条如何流动
全村人坐进会议厅,递纸条的规则有三步:先写消息,再汇总,最后更新判断。这套规则就是 GNN 的核心——消息传递。每个节点把自己当前的状态写成一条条消息,沿着边送给邻居;每个节点把所有收到的消息汇总,结合自己原来的状态,更新出新的状态。一轮下来,每个节点就“听见”了所有直接邻居的声音。
在 GraphCast 的每一层网络里,这三步由三个可学习的函数完成。发送方节点 u 写下消息,接收方节点 v 汇总邻居们的消息,再更新自己的状态:
一轮消息传递只让信息在“直接邻居”间流动,但天气的影响可以跨越数千公里。GraphCast 把上述三步连续做 16 层——每一轮,信息就顺着边向外扩散一层。就像村民会议开了一轮又一轮,消息从邻院传到几条街外、再传到几个村子外。掌握了这个核心机制,接下来就能把完整流水线拆开看:纸条怎么被格式化(编码器)、怎么在会议厅里反复讨论(处理器)、最后怎么宣读结论(解码器)。
- 消息生成发送方把自己的状态映射成一条“纸条消息”,写清“我这里情况如何”。
- 邻居聚合接收方把从四面八方收到的纸条全部相加,得到一条汇总信息。
- 节点更新接收方结合自己的旧状态与汇总消息,得出更了解全局的新状态。
编码器设计:把纸条翻译成标准格式
会议前,每位村民手里攥着十几条原始观测数据,长短不一、格式混乱。直接这样是没法开会的。所以村里定下规矩:所有纸条必须先翻译成统一格式的“编码”,登记在相同式样的本子上。这就是编码器的作用——把原始观测变成机器能高效处理的嵌入向量。
编码器把节点 v 的原始特征向量 x_v(包括 189 个气象变量、静态特征和时间特征)通过一个可学习的线性映射,变成高维嵌入向量 h_v^{(0)},作为第一层消息传递的起点:
GraphCast 的编码器还承担“网格到图”的桥梁作用:三个分辨率网格上的每个单元都要逐一映射成图节点,带上自己的嵌入向量;同时把边界条件等额外信息一并融合进来。经过这一步,103 万个网格单元不再是孤立的坐标点,而是一个个拥有统一“语言”的会议参与者,准备进入最深层的处理器。
- 原始特征向量 x_v节点 v 上归一化后的全部气象变量与静态特征拼成的向量。
- 可学习映射矩阵 W_E训练中不断调整的参数,把 d_in 维特征映射到 d_model 维嵌入空间。
- 偏置项 b_E让输出可以整体平移,增强表达能力。
处理器核心:反复开 16 场村民会议
纸条格式统一了,正式的“社区会议”开始。处理器是整条流水线中最深的部分——16 层 GNN 堆叠,每一层都是一次完整的消息传递。但深层网络有一个经典难题:层数越深,梯度传播越不稳定,模型的效果反而会退化。
村民开会也是如此——如果每轮讨论都推倒重来,16 轮下来肯定一团乱麻。要让每一轮都在上一轮结论上“打补丁”,就需要残差连接:把上一层的状态原样保留,加上本轮 GNN 学到的变化量:
处理器内部还有一个精妙设计:16 层 GNN 共享同一套参数。这就像全村统一一套议事规则——16 轮会议议题不断变化,但大家遵循的讨论逻辑是同一套,参数量因此大幅减少,泛化能力也更强。经过 16 轮讨论,每个节点都收敛到了一个融合了远近信息的隐状态,准备进入最后阶段。
- GNN 层输出第 l 层经过消息传递后对节点状态提出的“修改建议”。
- 残差相加旧状态加上修改建议,得到新状态,相当于在旧结论上打补丁。
- 叠加 16 层反复执行消息传递,让信息在空间上扩散得更远。
解码器输出:宣读最终预报
会议结束,村民回到自家院落,手里攥着只有自己看得懂的“会议纪要”——高维隐状态向量。但邻居们看不懂这些抽象符号。解码器的任务,就是把这些隐状态翻译回人人都能懂的天气数字:温度几度、风速几米每秒、会不会下雨。
解码器是编码器的镜像:先把图节点的隐状态映射回原始网格坐标(图到网格),再通过一个输出头产生两类结果——下一时刻的完整大气状态(6 小时后的温度、风速、湿度等),以及诊断量(如降水概率):
一次前向推演只得到 6 小时预报。要拿到 10 天预报,模型采用“迭代推演”:把刚预测出的 6 小时状态当作新输入,再推下一个 6 小时……循环 40 次。这种“滚雪球”式的自回归预测,让每一步都基于模型自己的最新预测。GraphCast 正是靠这个方案,在约 60 秒内完成 10 天全球预报,精度在 90% 以上的验证指标上超过了传统数值预报系统 HRES。
- 最终隐藏状态 h_v^{(L)}第 L 层(最后层)节点的状态向量,包含经过 16 轮传播后的全局信息。
- 输出权重矩阵 W_D将隐状态维度映射回输出变量维度。
- 输出预报值还原出该网格 6 小时后的全部天气变量。
计算图优化:让村庄会议更高效
103 万个节点、上千万条边,每层消息传递都要在边上做运算——如果不加优化,计算量和显存开销都是天文数字。就像村里开会,如果每个人都给全村人写信,邮局会直接瘫痪。聪明的办法是:只给邻居写信,并把所有信件打包成邮袋集中投递。
第一招是边稀疏化。GraphCast 在 0.25° 细网格上只保留距离约 316 公里以内的边,更远的依赖交给中、粗网格上的长边,每个节点平均只有几十条边。第二招是算子融合:把所有边上的消息计算合并成一次大型矩阵乘法,充分利用 GPU 的并行能力,而不是逐条边循环:
GraphCast 基于 JAX 实现,XLA 编译器会对整张计算图做进一步优化:自动融合算子、消除中间缓冲、调整执行顺序。显存管理上也有巧思——训练时把 103 万节点的上采样、下采样放到不同设备上,按需分配显存。经过这些优化,原本“不可能”的大规模 GNN 天气预报才真正落地。
- 源节点特征矩阵 H_src把所有“发送方”节点的特征堆叠成一个大矩阵。
- 共享消息权重 W_msg所有边共用同一个可学习权重矩阵。
- 一次矩阵乘法GPU 在几毫秒内算出全部边上的消息,再按邻接关系分组求和。
并行训练方法:全村人一起学历史
模型再精巧,也得有“老师”教。GraphCast 的老师是 ECMWF 提供的 ERA5 再分析资料——1979 到 2017 年整整 39 年的全球历史天气场。如何用这批数据教会 103 万节点上的 GNN?答案是:让多个村庄(GPU)同时开工。
最直观的思路是数据并行:把 39 年的样本切成多份,每张 GPU 学一份,各自算出梯度再汇总更新。但图太大时,一张卡存不下完整的图,就需要图切分:把地球表面的节点按空间区块切开分到多张卡上,卡与卡之间只交换切口附近的边界节点状态。
当显存仍然吃紧时,还可以用梯度累积。并不是每个小批次都要立刻更新模型,而是先攒若干个批次的梯度,再统一更新一次参数:
分布式通信同样讲究:卡与卡之间传递的不是整张图,而是边界上的少量节点嵌入,通信量大幅压缩。最终,这套并行训练方案让 GraphCast 在 32 块 TPU v4 上约 4 周完成训练——“学会 39 年全球天气”从不可能变成了现实。
- 梯度 g_k第 k 个小批次数据上计算的损失对参数的偏导数。
- 梯度平均将 K 个梯度求平均,既稳定又具备大批量训练的效果。
- 参数更新沿着平均梯度方向以学习率 η 更新参数。
AI 应用场景
极端天气早期预警
阶段:模型推理与部署
解决的问题:台风路径预测传统上依赖数值模式加人工订正,一次预报要跑数小时,且预报员经验影响大。GNN 天气模型能在 60 秒内滚动推演 10 天,把“临阵磨枪”变成“提前预演”。
具体案例:2023 年北大西洋飓风“李”(Lee)发展期间,GraphCast 提前 9 天就预测出它将在加拿大新斯科舍省登陆,而传统高分辨率预报在 6 天前才给出准确指向。灾害预警部门因此多出整整 3 天应急响应窗口。
新能源发电功率预测
阶段:特征工程 + 推理部署
解决的问题:风电场发电功率高度依赖未来风速预测。传统数值预报更新频率低、分辨率粗,难以匹配单个风场的尺度,导致电网调度压力大。
具体案例:某能源公司把 GraphCast 输出的 10 米风速场作为风电功率预测模型的输入,结合地形、风机功率曲线等特征,将次日发电量预测误差降低了 15%~20%,帮助电网更精准地安排火电备用容量。
气候变化区域研究
阶段:科学模型分析
解决的问题:全球气候模式在区域尺度上的分辨率太粗,“降尺度”(downscaling)需要极高算力,城市尺度的气候风险评估难以落地。
具体案例:研究者基于 GNN 天气模型对城市区域做迭代模拟,结合局地观测数据微调,为城市规划部门绘制了 50 米级的高温风险热力图,识别出哪些街区需要增加绿化与遮阳设施。
Python 演示
import numpy as np def build_grid_graph(height, width): """构建 4 邻接网格图,返回边列表""" edges = [] for r in range(height): for c in range(width): idx = r * width + c if r > 0: edges.append((idx, idx - width)) if r < height - 1: edges.append((idx, idx + width)) if c > 0: edges.append((idx, idx - 1)) if c < width - 1: edges.append((idx, idx + 1)) return np.array(edges) def message_passing(features, edges, w_msg, w_update, num_layers=3): """多层消息传递:邻居消息聚合后更新节点状态""" h = features.copy() degree = np.zeros(features.shape[0]) for i, j in edges: degree[j] += 1.0 for _ in range(num_layers): messages = np.zeros_like(h) for i, j in edges: messages[j] += h[i] @ w_msg messages /= np.maximum(degree[:, None], 1.0) h = h @ w_update + messages return h def main(): np.random.seed(42) height, width = 4, 4 x = np.linspace(0, 2 * np.pi, width) y = np.linspace(0, 2 * np.pi, height) grid_x, grid_y = np.meshgrid(x, y) temperature = 15.0 + 5.0 * np.sin(grid_x) + 3.0 * np.cos(grid_y) land = np.ones((height, width)) land[1:3, 1:3] = 0.0 node_feat = np.stack([temperature / 30.0, land], axis=-1).reshape(-1, 2) edges = build_grid_graph(height, width) w_msg = np.random.randn(2, 2).astype(np.float32) * 0.1 w_update = np.random.randn(2, 2).astype(np.float32) * 0.1 forecast = message_passing(node_feat, edges, w_msg, w_update, num_layers=3) print("初始温度场(摄氏度):") print(np.round(temperature, 2)) print("6小时后预测温度场(摄氏度):") print(np.round(forecast[:, 0] * 30.0, 2).reshape(height, width)) if __name__ == "__main__": main()
edges.append((idx, idx - width))为每个节点连上“北边邻居”,构建邻接边列表,相当于给村庄画道路。messages[j] += h[i] @ w_msg邻居 i 的消息乘以权重矩阵后累加到节点 j,即“消息生成 + 邻居聚合”一步完成。messages /= np.maximum(degree[:, None], 1.0)按邻居数量归一化,防止高连接度节点聚合值过大,是图上的“归一化”。h = h @ w_update + messages节点用自身旧状态乘以更新矩阵,再加上邻居汇总消息,完成“节点更新”。node_feat = np.stack([temperature / 30.0, land], axis=-1)把温度场和陆地掩膜拼成节点特征向量,同时做缩放到同数量级,对应特征编码。
常见误区
误区我听说 GNN 主要用在社交网络推荐、分子性质预测上,气象数据是规整的经纬网格,用 CNN 不就行了?说 GNN 可以做天气预报,怕是硬套概念吧。
正解恰恰相反,气象网格是球面网格,极点附近纬线收缩,CNN 的规则卷积核天然不匹配。GNN 把每个网格视为节点、用边编码真实的空间邻接关系,天然适合球面与多尺度网格。GraphCast 正是在 0.25°、1°、2.25° 三套网格上建图,才同时兼顾了效率和准确性。
为何常见:大多数教程都用社交网络举例,给人留下“GNN=关系数据专属”的印象,忽略了图结构的本质是“任意离散实体 + 成对关系”。
误区既然消息传递是沿着边走,那我把每个节点和全球所有节点都连上边,信息不是最充分吗?为什么还要做“边稀疏化”?
正解全连接图会让每层消息传递的计算量从 O(N+M) 膨胀到近似 O(N²),上千万亿条边的消息计算直接让训练崩溃。更重要的是,远距离影响本来就靠多层传递逐步扩散,单层全连接反而会造成“过度平滑”——所有节点信息趋同,失去局部差异性。GraphCast 用三档稀疏多尺度图,远近兼顾且开销可控。
为何常见:“信息越多越好”的直觉很自然,但没意识到 GNN 的信息传递靠“层数”累积,而不是靠单层边密度堆出来。
误区我理解 GraphCast 输入今天的天气,模型一次前向就能直接吐出未来 10 天的完整天气,就像 ChatGPT 一次生成一篇文章。
正解实际是迭代推演:每步只预测未来 6 小时,然后把预测结果作为下一次输入,循环 40 次才得到 10 天预报。这种自回归滚动设计与训练方式一致——监督信号就是相邻 6 小时的状态变化。看到“60 秒完成 10 天预报”时,要意识到内部发生了 40 次前向。
为何常见:宣传语强调“60 秒”很抓眼球,容易让人脑补成单次前向,忽略了“滚雪球”式的循环推演本质。
误区GraphCast 在 90% 以上的指标上超过 HRES,说明纯数据驱动的 AI 模型已经可以淘汰传统数值预报了,物理方程是不是没用了?
正解两者是互补关系。GNN 模型的训练数据 ERA5 本身就是数值预报同化系统的产物,AI 模型本质上是“用数据拟合物理规律”。而且纯数据驱动在极端罕见事件、数据分布之外的场景仍有风险。业界主流方向是“AI 与物理融合”,把 GNN 的快速推演嵌入传统模式流程,而不是替代。
为何常见:对比实验的宣传数字冲击力强,但忽略了数据来源依赖和极端天气可靠性这两个前提。
误区我只关心模型结构,XLA 编译、图切分、梯度累积那些是工程同学的事,对科学建模本身没影响。
正解恰恰相反,可扩展性决定了模型规模的上限。没有消息矩阵批处理和多尺度稀疏图,103 万节点的 16 层 GNN 根本跑不起来;没有数据并行 + 图切分 + 梯度累积,39 年训练数据在单卡上不可能学完。在 AI for Science 中,工程优化与科学效果是同一件事。
为何常见:教材习惯按“模型—训练—工程”切分章节,让人误以为它们是相互独立的知识点,忽略了它们在下游效果上的耦合。
面试题
Q1. GraphCast 用到的地球网格节点数量级约为?
- A.约千数量级
- B.约万数量级
- C.约百万数量级← 正确答案
- D.约亿数量级
答案:C。GraphCast 以 0.25° 分辨率剖分地球表面,得到 721×1440 个网格,约 103.8 万个节点,即百万数量级。千级和万级太小,无法覆盖全球尺度;亿级则远超实际网格数。
Q2. 图神经网络中“消息传递”的主要作用是?
- A.把节点位置信息互相复制
- B.让邻居信息向目标节点汇聚← 正确答案
- C.压缩每个节点的输入特征
- D.删除图中冗余的多余边
答案:B。消息传递分三步:发送方写消息、接收方汇总所有邻居消息、结合旧状态更新。核心就是把邻居信息汇聚到目标节点,如同村民递纸条交换天气情报。复制位置、压缩特征、删除边都不是消息传递的本职。
Q3. GraphCast 编码器的主要功能是?
- A.把原始气象特征映射成节点嵌入← 正确答案
- B.直接输出未来六小时的降水场
- C.把网格节点数量大幅裁剪压缩
- D.计算预报结果与真值之间的损失
答案:A。编码器通过线性映射 h = Wᵀx + b 把原始气象特征升维成节点嵌入,同时完成“网格到图”的映射。输出降水是解码器的职责;裁剪节点是稀疏化;计算损失是训练阶段的事,与编码器无关。
Q4. 特征归一化处理的主要目的是?
- A.让不同量纲的变量可以公平比较← 正确答案
- B.减少大气变量在模型中的数量
- C.将低分辨率网格提升为高分辨率
- D.让模型无需训练即可做出预测
答案:A。温度是十度量级、气压是千帕量级,若直接用原始值,大数值会淹没小数值。归一化通过 (x−μ)/σ 把各变量统一到同数量级,让模型公平地关注每个变量。它不改变变量数量、不提升分辨率,更不能替代训练。
Q5. 下列属于 GraphCast 大气输入变量的有哪些?
- A.温度场← 正确答案
- B.风场分量← 正确答案
- C.相对湿度场← 正确答案
- D.股票价格
答案:ABC。GraphCast 的节点特征包含 37 个气压层的温度、相对湿度、东西风和南北风分量,以及地表 2 米气温、10 米风、海平面气压等共 189 个大气变量。股票价格不是气象变量,不可能作为天气模型的输入。
Q6. 深层 GNN 中残差连接主要解决什么问题?
- A.网格节点数量过多的问题
- B.深层网络训练退化的问题← 正确答案
- C.气象数据分布不均的问题
- D.分布式通信延迟过高的问题
答案:B。层数加深后梯度传播不稳定,模型效果反而退化。残差连接把旧状态直接加到新状态上,让每一层在旧结论上“打补丁”,梯度可以顺畅回流。GraphCast 正是靠残差连接才把 GNN 稳健地堆到 16 层。
Q7. 为什么 GraphCast 使用多尺度图结构?
- A.可以同时捕获近程和远程的依赖关系← 正确答案
- B.用粗网格长边降低整体计算代价← 正确答案
- C.让不同距离的气象特征各有通道传递← 正确答案
- D.为了把输出分辨率提升到百米级
答案:ABC。0.25° 细网格短边捕获局地过程,1° 与 2.25° 粗网格长边捕获远距离依赖,同时长边数量少、整体计算代价低,相当于不同比例尺地图叠加。多尺度图不是为了提升输出分辨率,输出仍回到细网格。
Q8. GraphCast 单次前向推演的时间步长约为?
- A.大约六小时← 正确答案
- B.大约一整天
- C.大约一星期
- D.大约一个月
答案:A。GraphCast 每次前向只预测未来 6 小时的大气状态,然后将预测结果作为新输入继续推演,循环 40 次得到 10 天预报。6 小时步长是模型训练时监督信号的基本间隔。
Q9. 大规模 GNN 天气模型常用的并行训练方式有哪些?
- A.数据并行分发历史天气样本← 正确答案
- B.图切分按空间区块分配设备← 正确答案
- C.梯度累积攒多个批次再更新← 正确答案
- D.随机删除大量边压缩训练图
答案:ABC。数据并行让每张 GPU 处理不同年份样本;图切分把全球图按空间区块分到多卡,只交换边界节点;梯度累积把多个小批次梯度平均后再更新,缓解显存压力。随机删除边会破坏图结构、损害精度,不是正规并行手段。
Q10. GraphCast 相对传统数值预报 HRES 的优势体现在?
- A.训练数据中人工修正的比例更高
- B.在更强的物理约束下推理更精确
- C.在大多数验证指标上精度领先且更快← 正确答案
- D.完全不依赖历史观测数据即可训练
答案:C。GraphCast 在 90% 以上的验证指标上超过 HRES,且一次 10 天预报只需约 60 秒。它仍依赖 ERA5 历史再分析资料训练,也并非靠更强的物理约束取胜——恰恰相反,它是纯数据驱动模型,靠学习海量历史天气场捕捉规律。