
在气象与机器学习交叉领域**天气降尺度Weather Downscaling**一直是一个既基础又棘手的问题。传统降尺度方法要么依赖物理约束较强、计算成本高的区域气候模式要么使用纯统计映射很难同时兼顾精度与不确定性表达。最近读到一项很有意思的工作题目是Earth observation embeddings are effective sub-grid descriptors for probabilistic weather downscaling它把地球观测数据通过嵌入Embedding方式变成子网格描述符再配合概率模型做降尺度思路非常值得借鉴。这篇博客不是单纯翻译论文而是围绕“为什么用嵌入、如何构造特征、概率降尺度怎么落地”三个层面系统拆解相关概念、方法框架和工程实现思路。如果你对气象AI、遥感数据表征、概率预测模型感兴趣或者想在降雨预测、风场细化等场景中尝试类似方案这篇文章可以作为一份入门到进阶的学习笔记。1. 背景与核心概念1.1 天气降尺度到底解决什么问题全球气候模式GCM和再分析数据集的分辨率通常是几十公里甚至上百公里。这种分辨率对区域尺度的天气研究、城市防洪、农业气象、可再生能源功率预测来说太粗糙了。一个网格单元内可能有山脉、湖泊、城市、森林地形和地表覆盖的差异会显著影响局地温度、降水和风场。**降尺度Downscaling**的目标就是从低分辨率的大尺度气象场中重建出高分辨率的局地气象信息。降尺度有两大类主流方法动力降尺度Dynamical Downscaling把粗网格场作为边界条件驱动高分辨率区域气候模型如 WRF、RegCM。精度相对可靠但计算开销非常大不适合大规模业务化运行。统计降尺度Statistical Downscaling建立粗网格气象变量与细网格观测之间的统计映射关系。计算高效但关键在于如何选择有解释力的“预测因子”。近年来深度学习方法大量涌入统计降尺度领域出现了基于 U-Net、ConvLSTM、GAN、Normalizing Flow 等架构的方案。这些模型的共同难点之一是如何把“粗网格不知道、但实际会影响细网格天气”的信息注入模型——这就是“子网格描述符”发挥作用的舞台。1.2 什么是子网格描述符Sub-grid Descriptors“子网格”Sub-grid指的是比模型网格单元更小的空间尺度。一个粗网格单元比如 25km × 25km内部地表海拔、植被指数、土壤湿度、水体分布等变量差异很大。这些次网格尺度的信息会直接影响云的形成、降水触发、地表辐射收支等物理过程但粗网格气象场本身无法表达它们。**子网格描述符Sub-grid Descriptors**就是把网格单元内部的异质性信息压缩成一组统计特征或向量。传统做法可能包括网格内海拔的均值、方差、坡度方向植被覆盖度、土地类型占比海岸线距离、地形粗糙度等。这些描述符作为额外输入能够帮助降尺度模型理解同样是“气温 20℃、相对湿度 60%”的粗网格条件山区和平原的局地降水概率可能完全不同。作者提出的核心观点是与其手工设计这些描述符不如直接从地球观测数据中学习稠密嵌入向量。这些嵌入能够自动捕捉对降尺度有用的子网格特征而且在概率预测框架下效果更好。1.3 为什么要做概率性降尺度确定性降尺度输出的是一个确定的高分辨率场比如“明天中午 12 点这个网格降雨 12.5mm”。但天气系统充满不确定性——初始场误差、模式误差、次网格过程随机性都会让预测不可能做到精确。**概率性降尺度Probabilistic Downscaling**输出的是一个概率分布例如降水量的分布参数Gamma 分布的尺度和形状预测区间的上下界多个空间样本ensemble。这样下游业务可以根据风险偏好做决策。例如水电调度可以同时看“期望降水”和“极端降水概率”农业保险可以根据概率分布计算不同阈值下的赔付风险。概率模型也比确定性模型更诚实当预测不确定度高时分布会变宽当条件清晰时分布会变窄。这正是气象业务中非常需要的特性。2. 方法框架地球观测嵌入 概率降尺度从论文标题可以看出整体思路可以拆成两个关键点使用地球观测嵌入Earth Observation Embeddings作为子网格描述符在概率降尺度框架中使用这种嵌入。下面从原理层面拆解这个框架。2.1 地球观测嵌入Earth Observation Embeddings**嵌入Embedding**在机器学习中通常指把高维稀疏或原始数据映射到一个低维稠密向量空间。在自然语言处理中词嵌入把词汇映射成向量在气象遥感领域嵌入可以理解为把卫星图像块或多通道观测数据编码成一个固定维度的特征向量。和手工设计的描述符相比学习得到的嵌入有几个明显优势自动特征发现不需要专家手动指定“应该统计哪些变量”模型会从数据中发现有预测力的特征。可扩展性可以轻松加入更多遥感通道可见光、红外、微波、SAR 等而不是手工设计对应的统计量。端到端优化嵌入可以与降尺度模型联合训练特征会更加贴合目标任务。子网格信息保留如果一个区域内部高度异质嵌入向量可以通过非线性组合表达这种异质性而不需要预先定义“方差”“极差”等手工统计量。常见的编码器包括 ResNet、Vision TransformerViT、Swin Transformer 等。对卫星多光谱数据也可以使用面向遥感任务的预训练模型例如基于自监督学习在 Sentinel-2 或 Landsat 数据上预训练的编码器。2.2 整个降尺度流程一个典型的地球观测嵌入驱动概率降尺度框架包括以下环节输入粗网格气象场例如来自 ERA5 再分析数据或 GCM 输出输入与粗网格单元对齐的地球观测数据例如 Sentinel-2、MODIS、DEM用编码器把每个粗网格单元对应区域内的观测数据编码为嵌入向量嵌入向量作为子网格描述符与粗网格气象特征拼接概率生成模型解码出细网格目标变量的分布参数或样本训练时最小化负对数似然NLL或其他概率损失推理时输出分布参数采样得到多个可能的高分辨率场。用更通俗的方式理解粗网格气象场告诉模型“大环境大概是什么状态”地球观测嵌入告诉模型“这个网格内部的地表环境长什么样”两者结合起来模型就能更准确地推断出局地天气的细网格分布。2.3 为什么嵌入比手工描述符更适合概率模型在一些传统统计降尺度研究中子网格信息通常以手工统计量形式加入比如地形标准差、坡度均值、植被覆盖比例。这些特征对确定性预测也有帮助但在概率模型中可能存在表达能力不足的问题。概率模型需要刻画的条件分布可能很复杂——同一个粗网格条件在不同地形下可能对应完全不同的分布形态。手工特征往往是固定的低维描述难以捕捉复杂的非线性关系而嵌入向量是高维稠密表示可以更好地表达“这类地形组合往往带来偏态分布的降水”这类潜在模式。另外嵌入可以通过自监督预训练形成良好的先验表征再在下游降尺度任务中微调这种迁移学习优势也是手工特征不具备的。3. 数据准备与特征对齐如果你也想在自己的项目中复现类似思路第一个要解决的问题是数据准备。3.1 典型数据源气象粗网格数据ERA5、ERA5-Land、GCM 输出等。关键变量包括气温、气压、湿度、风场、降水等。地球观测数据Sentinel-2多光谱、MODIS植被指数、地表温度、SRTM 或 GTOPO30数字高程模型、ESA-CCI土地覆盖等。高分辨率观测标签气象站点观测、雷达估测降水、高分辨率再分析如 COSMO-REA6等。需要说明的是不同数据源的空间分辨率、时间分辨率和坐标系可能不一致需要做统一重采样和空间对齐。3.2 时间与空间对齐策略一种常见的做法是选择目标区域比如某个流域或省份把区域划分为规则网格例如 5km 分辨率收集每个时间步的粗网格气象变量例如 25km对每个粗网格单元裁剪对应的地球观测影像块例如该 25km 单元内部所有 5km 像素计算标签对应的高分辨率降水或气温场。如果地球观测数据在时间上变化不大如 DEM、土地覆盖可以只在训练时编码一次缓存下来供所有时间步使用如果使用植被指数等季节变化明显的数据则需要按时间窗口重新编码。3.3 数据增强与训练集划分气象数据具有强烈的时空自相关性划分训练集和测试集时需要特别注意避免随机划分导致空间泄漏建议按区域或时间块划分可以用“留一年做测试”的方式检验模型的泛化能力数据增强可以包括随机裁剪、翻转、旋转等但要注意气象场的物理合理性例如对降雨场做旋转可能不自然需要谨慎。4. 核心代码思路构建嵌入编码器与概率降尺度模型这一节提供一套通用的 PyTorch 示例思路帮助理解整体建模过程。因为不同数据集的格式差异较大代码只展示核心网络结构和损失函数实际使用时要根据你的数据做适配。4.1 编码器从多通道观测块到嵌入向量我们先用一个简单的 ResNet 风格编码器把多通道卫星/地形观测块编码成固定长度向量。假设输入是一个[B, C, H, W]的观测块其中C是通道数例如海拔、NDVI、土地覆盖类型等H和W是空间尺寸。# 文件路径models/encoder.py import torch import torch.nn as nn class ObservationEncoder(nn.Module): 将多通道地球观测块编码为子网格描述符向量。 输入形状(batch, in_channels, H, W) 输出形状(batch, embed_dim) def __init__(self, in_channels: int 6, embed_dim: int 64): super().__init__() self.features nn.Sequential( nn.Conv2d(in_channels, 32, kernel_size3, padding1), nn.BatchNorm2d(32), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), # H/2 nn.Conv2d(32, 64, kernel_size3, padding1), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), # H/4 nn.Conv2d(64, 128, kernel_size3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), nn.AdaptiveAvgPool2d((1, 1)), ) self.proj nn.Linear(128, embed_dim) def forward(self, x: torch.Tensor) - torch.Tensor: h self.features(x) # (B, 128, 1, 1) h h.flatten(start_dim1) # (B, 128) emb self.proj(h) # (B, embed_dim) return emb这里需要提醒几个设计点in_channels根据你的数据源决定。如果包括 DEM、坡度、土地覆盖、NDVI、地表反照率等可以一起拼接。AdaptiveAvgPool2d((1,1))让编码器对输入空间尺寸不敏感方便处理不同 Patch 大小。输出层不使用激活函数嵌入向量可以是任意实数向量后续拼接进降尺度模型即可。4.2 气象场编码粗网格条件特征粗网格气象场可以先用两三层的 CNN 或 MLP 编码成与嵌入向量同一维度的特征。这里给出一个轻量编码器输入是粗网格场的多通道图# 文件路径models/weather_encoder.py import torch import torch.nn as nn class WeatherEncoder(nn.Module): 将粗网格气象场编码为条件特征。 输入形状(batch, in_channels, Hc, Wc) 输出形状(batch, embed_dim, Hc, Wc) def __init__(self, in_channels: int 5, embed_dim: int 64): super().__init__() self.net nn.Sequential( nn.Conv2d(in_channels, 32, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(32, 64, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(64, embed_dim, kernel_size1), ) def forward(self, x: torch.Tensor) - torch.Tensor: return self.net(x)把这个气象编码器设计成保留空间维度的结构是为了后续能和嵌入向量做某种“融合”后生成高分辨率场。4.3 融合与生成从条件分布到高分辨率场在概率降尺度模型中生成器需要把条件特征变成高分辨率场。一种方式是把气象特征图上采样同时把每个粗网格单元的嵌入向量广播到对应空间位置在通道维度拼接再通过一个 U-Net 风格解码器输出分布参数。为了简化代码下面展示一个从融合特征到分布参数的生成模块# 文件路径models/probabilistic_head.py import torch import torch.nn as nn import torch.nn.functional as F class ProbabilisticHead(nn.Module): 根据融合特征输出目标变量的分布参数。 这里以连续变量为例输出均值和 log 方差。 输入形状(batch, fusion_channels, Hc, Wc) 输出形状mean (B, 1, Hc, Wc), logvar (B, 1, Hc, Wc) def __init__(self, fusion_channels: int 128): super().__init__() self.up1 nn.ConvTranspose2d(fusion_channels, 64, kernel_size4, stride2, padding1) self.up2 nn.ConvTranspose2d(64, 32, kernel_size4, stride2, padding1) self.mean_head nn.Conv2d(32, 1, kernel_size3, padding1) self.logvar_head nn.Conv2d(32, 1, kernel_size3, padding1) def forward(self, x: torch.Tensor): h F.relu(self.up1(x)) h F.relu(self.up2(h)) mean self.mean_head(h) logvar self.logvar_head(h) logvar torch.clamp(logvar, min-5.0, max5.0) return mean, logvar如果目标是降水通常不适合直接用高斯分布因为降水是高度偏态、包含大量零值的变量。更常见的选择是Tweedie 分布对零膨胀连续数据友好混合 Bernoulli-Gamma 分布或者使用条件 Normalizing Flow / Diffusion 模型直接建模复杂分布。4.4 损失函数设计示例概率降尺度的核心损失是负对数似然Negative Log-Likelihood, NLL。以高斯分布为例给定预测均值 $\mu$ 和方差 $\sigma^2$损失可以写成$$L \frac{1}{N} \sum \left( \frac{(y - \mu)^2}{2\sigma^2} \frac{1}{2} \log \sigma^2 \text{const} \right)$$PyTorch 实现如下# 文件路径losses/gaussian_nll.py import torch import torch.nn as nn class GaussianNLL(nn.Module): 用于连续变量概率降尺度的高斯负对数似然损失。 def __init__(self, eps: float 1e-6): super().__init__() self.eps eps def forward(self, mean: torch.Tensor, logvar: torch.Tensor, target: torch.Tensor) - torch.Tensor: var torch.exp(logvar) self.eps loss 0.5 * ((target - mean) ** 2) / var 0.5 * logvar return loss.mean()如果使用 Tweedie 分布或混合分布只需替换ProbabilisticHead输出的参数数量和对应的forward计算方法。核心思想不变模型输出的是分布参数损失函数衡量预测分布与真实观测的匹配程度。4.5 嵌入与气象条件融合一个关键的设计问题嵌入向量如何与气象特征融合简单有效的方式是“拼接 广播”。假设气象特征图是[B, Cw, H, W]每个空间位置对应一个粗网格单元嵌入向量是[B, De]我们先把它 reshape 成[B, De, 1, 1]然后在前两个维度上广播到[B, De, H, W]再与气象特征拼接成[B, CwDe, H, W]。# 文件路径models/fusion.py import torch def broadcast_concat(weather_feat: torch.Tensor, embedding: torch.Tensor) - torch.Tensor: weather_feat: (B, Cw, H, W) embedding: (B, De) 或 (B, De, 1, 1) emb embedding if emb.dim() 2: emb emb.unsqueeze(-1).unsqueeze(-1) # (B, De, 1, 1) emb emb.expand(-1, -1, weather_feat.size(2), weather_feat.size(3)) return torch.cat([weather_feat, emb], dim1)这种融合方式的好处是简单、稳定且不会引入额外的可学习参数。更高级的做法是使用 FiLM 条件化对特征图做缩放和偏移或者使用 Cross-Attention 机制让气象特征有条件地“查询”嵌入向量中的信息。5. 训练流程与评估方法5.1 训练流程整体训练流程可以概括为准备数据批次每个样本包含粗网格气象场、对应区域的地球观测块、高分辨率目标标签用观测编码器计算嵌入向量用气象编码器提取气象特征融合特征通过概率生成头输出分布参数计算 NLL 损失或所选分布的负对数似然反向传播更新编码器和生成器参数。伪代码# 文件路径train.py核心训练循环片段 for epoch in range(epochs): for batch in dataloader: weather_coarse batch[weather].to(device) # (B, Cw, Hc, Wc) obs_patch batch[observation].to(device) # (B, Co, Hp, Wp) target_fine batch[target].to(device) # (B, 1, Hf, Wf) emb obs_encoder(obs_patch) # (B, De) weather_feat weather_encoder(weather_coarse) # (B, Cw, Hc, Wc) fused broadcast_concat(weather_feat, emb) # (B, CwDe, Hc, Wc) mean, logvar prob_head(fused) # 生成分布参数 loss gaussian_nll(mean, logvar, target_fine) optimizer.zero_grad() loss.backward() optimizer.step()注意这里假设生成头输出的空间分辨率已经和目标标签对齐。如果上采样倍数不足以匹配目标分辨率需要调整解码器的stride和padding。5.2 评估指标概率降尺度的评估不能只看 RMSE还需要评估分布预测的质量。常用指标包括指标全称说明CRPSContinuous Ranked Probability Score衡量预测分布与观测的差异越低越好NLLNegative Log-Likelihood分布拟合程度的直接度量RMSERoot Mean Square Error确定性误差可以基于分布均值计算Bias平均偏差判断是否存在系统性高估/低估PITProbability Integral Transform检查预测分布是否校准理想情况接近均匀分布区间覆盖率Interval Coverage预测区间是否以正确频率包含真实值CRPS 在气象领域尤其常用它既考虑分布形态又对偶尔的极端观测有一定鲁棒性。如果预测分布是高斯分布CRPS 有解析公式可以直接计算如果使用混合分布或采样模型则需要用积分近似。5.3 消融实验嵌入到底有没有用要证明嵌入的有效性建议做以下消融Baseline仅用粗网格气象场不加任何子网格描述符Handcrafted Features加入手工统计特征海拔均值、标准差、植被指数均值等Learned Embedding加入观测编码器输出嵌入向量Pretrained Embedding使用预训练编码器提取的嵌入而不是端到端训练。通过对比不同设置的 CRPS / NLL可以直观看到学习得到的嵌入是否带来了显著增益。这也是论文中常见的验证思路。6. 常见问题与排查思路在实际复现和落地过程中下面几个问题最容易出现。这里整理成速查表。问题现象常见原因解决思路嵌入向量对结果没有明显提升观测数据本身与目标变量相关性低嵌入维度太小检查观测数据通道选择增大嵌入维度尝试预训练编码器训练不收敛损失过大或出现 NaN检查输入是否标准化降低学习率检查目标是否存在异常大值预测分布过于集中模型退化为确定性预测方差输出接近 0对 logvar 做 clamp调整损失权重检查标签噪声是否不足降水预测全是零降水稀疏模型倾向于预测无降水使用零膨胀损失如 Bernoulli-Gamma 混合重采样降水事件样本对降水概率单独建模空间分辨率不匹配解码器上采样倍数不对计算输入输出尺寸调整 ConvTranspose 的 stride 和 padding时空泄漏导致评估偏乐观训练集和测试集来自相近时间/区域按时间段或空间区域划分数据集不用随机划分显存不足观测块和高分辨率标签同时加载减小 batch size在编码端缓存嵌入向量使用梯度累积6.1 嵌入缓存策略如果地球观测数据随时间变化缓慢如 DEM、土地覆盖可以在训练前对所有网格单元的观测块一次性编码把嵌入向量保存到磁盘训练时直接加载即可。这样可以避免每个 epoch 都重新跑编码器大幅减少计算量。示例思路# 文件路径utils/cache_embeddings.py伪代码思路 for grid_id in grid_ids: obs_patch load_observation_patch(grid_id) with torch.no_grad(): emb obs_encoder(obs_patch.unsqueeze(0).to(device)) torch.save(emb.cpu(), fcache/emb_{grid_id}.pt)需要注意的是如果观测数据包含季节变化比如 NDVI 在一年内变化很大就不能简单缓存一个固定嵌入而应该按照时间窗口缓存多个版本。6.2 如何处理缺失观测数据不同类型的卫星数据可能受云遮挡或卫星重访周期影响出现缺失。常见处理方式使用月合成产品如 MODIS 月合成 NDVI降低云影响对缺失通道做掩码让编码器知道该通道不可用使用时间插值或气候态填补但要在评估时注意影响。7. 最佳实践与工程建议7.1 特征工程与数据预处理虽然嵌入能自动提取特征但数据预处理依然是决定成败的基础标准化所有数值型观测通道做均值方差标准化或 min-max 归一化避免量纲影响训练稳定性质量控制检查卫星数据异常值如云污染导致的反常反射率做掩膜或剔除目标变换对降水目标做对数变换log(1 y)可以缓解偏态问题但要注意分布假设的变化。7.2 模型结构选择如果目标是温度、气压等近高斯连续变量高斯分布头 U-Net 是稳妥的起点如果目标是降水优先尝试零膨胀混合分布或专门的降水概率模型如果希望训练更稳定可以考虑先训练一个确定性重建分支再让概率头在这个基础上做残差预测对序列数据如逐小时降水可以考虑在嵌入和生成之间加入 ConvLSTM 或 Transformer 时间编码模块。7.3 不确定性分解概率降尺度中的不确定性来自多个来源输入不确定性粗网格气象场本身的误差模型不确定性网络参数在有限数据下无法完全确定子网格变率同一个粗网格条件下可能对应多种真实细网格状态。合理安排实验时可以先固定输入气象场只评估模型在某个条件下的输出分布再考虑叠加输入扰动才能更全面地刻画总不确定性。7.4 生产环境注意事项把模型部署到业务系统时有几点特别提醒输入数据链路要稳定卫星数据的时效性、缺失率、格式变化都会影响线上推理建议加入数据质量监控定期重训练与监控气象数据分布会随季节变化需要按周期微调模型并监控 CRPS 和覆盖率是否漂移保存嵌入缓存策略要清晰如果观测数据更新频率低可以用定时任务更新嵌入如果使用季节动态数据需要设计更细的缓存键解释性工具使用 Grad-CAM 或 SHAP 分析嵌入向量关注的空间位置有助于发现模型在哪些地形/植被条件下表现更好也有助于向业务方解释模型行为。7.5 计算资源建议观测编码器本身参数量不大但高分辨率卫星影像块的读取和增强可能成为瓶颈。建议使用zarr、xarray等格式存储大型遥感数据支持分块读取使用Dask或DataLoader的多进程预取如果观测数据非常大可以先降采样到模型输入需要的空间尺寸再喂给编码器训练时使用混合精度AMP可以显著减少显存占用并加速训练。8. 总结与下一步学习建议这篇文章围绕“地球观测嵌入用于概率性天气降尺度”这一主题梳理了核心概念、方法框架、代码思路和工程落地要点。重点理解以下三点子网格描述符的本质粗网格气象场无法表达网格内部的地表异质性需要额外信息帮助模型推断局地天气嵌入向量的价值通过深度编码器从地球观测数据中学到的稠密向量比手工统计特征更灵活、更强表达力也能与下游概率模型端到端联合优化概率降尺度的关键在输出分布使用分布参数加负对数似然损失训练可以得到更可靠的不确定性估计。如果接下来想继续深入推荐从这几个方向入手阅读并复现 U-Net 风格的降尺度 baseline先跑通一个简单的一维或二维温度降尺度例子增加观测通道尝试 DEM NDVI 土地覆盖三种数据源对比手工特征和嵌入向量的表现把输出分布从高斯替换为 Tweedie 或混合分布对比降水任务的 CRPS 改善有兴趣的话进一步了解 Normalizing Flow、扩散模型在概率降尺度中的最新应用这类生成模型在高维不确定性建模方面很有潜力。技术路线选型时我建议从简单的概率生成头 通用编码器开始而不是一上来就上大规模扩散模型。先把数据对齐、评估指标、消融实验做好再逐步提升模型复杂度才是工程落地最稳妥的路径。如果本文对你有帮助可以收藏备用后续也会持续更新相关方向的学习笔记。