简介:《盘古天气大模型介绍PPT》面向气象AI、算法研发及深度学习应用学习者,围绕盘古天气模型的技术框架与预报价值展开,帮助读者理解AI如何切入中期全球天气预报。压缩包含1个pptx文件,约13.43MB,内容集中,便于查阅与二次整理,也适合技术分享或课程汇报取材。已有1557人学习,反映该主题在算法与人工智能社区受到关注。PPT从数值天气预报(NWP)背景、AI/DL现有工作讲起,重点梳理Pangu-Weather的3D深度网络、地球特定先验与分层时间聚合设计,并延伸至确定性/集合预报、气旋等极端天气案例及未来展望。读者可建立从背景、模型结构到实验验证的整体认知,理解秒级预报、精度提升及台风路径预测位置误差降低20%以上的应用潜力,为深入研读或汇报准备提供参考。
1. 盘古天气大模型反直觉的地方:它预报天气,但一个方程都不解
盘古天气大模型最容易被误读的一点,是它常被归到“用人工智能加速解方程”,但事实并非如此。它一个流体力学方程都不解,而是把几十年的全球大气状态当成一本已经写好的答案册,学的是“当前这张三维天气图,六小时后会变成哪一张”。这件事能成立靠两个支点:一个是把大气垂直方向真正当成第三维来建模的 3DEST 网络,它决定精度上限;另一个是把自回归迭代次数大幅压下去的分层时间聚合,它决定七天预报还能不能看。搞懂这两件事,你既能明白秒级出结果是怎么来的,也能明白它的短板藏在哪儿。
2. 从解方程到拟合映射:天气预报的两个死结是怎么被绕开的
传统数值预报的流程并不神秘:把大气切成网格,在每个格点上解一组偏微分方程,用超级计算机一步步往前积分。这套方法撑了半个多世纪,精度一直在稳步提升,问题在于它的误差来源是结构性的,并非算力不够。绕开这两个死结,才是数据驱动路线值得投入的真正理由。
2.1 参数化:写不进方程的那部分才是误差源头
大气模式的水平分辨率通常在几公里到几十公里,而积云对流、云微物理、边界层湍流、辐射传输这些过程的特征尺度远小于网格间距。网格无法解析它们,只能“参数化”,也就是用一套经验公式,把次网格过程的效果折算成网格尺度上的源汇项。这些公式里有大量可调参数,靠观测和试验整定,本质上是用人的经验去补物理方程管不到的地方。
麻烦的地方在于,参数化引入的不是随机噪声,而是系统性偏差。它在积分过程中被反复放大:今天对某片海域对流强度的估计偏强,三天后就会变成一条错误的高空槽,七天后整张环流形势都跑偏。换句话说,误差从一开始就藏在方程之外,算得再准也逃不掉。数据驱动路线选择的做法是,把这段“次网格到网格”的映射交给网络,从海量历史数据里自己拟合。
提示:这里容易形成误解,以为深度学习“比物理更准”。网络学到的是历史数据统计意义上的对应关系,物理约束并没有消失,只是转移到了数据里。
2.2 自回归迭代:为什么第 10 天一定会崩
数据驱动模型做预报是自回归的:单步模型学一个映射 f,然后拿自己的输出当下一步输入,x(t+1) = f(x(t))。这和语言模型逐 token 生成是一个结构,只不过这里是逐“天气态”生成。单步误差小,不代表多步误差小,原因有两个。
第一是大气本身的混沌性,初始场的微小误差会以大约几天翻一倍的速度增长,这是可预报性上限的物理来源,任何方法都绕不开。第二是训练与推理之间的分布错配:训练时模型看到的永远是再分析资料里那种物理自洽的真实状态,推理时它看到的是自己刚生成的、带着细微畸变的状态。一旦输入偏离训练分布,模型的输出偏差就会比训练时更大,下一步输入偏得更多,形成正反馈。这个现象在序列生成里叫曝光偏差,天气模型上表现得尤其明显,因为变量多、耦合强。
所以提升多步预报的关键,是让模型少走几步;只压低单步误差并不够。这正是分层时间聚合要解决的问题,后面单开一章。
2.3 再分析数据:把几十年的天气压成一张监督学习表
训练需要一个“标准答案”。气象领域恰好有这个东西:把地面站、探空、飞机报、卫星辐射率等稀疏且不均匀的观测,用四维同化技术融合到模式网格上,得到时空连续、物理自洽的分析场,这就是再分析资料。它从二十世纪四十年代一直做到现在,每六小时一个时次,覆盖全球。
变量组织方式对网络设计影响很大。高空层一般取位势、温度、比湿、纬向风、经向风五个变量,分布在十几个标准气压层上;地面层取 2 米温度、海平面气压、10 米纬向风、10 米经向风四个变量。输入是某个时刻的全套变量,输出是下一时刻的全套变量,两者结构完全同构。这意味着任务天然是“图到图”的稠密回归,不需要人工标注,任意两个相邻时次就是一对样本,样本量能堆到百万级。
同构输入输出还带来一个隐性好处:模型内部所有中间表示都可以保持同样的空间形状,不需要编解码器做维度变换,参数量能全部花在“理解大气状态怎么演化”上。
2.4 值得重做一遍的理由:快一万倍只是表面
相比传统方案,数据驱动路线的第一个优势是速度。业务级数值预报要在超算上跑几十分钟到几小时,而一次网络前向在秒级完成,两者差着三到四个数量级。速度的意义不只是“快”:它让集合预报变得廉价。传统方法做集合预报要跑几十个成员,算力成本让人心疼;数据驱动模型可以把几十个成员在一次批处理里出完,用来估计预报的不确定性。
第二个优势是独立性。数据驱动模型和偏微分方程方法走的是完全不同的技术路线,它们的误差模式不相关。两套结果放在一起比对,预报员能看出哪些形势是“两边都这么说”的高置信情况,哪些是“分歧很大”的危险情况。这种互补价值,比单纯追求某一项指标高出几个点更实在。
第三是端到端延展的空间。当前主流做法是把同化、预报、后处理三段分开,各自用各自的算法,AI 只替换中间那段。长远看,这三段都可以用网络替换,最终变成从观测直接到预报产品的单一通路。盘古天气大模型这一步做的是中间那段,但整体架构是朝着端到端留了接口的。
早期的数据驱动方案各有取舍:有的在频域做全局混合,计算效率高,但对高频细节不够敏感;有的把球面网格建成图做消息传递,物理直觉清楚,但极区附近网格度不均匀,消息传递的权重很难统一。盘古天气大模型选的是第三条路:把大气当成一个真正的三维体数据来处理。
3. 3DEST 网络:气压层为什么必须是第三个维度
把天气数据喂给视觉网络,最省事的做法是把每个气压层当成一张独立的二维图,分别跑,再在垂直方向拼起来。这个做法能跑通,早期不少工作也确实这么干。但它有三处硬伤,而且都不小。
3.1 逐层处理的隐性代价:垂直切变与推理次数
第一处是物理耦合被切断。辐射传输、对流调整、垂直动量输送,这些过程本质上都发生在垂直方向上,而且是跨层的。二维卷积的感受野只在同一层内,层与层之间的信息只能靠最后的浅层融合——通常是几个 1×1 卷积或者简单相加——这种“事后融合”的表达能力,远不如让网络在每一层特征里就带着跨层信息。
第二处是推理成本线性增长。十几个气压层就要跑十几次前向,或者把它们拼进 batch 维,显存占用翻十几倍。想加层、想上更高垂直分辨率,成本立刻失控。
第三处最隐蔽,也最容易在看指标时被忽略:各层独立预测,输出的场在相邻层之间可能不连续。真实大气里,风场随高度是连续变化的,温度层结也有明确的物理约束。如果模型对 500 hPa 和 400 hPa 分别给出方向差很大的风矢量,算出来的垂直切变就是虚假的,下游用它推涡度、散度、抬升条件,结果全废。
三维网络直接解决这三个问题:每个神经元的感受野天生跨层,一次前向出全部层,层间连续性由网络结构本身保证。至于代价——显存和计算量——得靠下面的切块策略压回去。
3.2 立体 patch 与窗口注意力:上千万个体素怎么塞进显存
算一下量级。0.25 度全球网格是 1440×721,十几个气压层,合起来约一千三百万个体素。如果每个体素当一个 token 做全局注意力,注意力矩阵是 N²,一亿亿级别的元素,任何加速卡都放不下。
第一步是立体 patch embedding。把相邻的若干体素压成一个 token,比如在经度、纬度、层三个方向各取几格,一个 token 就代表一小块三维空间。这一步把 token 数降一到两个数量级,同时每个 token 内部已经混合了局部三维信息。工程上有个小细节:十几个气压层往往不能被 patch 深度整除,常见做法是先把层数补齐到可整除的数字,比如复制最顶层或补零,反算回物理量时再裁掉。补哪一侧、补什么值,会直接影响顶层和底层的预报质量。
第二步是窗口注意力。即使压到几十万 token,全局注意力还是太重,于是把三维 token 网格切成互不重叠的立方窗口,注意力只在窗口内计算。窗口大小要按三个方向的物理尺度来定,而不是随手取个立方体——水平方向一格代表的实际距离随纬度剧烈变化,垂直方向一层的厚度从几十米到几公里不等。
import torch def window_partition_3d(x, win): """把 (B, D, H, W, C) 切成互不重叠的三维窗口。 win = (wd, wh, ww) 是窗口在三个方向上的边长,单位是 patch 数。 """ B, D, H, W, C = x.shape wd, wh, ww = win # 先按窗口边长重排,把窗口内部的三个轴与窗口编号的轴分开 x = x.view(B, D // wd, wd, H // wh, wh, W // ww, ww, C) # 把三个"窗口编号"轴提到前面,拼成新的 batch 维 x = x.permute(0, 1, 3, 5, 2, 4, 6, 7).contiguous() # 展平后每个窗口是一段长度为 wd*wh*ww 的 token 序列 return x.view(-1, wd * wh * ww, C), (D // wd, H // wh, W // ww)这段代码的关键在permute的参数顺序(0, 1, 3, 5, 2, 4, 6, 7):第 0 位是 batch,第 1、3、5 位是三个方向的窗口编号,第 2、4、6 位是窗口内部的三个坐标,第 7 位是通道。这样重排之后,每个窗口内部的 token 在内存里连续,展平后的窗口内 token 顺序与后面位置偏置索引的计算顺序必须严格一致——这两处只要对不上,模型照样能训练,损失也能降,但学到的空间关系是错位的,表现为预报场出现细微但系统性的位移偏差,而且非常难查。
窗口切分带来一个新问题:窗口之间不通信了。解决办法是移位窗口,也就是下一层把切分网格整体平移半个窗口,让新的窗口跨越原来的边界。这里有个容易翻车的地方:三个维度都要移,只移水平两个方向,垂直方向的层间边界永远打不通,高层和低层的信息就又断了。
3.3 地球特定先验:位置编码为什么不能交给模型自己学
图像任务里,位置编码通常是让模型自己学一张可训练的表:第 3 行第 5 列这个位置,学一个向量。这在图像上完全合理,因为图块的位置没有物理含义。天气数据不一样,每个体素都有一个绝对坐标,而且这个坐标和变量值强相关。
三件事决定了不能照搬图像的做法。其一,球面网格不均匀,同样的经度差,在赤道对应的实际距离是一个量级,在极区可能只剩几分之一,网格在极区高度收敛。其二,气压层不是等间距的,从 1000 hPa 到 925 hPa 的厚度和从 150 hPa 到 100 hPa 的厚度差着好几倍,层与层之间的物理距离完全不对称。其三,位势高度随纬度有数公里的系统性梯度,温度随气压层单调下降,这些先验不体现在位置编码里,网络就得靠参数量去硬背。
如果真给每个格点学一个自由的位置向量,参数量会膨胀到不可接受,而且学到的是一张只适用于当前分辨率的查表——换个网格分辨率就全废。盘古天气大模型的做法是改用相对位移偏置:注意力权重里加一项,这一项由查询和键在三个方向上的相对位移 (Δ层, Δ纬, Δ经) 决定,同一组位移共享一个标量偏置。偏置表的大小只和窗口尺寸有关,和全球分辨率无关,换分辨率不用重训位置部分。
import torch def rel_pos_bias_index(wd, wh, ww): """构造三维窗口内所有 token 对的相对位移索引,用于查偏置表。 返回形状 (N, N),N = wd*wh*ww,取值落在偏置表的扁平化下标空间。 """ # 窗口内每个 token 的三维坐标,顺序必须与 window_partition_3d 展平后一致 d = torch.arange(wd)[:, None, None] h = torch.arange(wh)[None, :, None] w = torch.arange(ww)[None, None, :] idx = (d * wh * ww + h * ww + w).reshape(-1) # 线性编号 coords = torch.stack([idx // (wh * ww), (idx // ww) % wh, idx % ww], dim=-1) rel = coords[:, None, :] - coords[None, :, :] # (N, N, 3),有正有负 rel = rel + torch.tensor([wd - 1, wh - 1, ww - 1]) # 平移到非负区间 # 压成一维,去查形状为 (2wd-1, 2wh-1, 2ww-1) 的可训练参数表 return (rel[..., 0] * (2 * wh - 1) + rel[..., 1]) * (2 * ww - 1) + rel[..., 2]偏置表本身是一张形状(2*wd-1, 2*wh-1, 2*ww-1)的参数张量,元素个数只有几千个,相比动辄上亿的注意力权重可以忽略。但它的物理含义很重:它告诉网络“在垂直方向上相隔两层、水平方向相隔一格的这两个位置,应该有多强的关联”,而且这个先验在全球任何位置都通用。这就是“地球特定”这个词的实际落点——把球面几何和气压层结构作为先验固化进结构里,能共享的部分尽量共享,只让真正需要变化的部分用参数去学。
4. 分层时间聚合:把“少迭代几次”做成一个调度问题
第 2 章说过,多步预报崩掉的主要机制是迭代次数太多、误差在自回归里滚雪球。既然单步误差降不下去多少了,那就换个方向:能不能用更少的步子走完同样的时间跨度。
4.1 误差随迭代步数增长的定量直觉
假设单步模型训练到 6 小时时效,做七天预报需要 28 次迭代。单步误差哪怕只有百分之一量级的增长,28 次方之后也是显著放大;何况真实大气的误差增长是超线性的,越过某个时效之后会迅速饱和到“气候态水平”,也就是预报彻底失去信息量。
这里有个反直觉的推论:把单步误差从 1.00 降到 0.99,收益远小于把 28 步降到 7 步。工程直觉上大家总想先把单个模型调好,但实际上调度策略的杠杆更大。分层时间聚合正是抓住了这个杠杆——它不去改网络,而是改“用哪个网络走下一步”。
4.2 四个 lead time 模型如何分工
具体做法是训练四个结构相同、参数独立的模型,分别以 1 小时、3 小时、6 小时、24 小时为预报步长。它们不是同一个模型换输入间隔,而是各自从头训练——因为不同步长对应的动力学过程不一样。1 小时步长的模型看到的主要是小尺度 Adjustment 过程和边界层日变化,细微但幅度小;24 小时步长的模型看到的是大尺度环流的日演变,幅度大但细节糊。让一个模型同时兼顾两者,能力会被摊薄。
代价很直接:训练成本四倍,权重量四倍。收益是推理时可以自由组合。这也解释了为什么这套方案宣称能“按需求和算力自适应抽取不同规模的模型”——手里有四个档位,想要快就全用 24 小时模型,想要精度就在尾巴上补短步长模型,灵活度来自模型库本身,不需要重新训练。
4.3 贪心调度的代码与边界条件
调度问题可以形式化成:给定总预报时长,用 {1, 3, 6, 24} 这四个面额凑出这个数,要求步数最少。
LEADS = [24, 6, 3, 1] # 训练好的四个模型,单位小时,从大到小 def plan(total_hours): """贪心分解:每次挑不超过剩余时长的最大步长模型。""" steps, remain = [], total_hours while remain > 0: lead = next(l for l in LEADS if l <= remain) # 最大可用步长 steps.append(lead) remain -= lead return steps for h in (6, 24, 100, 168): s = plan(h) print(f"{h}h -> {len(s)} 步: {s}") # 6h -> 1 步: [6] # 24h -> 1 步: [24] # 100h -> 6 步: [24, 24, 24, 24, 3, 1] # 168h -> 7 步: [24, 24, 24, 24, 24, 24, 24]七天预报从 28 次迭代压到 7 次,这是整条流水线上单项收益最大的一处改动。
贪心在这里能得到最优解并非巧合。这组面额满足“后一个面额不小于前一个的两倍”(3 ≥ 2×1,6 ≥ 2×3,24 ≥ 2×6),这个条件保证了贪心策略给出的就是步数最少的分解。换成 {1, 5, 11} 这种不满足条件的组合,贪心就会给出次优解——所以调度表的设计本身也有讲究,四个步长的取值不能随便挑。
不过要提醒一句:步数最少不等于总误差最小。24 小时模型的单步误差确实比 6 小时模型大,理论上用四次 6 小时可能更精细。实际测下来,减少迭代次数带来的收益盖过了单步误差的损失,所以这条路走通了。但这个结论必须用验证集确认,不能当成先验保证——换一套数据、换一个预报变量,最优组合可能就不一样。
5. 复现这类模型最容易翻车的五个地方
理论看着清楚,真动手的时候坑都藏在数据管线和评估口径里。这几条是这类工作里反复出现的问题,每条都按“看到什么现象、根子在哪、怎么改”来说。
5.1 拿 6 小时模型直接滚 7 天
现象很典型:前 48 小时预报场还挺像样,第 3 天开始整体变“糊”,细节消失,第 5 天之后出现物理上不可能的值——负的比湿、超过上限的风速、海平面气压降到不合理区间。指标上表现为 RMSE 在第 3 天左右突然抬头。
根子是两个机制叠加。一是自回归的曝光偏差,模型在训练时从没见过自己产生的畸变状态,一旦输入偏离分布,输出偏差比训练时更大。二是没有物理约束,网络是纯回归,输出什么值都不违反它的损失函数,湿度为负在数学上完全合法。
改法有三层:调度上必须用 24 小时模型走主步,剩余不足 24 小时的部分用 6/3/1 补齐,绝不能拿单一步长硬滚;输出层加物理裁剪,湿度限在 [0, 饱和值]、风速限在合理上限;训练时在输入里加入自己前几步的输出做数据增强,让模型提前见过“脏”输入,能显著缓解曝光偏差。
5.2 归一化统计量没按变量和层次分开
现象是训练损失降得很漂亮,但高层变量误差大得离谱,或者地面气压这一项的误差压过了所有高空变量,导致模型只顾着拟合气压。
原因是量纲差得太狠。海平面气压在 10⁵ Pa 量级,风速在 10¹ m/s 量级,比湿在 10⁻³ kg/kg 量级,直接混在一起算统计量,小量纲变量在损失里几乎不起作用。更要命的是同一个变量在不同气压层的方差也不同:高层温度的自然变率比低层小得多,用全局标准差归一化,高层的信息会被压平。
正确做法是每个变量、每个气压层单独统计均值和标准差,训练集上算一遍存成表,推理时严格用同一张表反归一化。
import numpy as np # stats 的形状: (n_vars, n_levels),由训练集统计而来,必须与推理时严格一致 def normalize(x, stats): mean, std = stats["mean"], stats["std"] return (x - mean) / std # 广播到 (B, n_vars, n_levels, H, W) def denormalize(x, stats): return x * stats["std"] + stats["mean"]有个容易忽略的点:统计量只能用训练集算。用全量数据算统计量,等于把验证期和测试期的信息泄漏进归一化,指标会虚高,而且这种泄漏在代码审查里极难发现。
5.3 经度接缝没处理,日期变更线上出现条带
现象很直接:预报场在 180 度经线附近出现一条竖直条带,那一列的误差比周围高一个数量级,画成图非常显眼。
原因是网格存储的首尾两列在物理上是同一条经线,但在张量里是距离最远的两列。patch 切分和窗口注意力都按张量相邻关系处理,于是这条接缝被当成“两个不相干的远端”。如果还用了移位窗口,接缝附近的窗口内容会更乱。
改法是在经度方向做周期填充,或者在前向时对最后一维做 roll,让首尾真正接上。计算损失函数时要记得把填充部分裁掉,否则接缝处的权重会被重复计算两次。
import torch # 输入 x 形状 (B, D, H, W, C),W 是经度方向,首尾物理相接 x_pad = torch.cat([x[..., -1:, :], x, x[..., :1, :]], dim=-2) # 两侧各补一列 # 前向结束后裁掉补的部分,保持输出形状与输入一致5.4 气压层顺序与垂直插值方式搞反
现象是位势高度场整体偏移几百米,或者高层变量的误差符号反了,但低层看着正常。
根子有两个。一是层的存储顺序,有的数据集按气压从大到小(1000 → 50),有的反过来,代码里如果一处假设升序、另一处假设降序,垂直方向的卷积和偏置索引就全乱了。二是垂直插值,把不同来源的数据统一到标准气压层时,如果用气压线性插值,高层误差会很大——因为大气密度随高度近似指数衰减,物理上应该在 log(p) 坐标下插值。
改法是:在数据元信息里显式记录层序,读取时立刻统一成一种约定,之后所有代码只认这一种;插值一律在 log 气压坐标下做;凡是涉及垂直方向索引的地方(包括 3.3 节的相对位移偏置),都写单元测试固定住方向。
5.5 用全球平均 RMSE 下结论
现象是对着自己的结果和公开指标一比,差了一大截,怀疑实现有问题,反复查了几天发现实现没错,是评估口径不同。
三个常见偏差。第一,没有纬度加权。全球网格上高纬度的格点在数量上被过度计数,而高纬度的预报误差通常更大,直接平均会把结果拉偏。标准做法是按 cos(纬度) 加权。第二,初始时刻没对齐。业务预报按 00/06/12/18 UTC 起报,如果自己的评估用随机时次起报,和公开指标根本没有可比性。第三,把不同步长的模型混着比,用 24 小时模型的 24 小时结果去对别人 6 小时模型滚四步的结果,这个比较没有意义。
import numpy as np def lat_weighted_rmse(pred, true, lat): """pred/true 形状 (..., H, W),lat 是长度 H 的纬度数组(单位:度)。""" w = np.cos(np.deg2rad(lat))[:, None] # 面积权重,与经度无关 w = w / w.mean() # 归一化,便于跨变量比较 err = (pred - true) ** 2 return float(np.sqrt((err * w).mean()))报告结果时,我一般会强制拆成三个维度:按变量、按气压层、按预报时效。只给一个总分,什么问题都看不出来——总分好看但高层一塌糊涂的模型,在业务上是不能用的。
6. 速度换来了什么:这套设计的取舍边界在哪
把三处设计取舍摆在一起看,思路就很清楚了。
| 取舍点 | 选择 | 换来了什么 | 放弃了什么 |
|---|---|---|---|
| 网络维度 | 三维立体建模 | 跨层物理耦合、层间一致、一次前向出全部层 | 显存与算力,必须靠 patch 与窗口注意力压回去 |
| 位置编码 | 相对位移偏置,三方向共享 | 参数量小、跨分辨率可迁移、球面几何先验内建 | 表达自由度,无法针对局部特殊地形单独建模 |
| 时间推进 | 四个步长模型 + 贪心调度 | 七天预报从 28 步压到 7 步,可按算力裁剪 | 四倍训练成本与权重存储 |
| 方法论 | 纯数据驱动 | 秒级出结果,与方程方法误差互补 | 可解释性,以及数据分布外的行为无保证 |
最后一行是真正的边界。这类模型学的是再分析资料的输出分布,而再分析资料本身是同化系统的产物,带着同化系统的系统性偏差。模型会把这些偏差一起学走,并且因为它是纯回归,外推时不会有任何“我觉得这里不对劲”的自我怀疑。在观测稀疏的海面和高原、在训练期很少出现的极端事件、在气候态本身发生漂移的情形下,它的表现没有理论保证——这一点和数值模式有本质区别,后者至少在物理守恒上是被约束住的。
所以验证这套东西不能只看一条 ACC 曲线。我一般会做三件事:把误差按纬度带切开看,海洋和陆地上分别报;挑几个极端个例(强台风、爆发性气旋)做逐时次回放,看路径和强度演变的偏差是不是有系统性偏向;再检查集合成员的离散度与实际误差是否匹配,离散度远小于误差说明模型过度自信,这种模型给出的“高置信预报”最危险。
从那以后我每次评估一个新的气象模型,都强制走一遍“分纬度带 + 分层次 + 极端个例回放”这三步,不管总分多好看。希望帮到你。
本文还有配套的精品资源,点击获取