简介:面向本地部署气象大模型的研究者与开发者,这份项目代码资源围绕Pangu、Fuxi、Fengwu、GraphCast、FourCastNet等主流模型,提供了一套轻量的入门指引。资源压缩包仅5KB,共含2个文件:一个HTML说明页和一个inscode配置文件,前者用于查看整体部署流程与环境要求,后者可用于快速调起可运行的代码框架。虽然包体不大,但内容组织紧凑,已有133人学习/下载,适合希望在本地环境复现气象大模型推理、但不想从零查资料的AI或气象领域学习者。
该资源贴合作者实测环境(Ubuntu 18.04.6 LTS + Anaconda 3 + CUDA 11.8 + libcudnn 8),从创建虚拟环境、安装依赖库,到添加各类模型并下载预训练权重,再到接入ERA5输入数据,均有明确步骤说明。针对GPU调用失败、依赖版本不匹配、Fengwu需手动安装等常见问题,也整理了对应的排错与安装指南。此外,关于如何通过CDS获取ERA5数据并驱动模型进行预报,资源中也提供了衔接思路,可以帮助使用者缩短环境搭建摸索周期,更快进入实际模型运行与结果分析阶段。 气象大模型本地部署,这个话题这两年热度一直很高。网上教程确实不少,但我发现一个普遍问题:大多停在“装好依赖、跑通官方demo”就结束了,真到要把开源项目代码搬到自己机器上、换成自己的数据、输出业务需要的预报产品,中间那一段几乎没人讲。这篇文章就围绕本地部署气象大模型的完整链路来写,包含硬件选型、环境配置、气象数据准备、项目代码拆解和最后的推理调优。适合两类人:一是想自建气象预报能力但还没动手的开发者,二是已经在跑GPU服务器、想把手头模型真正用起来的工程师。
1. 为什么非要在本地跑气象大模型:云端API做不到的三件事
现在很多云平台都提供了气象大模型的API接口,输入经纬度和时间范围,返回未来几天的预测结果。既然API这么方便,为什么还要折腾本地部署?我的答案很直接:因为API解决不了三类实际诉求,而这恰恰是业务落地时最常见的需求。
1.1 批量历史回算:API按次收费,本地按电费计
做农业气象服务、保险定损或者新能源功率预测的时候,经常需要回算过去几个月的逐小时气象场,用来和实际观测数据做对比验证,或者补全历史业务样本。这种回算动辄几千步,跑完一个夏季就是一两个月的数据量。云端API按次收费,单次预测报价看起来不高,乘上几千次调用就非常可观,而且还有并发限制,经常你发十个请求就被限流了,进度完全不可控。
本地部署之后,同样的回算任务就变成“一次性投入硬件,之后按电费跑”。只要把checkpoint和预处理管线搭好,回算多少天只是时间问题,边际成本几乎为零。我自己算过一笔账:某主流气象API单次预测在5到8元,回算一年8760个时次,成本接近五万元;一台二手RTX 4090整机也就三万元出头,跑同样的回算任务还更灵活。如果你有持续性回算需求,本地部署几乎是必然选择。
1.2 业务定制与内网环境:黑盒接口解决不了的事
第二个痛点是定制化。API返回的是黑盒结果,你只能拿到预测字段,但实际业务系统往往要改输入变量、做区域裁剪、把预测结果插值到站点、再叠加自己的订正算法。这些操作在云端只能通过有限的参数完成,遇到模型把某个变量预测偏了,你想看一下中间层特征都没办法。
更关键的是部署环境。很多单位的业务网和公网隔离,气象数据本身也有使用规范,不能随意传到第三方平台。这些场景下,本地部署不是“可选优化”,而是唯一能走通的技术路线。模型权重放在内网服务器上,数据从自己的存储里读,推理结果直接落业务库,整个过程不依赖外网,安全性和可控性都掌握在自己手里。
1.3 什么情况不建议本地部署
当然,本地部署不是万灵药。如果你只是临时验证一个想法,或者团队没有GPU运维经验,我反而不建议一上来就自建——先买API额度跑通业务模型,确认收益后再投入硬件更稳妥。另外,如果你需要的预报时效和区域很固定,云API通常能覆盖,运维成本也低得多。本地部署适合的是那些“长期、批量、可定制”的场景,这点判断清楚了再动手,能少走很多弯路。
2. 硬件选型与运行环境:先把GPU和CUDA这关过了
确定要本地部署之后,第一关就是硬件和环境。和本地部署大语言模型那种“显存越大越好”的直觉不同,气象大模型的显存敏感点非常具体:它由输入网格尺寸决定,算清楚这个,你的显卡预算基本就定了。
2.1 显存是第一指标:一个输入张量就占多少
主流气象大模型的输入基本都是0.25°×0.25°的全球网格,纬度方向721个格点,经度方向1440个格点,一共约104万个格点。如果输入包含69个通道(多个等压面的位势高度、温度、风分量加地面变量),按float32计算,单单一个输入张量就是69 × 721 × 1440 × 4字节,约280MB。
这只是原始输入。模型前向传播过程中,中间激活值通常是输入量的好几倍,再加上模型权重本身,一张24GB显存的显卡,跑完一个完整预测大概能剩下不到40%的余量。所以我给身边人的选型建议是:16GB是底线,24GB是安心线,40GB可以非常从容。
2.2 显卡与版本选型参考
按照上面的逻辑,不同显卡的适用情况我整理成了一张表,方便你对着自己的预算看:
| 显卡配置 | 显存 | 适合场景 | 备注 |
|---|---|---|---|
| RTX 4060 Ti 16GB | 16GB | 小区域裁剪推理、原型验证 | 全球网格全量推理勉强,需要谨慎 |
| RTX 4090 24GB | 24GB | 单个模型全量推理 | 性价比很高的选择 |
| A5000 / A6000 24GB+ | 24GB~48GB | 多模型并行、开发调试验证 | 稳定性好,适合长期跑任务 |
| A100 40GB | 40GB | 大规模回算、批量预测 | 显存充裕,基本不受限 |
| 纯CPU | — | 仅代码调试、流程验证 | 一次推理可能几十分钟,不建议生产用 |
环境方面,我的推荐组合是Ubuntu 22.04 + Python 3.10 + CUDA 12.1 + PyTorch 2.x。这套组合兼容性最稳,网上能查到的坑也基本都被踩过了。
2.3 环境自检:驱动、CUDA、PyTorch三件套
环境配置最容易翻车的地方是版本错位。显卡驱动、CUDA运行时、PyTorch这三者只要有一个版本不匹配,torch.cuda.is_available()就会返回False,或者直接报undefined symbol错误。检查顺序建议这样来:
nvidia-smi # 看驱动版本和显卡状态 nvcc --version # 看CUDA编译版本 python -c "import torch; print(torch.__version__, torch.cuda.is_available())"先确认显卡能被系统识别,再确认CUDA版本,最后看PyTorch能不能调用GPU。如果最后一步返回False,大概率是PyTorch装成了CPU版本,重新用对应CUDA的index安装就行。另外,气象数据处理库的依赖也要提前装好:xarray、cfgrib、eccodes、netCDF4,这几个是后面处理GRIB和NetCDF数据的主力,缺一个都会在数据读取时报出莫名其妙的错误。
3. 气象数据准备:GRIB、NetCDF与0.25°网格的隐藏工作量
把模型代码跑通只需要半天,但把气象数据处理好,可能得花两三天。这个比例是我实际做过很多次项目之后的体感,一点都不夸张。气象大模型训练和推理的输入从来不是一张干净的图片,而是经过严格格式约定、单位约定和网格对齐的变量集。
3.1 数据源选择:ERA5回算与GFS实时两条路
气象大模型常用的输入数据有两类:再分析资料和实时预报资料。再分析资料最常用的是ERA5,它把历史观测和数值同化结合,产出自1940年以来、0.25°分辨率的全球逐小时气象场,适合做回算和验证。实时预报则常用GFS,它是美国国家环境预报中心发布的全球预报产品,适合接入业务系统,每天更新多次,时效到未来10天以上。
ERA5数据通过CDS(Climate Data Store)获取,注册账户后可以申请API key下载;GFS则可以直接从NCEP的公开接口拉取。实际体验下来,数据下载是整个流程里最耗时的一环——一个覆盖完整变量集合的ERA5年数据能到几十GB,下载前一定规划好磁盘空间,建议至少留1TB。
3.2 读取GRIB的正确姿势
气象数据里最折磨人的就是GRIB格式。它是WMO定义的二进制格式,把变量名、层级、时间、统计类型全部编码在二进制元数据里,直接用普通方式根本读不了。Python生态里最常用的方案是cfgrib引擎加eccodes库,让xarray能够透明读取GRIB文件:
import xarray as xr # 读取单个变量,避免一个大文件混多个变量时解析失败 ds = xr.open_dataset( "era5.grib", engine="cfgrib", backend_kwargs={"filter_by_keys": {"shortName": "t"}} ) print(ds)这里有个很容易踩的坑:GRIB文件经常一个文件里同时包含温度、风、气压等多个变量和多个气压层,直接xr.open_dataset很容易报key 'shortName' not found之类的错误。稳妥的做法是按shortName或typeOfLevel参数过滤着读,虽然慢一点,但稳定可靠。
3.3 变量、层级与单位的对齐清单
模型输入不是“有数据就行”,而是要求一套严格对齐的变量组合。以常见气象大模型为例,输入通常包含多个等压面上的位势高度、温度、纬向风、经向风、比湿,以及地面气压、2m温度、10m风等变量。每个变量的网格范围、网格分辨率、层级顺序、单位都必须和模型训练时保持一致。
我的建议是提前整理一张“变量对齐清单”,写进配置文件里,不要靠脑子记:
| 变量名 | GRIB shortName | 层级 | 单位 |
|---|---|---|---|
| 位势高度 | z | 1000hPa ~ 50hPa | gpm |
| 温度 | t | 1000hPa ~ 50hPa | K |
| 纬向风 | u | 1000hPa ~ 50hPa | m/s |
| 经向风 | v | 1000hPa ~ 50hPa | m/s |
| 比湿 | q | 1000hPa ~ 50hPa | kg/kg |
| 地表气压 | sp | 单层 | Pa |
| 2m温度 | 2t | 单层 | K |
| 10m风分量 | 10u / 10v | 单层 | m/s |
单位是重灾区。有的数据源把温度给成摄氏度,有的给开尔文;气压给百帕还是帕也经常搞混。模型训练时用的是标准化之后的特征,推理时如果单位不对,预测结果会直接漂移,而且这种错误很难通过肉眼发现。我每次拿到新数据源都会先做一个极值检查,比如温度场是否在合理物理范围内,超过就停下来排查,这个习惯帮我省了不少返工时间。
4. 项目代码拆解与推理主流程:从仓库克隆到拿到第一张预报图
环境就绪、数据到位之后,终于可以碰项目代码了。拿到一个开源气象大模型的仓库,先别急着python inference.py,花十分钟把目录结构和入口逻辑看一遍,比你盲目试错高效得多。
4.1 一个典型气象大模型仓库的结构
我见过的气象大模型项目代码,结构上大同小异,通常是下面这样:
weather-model/ ├── configs/ │ └── inference.yaml # 推理配置 ├── src/ │ ├── model.py # 模型定义 │ ├── data_loader.py # 数据读取与预处理 │ ├── inference.py # 推理入口 │ └── utils/ # 工具函数 ├── checkpoints/ │ └── model_weights.ckpt # 预训练权重 ├── stats/ │ ├── mean.npy # 训练集均值 │ └── std.npy # 训练集标准差 └── requirements.txt其中stats/目录最容易被人忽略,但它恰恰决定推理成败。气象大模型的输入要做标准化,也就是减均值除方差,这个均值和方差必须来自训练集统计,不能用你自己的数据瞎算。用错统计量,模型预测会快速发散,典型症状是输出一会儿就全是NaN。
4.2 推理主流程:加载、标准化、滚动预测
推理主流程可以概括为三步:加载checkpoint、标准化输入、滚动预测。所谓滚动预测,是指模型每次只预测下一个时间步,然后把预测结果拼回输入序列,作为下一步的输入。这是气象大模型和图像分类模型的本质区别,类似于语言模型里逐token生成。
核心代码大致长这样:
import torch import numpy as np model = load_model("checkpoints/model_weights.ckpt") model.eval() mean = np.load("stats/mean.npy") std = np.load("stats/std.npy") def normalize(x): return (x - mean) / std def denormalize(x): return x * std + mean with torch.no_grad(): for step in range(24): # 预测未来24个时间步 input_tensor = torch.from_numpy(normalize(field)).float() input_tensor = input_tensor.unsqueeze(0).cuda() pred = model(input_tensor) # 输出当前时间步预测 pred = denormalize(pred.cpu().numpy()) predictions[step] = pred # 滚动:丢掉输入序列里最旧的一帧,拼上最新预测 field = np.concatenate([field[:, 1:], pred], axis=1)注意推理全程要包在torch.no_grad()里,否则每一帧都会记录梯度,显存会被中间变量撑爆。另外,model.eval()一定要调用,它会让Dropout和BatchNorm切到推理模式,否则结果会随机抖动。
4.3 输出与可视化:先看到图再谈精度
第一次跑通之后,不要急着分析精度,先做一张可视化图。用matplotlib和cartopy把预测出的温度场或位势高度场画出来,看看等值线是否平滑、是否有明显的错误极值。这一步能帮你快速发现数据对齐、单位转换等基础问题。
import matplotlib.pyplot as plt import cartopy.crs as ccrs lon = np.linspace(0, 359.75, 1440) lat = np.linspace(-90, 90, 721) fig = plt.figure(figsize=(10, 6)) ax = plt.axes(projection=ccrs.PlateCarree()) cs = ax.contourf(lon, lat, pred_field, transform=ccrs.PlateCarree()) ax.coastlines() plt.colorbar(cs) plt.savefig("first_prediction.png")如果能画出看起来合理的气象场分布,就说明整条链路通了,接下来才值得投入时间做精度验证和调优。我习惯把这个流程固化成脚本,后续每次换数据源、换模型都能复用。
5. 实测调优与常见排错:把推理速度提上去,把显存压下来
模型能跑通只是开始。在实际项目里,你往往需要在有限硬件上跑更多的预测任务,这时候“能跑”和“跑得快”就是两码事了。这一节分享我在多台机器上实测下来的数据,以及几条性价比最高的调优手段。
5.1 一台24GB显卡的实测性能基线
以下是在同一份数据、同一个模型、预测未来24个时间步的条件下,端到端推理耗时(包含数据预处理、模型推理、结果落盘):
| 显卡 | 全量全球网格(float32) | 混合精度 + 区域裁剪 |
|---|---|---|
| A100 40GB | 约2分钟 | 约40秒 |
| RTX 4090 24GB | 约3分钟 | 约1分钟 |
| RTX 4060 Ti 16GB | 约5分钟 | 约1分40秒 |
端到端推理的耗时大头往往不在模型本身,而在数据预处理和反复的CPU-GPU拷贝。下面几条手段,按性价比从高到低排列。
5.2 四条实用加速手段
第一,用torch.no_grad()包裹整个推理循环,这个前面提过,不做等于每步都在算梯度,白白浪费大量显存和算力。第二,模型和数据都转成半精度float16,显存占用直接减半,推理速度通常还能提升30%以上。但注意标准化系数建议保留float32,部分敏感层也要做精度保护,否则个别拐点会出现数值误差。
第三,避免频繁的CPU-GPU来回拷贝。把一整段输入数据先一次性搬到GPU,预测完再把全部结果一次性取回CPU,比每步都拷贝快得多。第四,如果业务只需要某个区域,可以在输入阶段就做区域裁剪,比如只预测中国区域,网格从全球的721×1440缩小到300×300,这个操作带来的加速比任何模型层面的优化都明显。
5.3 显存不足怎么办:区域裁剪与分块
如果显卡只有16GB,跑全球网格全量推理还是会偶尔爆显存,我的建议是分优先级处理。首选区域裁剪,这也是业务上最常用的一招。多数应用场景只需要关注特定范围,并不需要全球场,把输入数据先裁剪成目标区域,再喂给模型,显存压力瞬间小一半。如果你的场景确实需要全球网格,但显存不够用,可以考虑把经度方向分块推理,每块重叠几个格点防止边缘不连续,最后再拼接。
这里提醒一句:气象大模型的推理结果对边缘区域有依赖,分块时重叠区不能太小,我一般设置10到20个格点,足以保证拼接处没有明显接缝。
5.4 高频报错与排错链路
最后整理一份我反复遇到的报错排查表,按照出现频率排序:
| 报错信息 | 原因 | 解决办法 |
|---|---|---|
| CUDA out of memory | 显存超限 | 改混合精度、区域裁剪、分批推理 |
| OSError: libeccodes not found | eccodes动态库缺失 | conda install -c conda-forge eccodes |
| key 'shortName' not found | GRIB解析失败 | 用filter_by_keys按变量过滤读取 |
| 预测输出全是NaN | 标准化统计量不匹配 | 检查stats/mean.npy和std.npy来源 |
| ImportError: cannot import name | 依赖版本不对 | 严格按requirements.txt安装,避免混装 |
其中“预测输出全是NaN”最隐蔽,因为它不会直接报错,直到你画图时发现整个区域一片空白才意识到出问题了。排查链路通常是这样:先检查输入是否存在NaN,再检查标准化系数是不是训练集统计,再看模型权重加载是否正确。我遇到过最离谱的一次,是代码里把均值文件路径配错了,导致减的是另一个模型的均值,预测在第4步就开始发散。
所以说,正式跑批量任务前,一定要先用少量时间步做一次完整流程验证,画一张图出来看看,确认没有问题再放开跑。这个习惯帮我省下的调试时间,远比那几分钟验证时间多。
最后再分享一点个人体会。与本地部署大语言模型相比,气象大模型的工程难点不在模型结构,而在一整套数据处理链路。你把GRIB读取、变量对齐、标准化、滚动推理封装好了,整个项目就完成了一大半。我现在的做法是把推理脚本封装成一个函数式接口,输入是上一时次的气象观测,输出是未来几天的预测字段,业务方直接通过接口拉结果,后续接农业物联网的智能灌溉、风电功率预测这些场景,都方便了很多。如果你也准备入坑,建议先拿一个小区域、小数据量跑通全流程,再逐步放开,祝早日拿到第一张自己机器上产出的预报图。
本文还有配套的精品资源,点击获取