Promote EMOS to the primary probability engine

This commit is contained in:
2569718930@qq.com
2026-04-19 03:36:26 +08:00
parent 3e44ed6eaa
commit 1892d638fa
12 changed files with 509 additions and 675 deletions
+80 -271
View File
@@ -1,311 +1,120 @@
# EMOS 训练报告(2026-03-20
# EMOS 训练报告(2026-04-19
## 1. 报告目的
## 1. 当前结论
本文档用于记录当前 PolyWeather 概率校准引擎(EMOS)的训练结果、离线评估结果、线上 shadow 观测结果,以及是否具备切换为主路径的条件
- `EMOS` 已切为默认主概率路径:`emos_primary`
- 本次切换只影响概率分布校准层,不改变 `DEB`、多模型预报、METAR 结算口径、订阅权限或缓存路由。
- 线上回滚开关保留:`POLYWEATHER_PROBABILITY_ENGINE=emos_shadow``legacy`
- `LGBM` 本轮重新训练后仍不建议上线,继续保持 `POLYWEATHER_LGBM_ENABLED=false`
当前结论先写在前面:
## 2. 本次 EMOS 版本
- `EMOS` 已完成接入、训练、离线评估、shadow 落盘与滚动报表。
- 当前默认运行模式应继续保持 `emos_shadow`
- 现阶段 **不建议切换到 `emos_primary`**
## 2. 本次训练版本
- 校准版本:`emos-20260320130245`
- 训练时间:`2026-03-20T13:02:45.903772+00:00`
- 校准版本:`emos-20260418192717`
- 训练时间:`2026-04-18T19:27:17Z`
- 样本数:`74`
- 参数文件:[default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json)
- 离线评估报告:[evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.json)
- 线上 shadow 报表:[shadow_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/shadow_report.json)
## 3. 训练数据概况
## 3. 离线评估摘要
### 3.1 数据来源
本次评估对比 legacy 概率和强制 EMOS primary 概率:
当前训练主要使用两类数据:
| 指标 | Legacy | EMOS | 变化 |
| :-- | --: | --: | --: |
| CRPS | `3.474108` | `3.331240` | `-0.142868` |
| MAE | `3.679324` | `3.622584` | `-0.056741` |
| Bucket hit rate | `0.500000` | `0.500000` | `0.000000` |
1. 项目历史日记录
文件:[daily_records.json](/E:/web/PolyWeather/data/daily_records.json)
解读:
2. 历史天气 CSV 构建出的结算标签
文件:[settlement_history.json](/E:/web/PolyWeather/artifacts/probability_calibration/settlement_history.json)
- `CRPS` 改善,说明整体概率分布质量更好。
- `MAE` 小幅改善,不再出现上一版“误差持平或略差”的问题。
- `bucket_hit_rate` 持平,没有牺牲结算桶命中率。
### 3.2 样本规模
因此本轮可以先把 EMOS 作为主概率路径上线,但仍需要线上持续观察。
- 总训练样本数:`105`
- 通过历史天气 CSV 补回的缺失 `actual_high``2`
- 历史结算标签覆盖城市数:`30`
## 4. LGBM 本轮结果
说明
本轮 LGBM 训练完成,但验证集表现不足
- 当前样本已覆盖 30 个城市,但有效监督样本量仍偏小。
- 部分城市样本数只有 `2-7` 条,城市级参数容易波动。
| 指标 | Validation |
| :-- | --: |
| LGBM MAE | `5.867` |
| DEB MAE | `1.825` |
| Best-single MAE | `0.567` |
| Median MAE | `1.700` |
## 4. 模型结构
结论:
### 4.1 当前实现
- LGBM 当前样本量和泛化质量不足。
- 不能替代“校准模型概率”板块。
- 线上继续关闭:`POLYWEATHER_LGBM_ENABLED=false`
- 可以保留模型文件用于离线跟踪,不进入前端主路径。
EMOS 属于统计后处理层,不是数值天气模型本身。当前结构位于:
## 5. 上线方式
- [probability_calibration.py](/E:/web/PolyWeather/src/analysis/probability_calibration.py)
默认代码路径已改为:
当前目标是对原有概率引擎输出进行校准:
```text
POLYWEATHER_PROBABILITY_ENGINE=emos_primary
```
- 输入:`raw_mu``raw_sigma``DEB``ensemble median/spread``peak_status` 等特征
- 输出:校准后的 `mu / sigma / distribution`
未设置环境变量时,系统默认走 `emos_primary`
### 4.2 当前运行模式
显式回滚方式:
支持三种模式:
```text
POLYWEATHER_PROBABILITY_ENGINE=emos_shadow
```
- `legacy`
- `emos_shadow`
- `emos_primary`
或:
当前建议默认模式:
```text
POLYWEATHER_PROBABILITY_ENGINE=legacy
```
- `emos_shadow`
`.env.example` 已同步暴露该配置项。
即:
## 6. 前端表现
- 对外仍展示 legacy 结果
- 后台并行计算 EMOS 结果
- 用于持续评估,不直接影响用户
今日日内分析中的“校准模型概率”会优先展示 EMOS 校准后的温度桶分布。
## 5. 本次训练参数摘要
用户看到的含义应该是:
### 5.1 全局约束
- 这是经过历史误差校准后的概率分布;
- 不是简单模型投票;
- 不直接等于最终结算概率;
- 仍应结合 METAR 实测、峰值窗口、失效条件和模型层分歧。
本次训练已加入两类约束:
## 7. 监控要求
1. `sigma_constraints`
- `min_ratio = 0.85`
- `max_ratio = 1.35`
- `absolute_min = 0.25`
- `absolute_max = 3.0`
上线后持续关注:
2. `selection_guardrails`
- `max_mae_increase = 0.02`
- `max_bucket_hit_drop = 0.01`
- `max_bucket_brier_increase = 0.05`
- `CRPS`
- `MAE`
- `bucket_hit_rate`
- 城市级样本分布
- 概率是否过度摊平
- 高温/低温尾部桶是否系统性低估
这两类约束的目的不是追求“更激进的拟合”,而是防止 EMOS 为了降低 CRPS 而把分布摊得过平,导致业务上更关键的顶桶命中和概率质量变差
如果连续回归显示 EMOS 退化,应先切回 `emos_shadow`,保留 shadow 观测,再决定是否回退到 `legacy`
### 5.2 当前选中的 blending
## 8. 已验证
本次训练产物中最终选择
本次上线前已执行
- `alpha_mu = 0.0`
- `alpha_sigma = 0.0`
```text
python scripts\fit_probability_calibration.py
python scripts\evaluate_probability_calibration.py
python scripts\train_lgbm_daily_high.py
python scripts\report_lgbm_daily_high.py
python -m pytest tests\test_probability_calibration.py tests\test_probability_rollout.py tests\test_lgbm_daily_high.py tests\test_lgbm_features.py
```
含义是
代码切换后补充执行
- 训练器在护栏约束下,没有找到足够安全的候选方案可以替代 legacy 主路径
- 因此当前正式选中的可用结果,本质上仍然锚定在 legacy
```text
python -m pytest tests\test_probability_calibration.py tests\test_probability_rollout.py
```
这是一种正确的保护行为,不是失败。说明门禁已经起作用,避免了坏校准进入主路径
## 6. 离线评估结果
评估报告来源:
- [evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.json)
### 6.1 总体结果
Legacy
- `mean_crps = 2.793938`
- `mean_mae = 2.721143`
- `bucket_hit_rate = 0.695238`
EMOS(强制 primary 评估):
- `mean_crps = 2.650216`
- `mean_mae = 2.722829`
- `bucket_hit_rate = 0.666667`
Delta
- `CRPS = -0.143722`
- `MAE = +0.001686`
- `bucket_hit_rate = -0.028571`
### 6.2 解读
这组结果说明:
1. `CRPS` 有改善
说明从“分布整体平滑度”角度看,EMOS 有一定价值。
2. `MAE` 基本持平但略差
不是大问题,但也不能算改善。
3. `bucket_hit_rate` 明显下降
这是当前最大阻塞项。对 PolyWeather 这种结算桶业务来说,顶桶命中率比单纯 CRPS 更关键。
因此,离线结论是:
- `EMOS` 有研究价值
-**离线强切 primary 仍然不合格**
## 7. 线上 Shadow 观测结果
线上 shadow 报表来源:
- [shadow_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/shadow_report.json)
### 7.1 总体结果
- `samples = 103`
- `legacy_mean_mae = 1.839223`
- `shadow_mean_mae = 1.851931`
- `delta_mae = +0.012708`
- `legacy_bucket_hit_rate = 0.669903`
- `shadow_bucket_hit_rate = 0.679612`
- `delta_bucket_hit_rate = +0.009709`
- `legacy_bucket_brier = 0.462814`
- `shadow_bucket_brier = 0.756649`
- `delta_bucket_brier = +0.293835`
### 7.2 解读
线上 shadow 结果和离线强制 primary 结果不完全相同,这是正常的。原因是:
- `shadow_report` 反映的是历史记录中实际落盘的 shadow 输出
- `evaluation_report` 反映的是离线脚本在强制 `emos_primary` 下重新计算的效果
当前线上 shadow 的含义是:
1. 顶桶命中率略有提升
`+0.97%`
2.`MAE` 轻微变差
虽然幅度不大,但没有形成明确优势
3. `bucket_brier` 明显更差
说明 shadow 分布仍然偏“摊平”,概率质量不足
这是当前最重要的信号:
- EMOS 在“顶桶命中”上偶尔能赢
- 但在“概率质量”上还不够好
## 8. 城市级观察
从当前城市级结果看,EMOS 并不是“全城市统一改善”,而是明显分化:
### 8.1 相对改善较明显的城市
- `London`
- `Hong Kong`
- `Tokyo`
- `New York`
这些城市在部分指标上看到一定改善,说明当前校准特征在这些城市上更有效。
### 8.2 风险较高的城市
- `Atlanta`
- `Miami`
- `Chicago`
- `Dallas`
- `Seattle`
这些城市常见现象是:
- 顶桶命中没有显著提高
-`bucket_brier` 明显恶化
- 或者 `MAE` 出现不必要抬升
这说明当前 EMOS 还没有形成稳定的全局校准能力,城市间异质性很强。
## 9. 当前判断
### 9.1 能不能上线为主路径
当前答案:
- **不能**
原因:
1. 离线强制 primary 时,`bucket_hit_rate` 下降
2. 线上 shadow 时,`bucket_brier` 明显变差
3. 样本量依然偏小,城市样本不均衡
4. 城市级表现分化明显
### 9.2 当前应该怎么运行
当前最合理的运行方式:
1. 保持 `emos_shadow`
2. 继续落盘 `shadow_prob_snapshot`
3. 继续维护滚动报表
4. 不修改机器人和网页的正式对外概率展示
## 10. 已完成的工程能力
目前已经具备以下能力:
1. 可离线训练
脚本:[fit_probability_calibration.py](/E:/web/PolyWeather/scripts/fit_probability_calibration.py)
2. 可离线评估
脚本:[evaluate_probability_calibration.py](/E:/web/PolyWeather/scripts/evaluate_probability_calibration.py)
3. 可导出训练样本
脚本:[export_probability_training_dataset.py](/E:/web/PolyWeather/scripts/export_probability_training_dataset.py)
4. 可历史回填 shadow 结果
脚本:[backfill_probability_shadow_history.py](/E:/web/PolyWeather/scripts/backfill_probability_shadow_history.py)
5. 可生成滚动 shadow 报表
脚本:[build_probability_shadow_report.py](/E:/web/PolyWeather/scripts/build_probability_shadow_report.py)
6. CI 已接入
包含 `ruff / pytest / frontend build / docker build workflow`
## 11. 下一步建议
### 11.1 必做
1. 扩大监督样本量
重点不是继续堆原始天气 CSV,而是补更多带 forecast snapshot 的历史样本。
2. 继续按版本沉淀训练报告
每次重训后都更新本报告或新增版本报告,避免只看单次结果。
3. 保持 `shadow` 连续观测
至少持续一段时间观察滚动指标是否稳定。
### 11.2 再做
1. 细分城市组建模
比如按气候区、结算规则、温度单位分组,而不是完全全局一套参数。
2. 优化训练目标
目前已经把 `bucket_brier` 纳入目标,但仍需进一步靠近 PolyWeather 的业务目标。
3. 补更严格的切换门槛
只有在同时满足以下条件时,才考虑切 `emos_primary`
- `CRPS` 下降
- `MAE` 不上升
- `bucket_hit_rate` 不下降
- `bucket_brier` 不上升
## 12. 结论
当前 EMOS 状态可以概括为:
- 工程上:已经完整接入,具备训练、评估、shadow 观测能力
- 模型上:有一定价值,但还不稳定
- 产品上:适合继续做 shadow,不适合切主路径
最终结论:
- **继续使用 `emos_shadow`**
- **暂不切 `emos_primary`**
- **继续积累样本并按版本跟踪训练结果**
结果:通过
+6 -6
View File
@@ -1,6 +1,6 @@
# 技术债与工程待办(v1.5.1
# 技术债与工程待办(v1.5.4
最后更新:`2026-03-31`
最后更新:`2026-04-19`
目标:在收费上线后,优先保证状态一致性、支付可靠性、可观测性和概率引擎发布可控。
@@ -29,7 +29,7 @@ flowchart TD
end
subgraph S["状态与概率"]
S1["EMOS shadow -> primary 门禁稳定化"]
S1["EMOS primary 线上监控"]
end
A --> P
@@ -49,13 +49,13 @@ flowchart TD
- 钱包异动支持独立频道路由。
- 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。
- 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。
- EMOS/CRPS 校准链路已上线 shadow 模式
- EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关
## 3. 高优先级技术债
| 项目 | 影响 | 建议动作 |
| :-- | :-- | :-- |
| EMOS 上线门禁 | 当前 `hold`,不能切 primary | 继续积累样本,重点压 `bucket_brier` |
| EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` |
| 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 |
| 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 |
@@ -76,6 +76,6 @@ flowchart TD
## 6. 下阶段里程碑
1. 稳定 EMOS shadow,达到 rollout `observe/promote` 条件
1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚
2. 补外部监控抓取与告警阈值。
3. 评估并推进支付合约 V2 升级。
+6 -6
View File
@@ -1,6 +1,6 @@
# 技术债与工程待办(v1.5.1
# 技术债与工程待办(v1.5.4
最后更新:`2026-03-31`
最后更新:`2026-04-19`
目标:在收费上线后,优先保证状态一致性、支付可靠性、可观测性和概率引擎发布可控。
@@ -29,7 +29,7 @@ flowchart TD
end
subgraph S["状态与概率"]
S1["EMOS shadow -> primary 门禁稳定化"]
S1["EMOS primary 线上监控"]
end
A --> P
@@ -49,13 +49,13 @@ flowchart TD
- 钱包异动支持独立频道路由。
- 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。
- 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。
- EMOS/CRPS 校准链路已上线 shadow 模式
- EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关
## 3. 高优先级技术债
| 项目 | 影响 | 建议动作 |
| :-- | :-- | :-- |
| EMOS 上线门禁 | 当前 `hold`,不能切 primary | 继续积累样本,重点压 `bucket_brier` |
| EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` |
| 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 |
| 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 |
@@ -76,6 +76,6 @@ flowchart TD
## 6. 下阶段里程碑
1. 稳定 EMOS shadow,达到 rollout `observe/promote` 条件
1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚
2. 补外部监控抓取与告警阈值。
3. 评估并推进支付合约 V2 升级。