
简介《基于强暴雨预报知识的机器学习尝试》是一篇面向气象预报与人工智能交叉领域研究者的参考文献聚焦如何把强暴雨预报经验转化为机器学习可用的知识环境。文献以江西省强暴雨为对象介绍借助IMFOS-0520-CH微机与JMFOS系统实现规则自动生成的过程涉及类比学习与归纳学习两类方式并阐述和谐性、完备性两条原则以及起报条件、54个因子库、历史个例库等关键环节最终生成150条预报规则并完成五年试报兼具专业指导价值与方案参考意义。资源包仅含1个PDF文件约142KB便于检索、打印与引用适合作为论文写作与算法设计时的案例素材。目前已有84人学习下载。1. 强暴雨预报知识与机器学习尝试先别急着上模型强暴雨预报知识和机器学习放在一张样本表里最先暴露的通常不是模型结构而是正样本太少。把 1 小时降水达到 20 mm 以上记成正样本一个汛期也许只有几百到几千条负样本却有几十万条模型 AUC 看起来不错落到 TS、POD、FAR 上却常常没法给预报员用。标题里的 .pdf 只是载体真正要落地的是把强暴雨预报知识转成机器学习模型能吃的标签、特征和检验口径。适合已经会 Python 机器学习基础、手上有雷达、自动站、探空或再分析样本准备做短时强降水、强对流短临项目的人也适合机器学习入门后想找一个真实不平衡时序问题练手的人。路径按四步走定义标签构造物理量和雷达特征用传统机器学习算法跑基线再用概率校准和邻域检验决定能不能发提示。2. 把强暴雨预报知识转成机器学习特征CAPE、K指数、雷达回波与时间窗2.1 强暴雨标签怎么定1h、3h、6h 降水阈值与格点匹配标签不是把降水画个圈就完事。短临强降水常见做法是按站点或格点定义未来 1 h、3 h、6 h 累计降水阈值再用半径 1 到 3 个格点的邻域放宽命中。若直接要求格点完全重合正样本会少到模型学不动若邻域开太大FAR 会抬头预报员很快就不看。更关键的是特征截止时间起报时刻之后的数据一律不能进入特征哪怕它只是“未来 10 分钟”的雷达回波。预报对象常见标签阈值标签窗口特征截止建模注意短时强降水1 h 累计 ≥ 20 mm未来 1 h起报时刻样本少邻域 1 格较常见强降雨3 h 累计 ≥ 50 mm未来 3 h起报时刻与特征窗口留出间隔暴雨6 h 累计 ≥ 100 mm未来 6 h起报时刻地形和边界影响大极端强降水1 h 累计 ≥ 50 mm未来 1 h起报时刻需要代价敏感和概率输出格点匹配时还要统一投影和分辨率。雷达拼图、数值模式、自动站常来自不同网格直接按行列号对齐会错位几公里到十几公里。我一般先把所有数据插值到同一套等经纬度或兰勃特投影网格再用最近邻或双线性重采样标签格点与特征格点必须共用同一套坐标。2.2 用 CAPE、K指数、风切变、可降水量做 Python 机器学习特征CAPE、K 指数、深层风切变、可降水量、抬升凝结高度、CIN、SRH 是传统机器学习里性价比很高的一组物理量。它们不是让模型背公式而是给模型先验低层暖湿、中层干冷、抬升条件具备、风切变合适强降水和对流才有组织。下面这段代码把常见探空和再分析变量拼成特征字段名按你手上的表结构替换即可。import numpy as np import pandas as pd def add_thermo_features(df): # K指数中低层温差 低层露点 - 中层干层越大通常越有利于对流 df[k_index] (df[t850] - df[t500]) df[td850] - (df[t700] - df[td700]) # 0-6 km 风切变这里用 850 hPa 与 500 hPa 近似实际项目按高度层插值 df[ws850] np.sqrt(df[u850] ** 2 df[v850] ** 2) df[ws500] np.sqrt(df[u500] ** 2 df[v500] ** 2) df[shear_0_6] np.sqrt( (df[u500] - df[u850]) ** 2 (df[v500] - df[v850]) ** 2 ) # 可降水量单位统一到 mm缺失用训练期气候中位数填补 df[pw_mm] df[pw].fillna(df[pw].median()) # 对流抑制和抬升凝结高度常与触发条件有关 df[cin_abs] df[cin].abs() df[lcl_km] df[lcl] / 1000.0 return df # 调用示例 # df pd.read_parquet(storm_samples.parquet) # df add_thermo_features(df)逻辑说明先把热力不稳定、水汽、动力切变拆成独立列让树模型或线性模型自己找非线性关系不要直接把“是否强暴雨”写进特征。参数说明t850、td850、t700、td700、t500的温度露点单位要一致摄氏度或开尔文都可以因为计算的是温差u850、v850、u500、v500单位统一为 m/spw若原始单位是 cm要先乘 10。缺失值只能用训练期统计量填不能把验证期和测试期一起算中位数否则就是数据泄漏。提示物理量特征不是越多越好。先保留 10 到 20 个有明确天气学含义的变量再让特征重要性筛选比一上来堆几百列更接近可复现的机器学习项目。2.3 雷达回波特征与光流外推哪些量能进模型雷达侧的特征要围绕“当前回波状态”和“过去演变”展开。组合反射率最大值、平均值、面积、回波顶高、垂直积分液态水、低层径向速度、质心位置、移动矢量、过去 30 分钟增强率都是短临里常见且容易落表的量。光流外推可以用来估计回波移动但只能使用当前帧和过去帧如果把未来帧拿进来算光流再拿去预测未来降水离线指标会好得离谱上线就掉下来。深度学习和机器学习结合时可以先用卷积网络从雷达序列里提空间特征再把 CAPE、K 指数、风切变拼进全连接层。不过对大多数刚起步的机器学习项目先把统计特征和梯度提升树跑通比直接上复杂时空网络更容易定位问题。传统机器学习算法在几百到几万条样本上往往更稳特征含义也更容易和预报员解释。2.4 样本不平衡下的滑动窗口与时间切分样本构造通常按起报时刻滑动每 10 分钟或每 1 小时取一个样本特征用起报时刻之前的数据标签用之后 1 h、3 h、6 h 的累计降水。正样本少时不要全局随机过采样因为同一次强降水过程会产生大量相似样本全局采样会把同一个过程的样本同时撒进训练和测试。更稳妥的做法是先在训练折内做加权或欠采样验证和测试保持原始分布切分按时间顺序训练集在前验证集居中测试集在后。具体步骤可以这样定按valid_time排序先划出训练、验证、测试三个时间段。只在训练段内统计正负比求出scale_pos_weight或样本权重。对每个起报时刻检查特征最大时间是否小于标签开始时间。对同一降水过程做分组标记交叉验证时按过程分组避免过程内泄漏。3. 强暴雨机器学习建模最小闭环时间切分、梯度提升树与概率阈值3.1 用时间切分替代随机切分的最小代码时间序列问题里随机切分是第一个大坑。它会用 8 月样本训练、7 月样本测试让模型看到未来气候背景。下面这段代码用valid_time做时间切分训练一个梯度提升树基线并输出 AUC、PR-AUC 和 Brier 分数。import numpy as np import pandas as pd from sklearn.ensemble import HistGradientBoostingClassifier from sklearn.metrics import roc_auc_score, average_precision_score, brier_score_loss df df.sort_values(valid_time).reset_index(dropTrue) split_train pd.Timestamp(2021-01-01) split_valid pd.Timestamp(2022-01-01) train df[df[valid_time] split_train] valid df[(df[valid_time] split_train) (df[valid_time] split_valid)] test df[df[valid_time] split_valid] features [ k_index, shear_0_6, pw_mm, cape, cin_abs, lcl_km, srh, ref_max, ref_area, echo_top ] target label_3h_50mm X_train, y_train train[features], train[target] X_valid, y_valid valid[features], valid[target] X_test, y_test test[features], test[target] # 训练段正负比用于样本加权 neg (y_train 0).sum() pos (y_train 1).sum() spw neg / max(pos, 1) w_train np.where(y_train 1, spw, 1.0) model HistGradientBoostingClassifier( max_iter300, learning_rate0.05, max_leaf_nodes31, l2_regularization1.0, random_state42 ) model.fit(X_train, y_train, sample_weightw_train) valid_prob model.predict_proba(X_valid)[:, 1] test_prob model.predict_proba(X_test)[:, 1] print(valid AUC, roc_auc_score(y_valid, valid_prob)) print(valid PR-AUC, average_precision_score(y_valid, valid_prob)) print(valid Brier, brier_score_loss(y_valid, valid_prob))逻辑说明训练段在前、验证段居中、测试段在后模拟业务上线时只能看到历史sample_weight提高正样本权重缓解极端不平衡。参数说明max_iter控制树的数量强暴雨样本少时可先 200 到 500learning_rate越小通常需要更多树max_leaf_nodes越大模型越容易记住过程细节l2_regularization用来压过拟合。AUC 高不代表强暴雨命中好PR-AUC 和 Brier 更值得盯。3.2 传统机器学习算法基线逻辑回归和梯度提升树怎么选先用简单模型确认特征方向再上复杂模型是机器学习实战里省时间的顺序。逻辑回归能看出每个物理量是正贡献还是负贡献梯度提升树能抓阈值和非线性随机森林方差小一些深度模型适合样本多、雷达序列完整的团队。模型可解释性不平衡表现训练速度适合场景逻辑回归高依赖权重和校准快入门基线、特征方向检查随机森林中较稳概率偏粗中多特征、小样本梯度提升树中好需调参中表格特征主力一维卷积或 LSTM低依赖数据和损失慢雷达序列、时空特征充足如果只是机器学习入门可以手写逻辑回归梯度下降理解损失函数但做业务原型时直接用成熟库更省事。机器学习模型可以自己写吗可以但先把数据切分、特征时间对齐和评估指标做对比手写网络结构重要得多。3.3 概率校准与强暴雨阈值扫描强暴雨预报最终要给的是概率不是 0/1。梯度提升树输出的概率常常偏尖需要用验证集做校准再扫描阈值。下面代码在验证集上找 TS 最高的阈值再拿去测试集确认。import pandas as pd import numpy as np thresholds np.arange(0.05, 0.95, 0.05) rows [] for th in thresholds: pred (valid_prob th).astype(int) hits int(((pred 1) (y_valid 1)).sum()) misses int(((pred 0) (y_valid 1)).sum()) fas int(((pred 1) (y_valid 0)).sum()) ts hits / (hits misses fas 1e-9) far fas / (hits fas 1e-9) rows.append({threshold: round(th, 2), TS: ts, FAR: far, hits: hits}) scan pd.DataFrame(rows).sort_values(TS, ascendingFalse) print(scan.head(10)) best_th float(scan.iloc[0][threshold]) test_pred (test_prob best_th).astype(int) test_hits int(((test_pred 1) (y_test 1)).sum()) test_misses int(((test_pred 0) (y_test 1)).sum()) test_fas int(((test_pred 1) (y_test 0)).sum()) test_ts test_hits / (test_hits test_misses test_fas 1e-9) print(test TS, test_ts, best_th, best_th)逻辑说明阈值只能在验证集或历史回测集上选不能拿测试集反复挑测试集只用一次才是接近真实的检验。参数说明thresholds从 0.05 到 0.95 扫描业务上还要看 FAR 能不能接受如果预报员更怕空报可以把阈值抬高如果更怕漏报就降低阈值并接受更多空报。概率校准可用CalibratedClassifierCV但要在训练段内部再做一次时间切分不能直接对全量数据校准。3.4 类别权重、代价敏感和降水分级输出强暴雨样本少类别权重是最直接的代价敏感手段。更细一点可以把降水分级20 到 30 mm、30 到 50 mm、50 mm 以上分别建模或者用 ordinal 思路输出各级概率。业务上不一定只发一个“有/无”而是给 0 到 20 mm、20 到 50 mm、50 mm 以上三档概率让预报员看到量级倾向。机器学习模型优化方案里重采样、代价矩阵、分档建模和多模型集成可以一起用但每次只改一个变量否则回测结果没法归因。4. 强暴雨预报模型检验与排错TS、FSS、数据泄漏和时间错位4.1 TS、POD、FAR、ETS 怎么算与怎么看强降水的检验不能只看准确率。晴雨样本比例悬殊时全报“无强暴雨”也能有很高准确率。短临业务更常看 TS、POD、FAR、ETS分别回答命中多少、漏报多少、空报多少、扣掉随机命中后还有多少技巧。指标计算方式关注点TS命中 /命中 漏报 空报综合命中与空报POD命中 /命中 漏报漏报是否严重FAR空报 /命中 空报空报是否过多ETS扣除随机命中后的 TS与气候概率比较Brier概率预测的均方误差概率是否校准BSS相对气候概率的 Brier 技巧是否比气候背景强这些指标要按时间窗、降水量级、区域分开算。一个模型在 1 h 20 mm 上 TS 不错不代表在 1 h 50 mm 上也能用。机器学习模型输出概率后先做可靠性曲线再看阈值扫描表最后按过程逐个复盘。4.2 邻域法 FSS 检验高分辨率强暴雨预报不能只看点对点强暴雨落区空间误差一两格点对点评分就会很难看。邻域法 FSS 用一定窗口放宽匹配更贴近短临预报的实际使用方式。下面是一个简化二值邻域命中示例真实业务里还会用分数场和基线 FSS。import numpy as np from scipy.ndimage import maximum_filter def fss_binary(obs, pred, window5): # obs、pred 为二维 0/1 网格window 为邻域边长 o maximum_filter(obs, sizewindow) p maximum_filter(pred, sizewindow) hits np.sum((o 1) (p 1)) misses np.sum((o 1) (p 0)) fas np.sum((o 0) (p 1)) return hits / (hits misses fas 1e-9) # 示例obs 和 pred 从格点场转成 0/1 后传入 # score fss_binary(obs_grid, pred_grid, window5)逻辑说明先用maximum_filter把观测和预报在邻域内膨胀再算命中、漏报、空报得到邻域 TS 类似量。参数说明window根据检验需求和分辨率定常见 3、5、9窗口越大分数通常越高所以不同模型必须用同一窗口比较。FSS 不能替代点对点 TS两者要一起看。4.3 数据泄漏与时间错位的 3 个排查动作第一检查特征时间戳。任何特征的生成时间晚于起报时刻都要删掉或向后平移。第二检查标签窗口重叠。用 08 时起报预测 08 到 11 时就不能把 09 时观测放进特征。第三检查预处理顺序。标准化、插补、特征选择如果放在训练测试切分之前测试集统计量就会漏进训练。下面这段检查代码可以放进日常流程。def check_time_leakage(df, feature_cols, issue_colinit_time, label_start_collabel_start): bad [] for col in feature_cols: if col in df.columns and df[col].dtype.kind in iufc: pass # 真正要检查的是每列的特征有效时间而不是列名 max_feat_time df[feature_max_time] label_start df[label_start_col] leak_rows df[max_feat_time label_start] return leak_rows[[init_time, feature_max_time, label_start]] # leak check_time_leakage(df, features) # print(leak.head())逻辑说明这段代码不是靠列名判断而是靠每列特征的最大有效时间与标签开始时间比较只要特征最大时间大于等于标签开始时间就存在泄漏嫌疑。参数说明feature_max_time是每个样本特征窗口的最后一个时次label_start是标签窗口起点init_time用于回溯是哪次起报。4.4 模型调参顺序先对齐时间再谈超参数调参顺序建议是数据泄漏排查、时间切分检查、标签定义检查、阈值选择、特征筛选、超参数。很多团队一上来调max_depth、learning_rate结果真正问题是雷达特征用了未来帧。超参数只在前四步干净后才有意义。每轮实验保留一份配置表特征版本、训练时间段、验证时间段、正负比、阈值、TS、FAR、Brier。这样换模型或换汛期时能快速定位是数据变了还是参数变了。5. 强暴雨机器学习模型的进阶用法概率集成、漂移监控与预报员会商5.1 概率集成与多模式融合单模型在强暴雨上容易受某类过程影响概率集成能把逻辑回归、梯度提升树、随机森林甚至数值模式降水概率融合。权重不要拍脑袋用验证集 BSS 或 TS 调测试集只做最终确认。import numpy as np # 假设三个模型已在同一验证集和测试集上输出概率 probs_valid np.vstack([valid_prob_lr, valid_prob_gbdt, valid_prob_rf]) probs_test np.vstack([test_prob_lr, test_prob_gbdt, test_prob_rf]) # 权重按验证集表现分配这里只是示例 weights np.array([0.2, 0.5, 0.3]) ensemble_valid np.average(probs_valid, axis0, weightsweights) ensemble_test np.average(probs_test, axis0, weightsweights) print(ensemble valid mean, ensemble_valid.mean()) print(ensemble test mean, ensemble_test.mean())逻辑说明集成前必须保证各模型使用同一起报时刻、同一标签、同一验证时间段否则概率不可加。参数说明weights可以按 BSS 网格搜索但搜索空间不要太大如果某模型在验证集上 FAR 很高权重应压低。多模式融合时数值模式降水概率可以作为一列特征而不是直接替换机器学习输出。5.2 在线更新与漂移监控汛期前后气候背景、雷达标定、模式版本都会变模型上线后要做漂移监控。常见做法是每周算一次特征分布 PSI、预测概率分布 KL 或 KS再按月回算 TS、FAR。若某几个物理量分布明显偏移先查数据源不要急着重新训练。在线更新可以采用滑动训练窗口比如始终用最近 3 年同期加最近 1 个月数据既保留季节规律也吸收近期样本。监控项频率触发动作特征均值与分位数每周查数据源和插值预测概率分布每周查模型输入漂移TS、FAR、Brier每月评估是否重训正样本率每汛期检查标签口径5.3 解释性、会商与业务阈值预报员不会只看一个概率数字。把 SHAP 值、部分依赖和个例特征贡献做成会商材料能解释“为什么这次模型给高概率”是 CAPE 和可降水量配合还是雷达回波面积快速增长。业务阈值也要分会商场景内部参考可以低阈值多提示对外发布要高阈值压空报。最后把 0 到 3 h 强降水概率做成每 10 分钟刷新、带邻域概率和不确定区间的面板比单纯追一个二分类准确率更接近强暴雨预报真正要解决的问题。本文还有配套的精品资源点击获取