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
+1
View File
@@ -55,6 +55,7 @@ POLYWEATHER_METAR_CLUSTER_TIMEOUT_SEC=3.5
METAR_CACHE_TTL_SEC=600 METAR_CACHE_TTL_SEC=600
JMA_AMEDAS_CACHE_TTL_SEC=120 JMA_AMEDAS_CACHE_TTL_SEC=120
METEOBLUE_CACHE_TTL_SEC=7200 METEOBLUE_CACHE_TTL_SEC=7200
POLYWEATHER_PROBABILITY_ENGINE=emos_primary
POLYWEATHER_LGBM_ENABLED=false POLYWEATHER_LGBM_ENABLED=false
POLYWEATHER_LGBM_MODEL_PATH=/app/artifacts/models/lgbm_daily_high.txt POLYWEATHER_LGBM_MODEL_PATH=/app/artifacts/models/lgbm_daily_high.txt
POLYWEATHER_LGBM_SCHEMA_PATH=/app/artifacts/models/lgbm_daily_high_schema.json POLYWEATHER_LGBM_SCHEMA_PATH=/app/artifacts/models/lgbm_daily_high_schema.json
+2 -2
View File
@@ -17,7 +17,7 @@ Public docs center: `/docs/intro` on the main site (bilingual product documentat
![PolyWeather Ankara analysis](docs/images/demo_ankara.png) ![PolyWeather Ankara analysis](docs/images/demo_ankara.png)
## Product Status (2026-04-18) ## Product Status (2026-04-19)
- Subscription live: `Pro Monthly 5 USDC`. - Subscription live: `Pro Monthly 5 USDC`.
- Points redemption live: `500 points = 1 USDC`, max `3 USDC` off. - Points redemption live: `500 points = 1 USDC`, max `3 USDC` off.
@@ -26,7 +26,7 @@ Public docs center: `/docs/intro` on the main site (bilingual product documentat
- Ops dashboard live: `/ops` for memberships, leaderboard, manual point grants, and payment incident triage. - Ops dashboard live: `/ops` for memberships, leaderboard, manual point grants, and payment incident triage.
- Lightweight observability live: `/healthz`, `/api/system/status`, `/metrics`. - Lightweight observability live: `/healthz`, `/api/system/status`, `/metrics`.
- Runtime state, cache, and core offline training/backfill flows now use SQLite as the primary path; legacy JSON/JSONL files remain only for migration, export, and explicit fallback input. - Runtime state, cache, and core offline training/backfill flows now use SQLite as the primary path; legacy JSON/JSONL files remain only for migration, export, and explicit fallback input.
- EMOS/CRPS pipeline is integrated in `shadow` mode with rollout gating. - EMOS/CRPS calibrated probability is now the default primary probability engine (`emos_primary`); set `POLYWEATHER_PROBABILITY_ENGINE=emos_shadow` or `legacy` to roll back.
- Intraday analysis is now positioned as a professional meteorology read: headline, confidence, base/upside/downside paths, next observation point, evidence chain, failure modes, and confirmation rules. - Intraday analysis is now positioned as a professional meteorology read: headline, confidence, base/upside/downside paths, next observation point, evidence chain, failure modes, and confirmation rules.
- Intraday modal now blocks stale cached detail during refresh, so users do not briefly trade off old city/date data before full detail arrives. - Intraday modal now blocks stale cached detail during refresh, so users do not briefly trade off old city/date data before full detail arrives.
- Calibrated model probability is now the primary probability panel. `LGBM` is shown as a calibrated probability engine when available; model consensus and market prices are secondary references. - Calibrated model probability is now the primary probability panel. `LGBM` is shown as a calibrated probability engine when available; model consensus and market prices are secondary references.
+2 -2
View File
@@ -14,7 +14,7 @@
![PolyWeather Ankara 分析页](docs/images/demo_ankara.png) ![PolyWeather Ankara 分析页](docs/images/demo_ankara.png)
## 当前产品状态(2026-04-18 ## 当前产品状态(2026-04-19
- 已上线订阅制:`Pro 月付 5 USDC` - 已上线订阅制:`Pro 月付 5 USDC`
- 已上线积分抵扣:`500 积分 = 1 USDC`,最多抵扣 `3 USDC` - 已上线积分抵扣:`500 积分 = 1 USDC`,最多抵扣 `3 USDC`
@@ -25,7 +25,7 @@
- 已上线轻量可观测性:`/healthz``/api/system/status``/metrics` - 已上线轻量可观测性:`/healthz``/api/system/status``/metrics`
- 已补最小外部监控栈:Prometheus + Alertmanager + Grafana + Telegram 告警 relay。 - 已补最小外部监控栈:Prometheus + Alertmanager + Grafana + Telegram 告警 relay。
- 运行态状态、缓存与核心离线训练/回填链路已完成 SQLite 主路径收口;legacy JSON/JSONL 仅保留给迁移、导出与显式回退输入。 - 运行态状态、缓存与核心离线训练/回填链路已完成 SQLite 主路径收口;legacy JSON/JSONL 仅保留给迁移、导出与显式回退输入。
- 已接入 EMOS/CRPS 校准链路,但当前仍保持 `emos_shadow` - EMOS/CRPS 校准概率已切为默认主路径(`emos_primary`);如需回滚可设置 `POLYWEATHER_PROBABILITY_ENGINE=emos_shadow``legacy`
- 官方增强站网已统一接入: - 官方增强站网已统一接入:
- `MGM`(土耳其) - `MGM`(土耳其)
- `CMA/NMC`(中国内地) - `CMA/NMC`(中国内地)
+243 -247
View File
@@ -6,24 +6,24 @@ label_index=0
max_feature_idx=26 max_feature_idx=26
objective=regression objective=regression
feature_names=actual_high_lag_1 actual_high_lag_2 actual_high_lag_3 actual_high_lag_7 actual_high_mean_7 actual_high_mean_14 actual_high_trend_3 open_meteo ecmwf gfs gem jma icon mgm nws deb_prediction model_median model_spread current_temp max_so_far humidity wind_speed_kt visibility_mi local_hour month weekday peak_status_code feature_names=actual_high_lag_1 actual_high_lag_2 actual_high_lag_3 actual_high_lag_7 actual_high_mean_7 actual_high_mean_14 actual_high_trend_3 open_meteo ecmwf gfs gem jma icon mgm nws deb_prediction model_median model_spread current_temp max_so_far humidity wind_speed_kt visibility_mi local_hour month weekday peak_status_code
feature_infos=[2:33] [5.5999999046325684:28] [5.5999999046325684:28] [5.4000000953674316:27.100000381469727] [7.5714287757873535:27.871429443359375] [8.9142856597900391:26.335714340209961] [-14:11] [7.5:30.899999618530273] [7.5:30.899999618530273] [8.1999998092651367:32.900001525878906] [8.1999998092651367:30.700000762939453] [8.3000001907348633:30.799999237060547] [7.5:30.899999618530273] none none [7.9000000953674316:30.899999618530273] [8.1999998092651367:30.899999618530273] [0.30000001192092896:7.5999999046325684] [0:29.200000762939453] [2:32.099998474121094] [46.900001525878906:81] [1:17] none [5:20] none [0:6] [0:2] feature_infos=[2:33] [5.5999999046325684:28] [5.5999999046325684:28] [5.4000000953674316:27.100000381469727] [7.5714287757873535:27.857143402099609] [8.9142856597900391:26.328571319580078] [-14:11] [7.5:30.899999618530273] [7.5:30.899999618530273] [8.1999998092651367:32.900001525878906] [8.1999998092651367:30.700000762939453] [8.3000001907348633:30.799999237060547] [7.5:30.899999618530273] none none [7.9000000953674316:30.899999618530273] [8.1999998092651367:30.899999618530273] [0.30000001192092896:7.5999999046325684] [0:29.200000762939453] [2:32.099998474121094] [46.900001525878906:81] [1:17] none [5:20] none [0:6] [0:2]
tree_sizes=411 401 404 404 426 314 427 422 423 424 430 427 519 431 427 518 427 429 500 427 tree_sizes=415 427 423 408 502 425 426 426 501 503 523 521 524 524 526 522 524 521 525 521
Tree=0 Tree=0
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=10 2 split_feature=10 19
split_gain=1001.8 123.037 split_gain=959.069 145.855
threshold=20.04999923706055 19.94999980926514 threshold=19.000000000000004 23.500000000000004
decision_type=10 10 decision_type=10 10
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=19.431389017899832 20.051389029050867 20.38722237745921 leaf_value=19.533250135183334 20.11658346115922 20.452535862582071
leaf_weight=6.0000000000000027 4.9999999999999982 6 leaf_weight=6.0000000000000027 5.9999999999999982 7
leaf_count=6 5 6 leaf_count=6 6 7
internal_value=19.9511 20.2346 internal_value=20.0561 20.2975
internal_weight=17 11 internal_weight=19 13
internal_count=17 11 internal_count=19 13
is_linear=0 is_linear=0
shrinkage=1 shrinkage=1
@@ -31,18 +31,18 @@ shrinkage=1
Tree=1 Tree=1
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=7 0 split_feature=7 20
split_gain=858.905 67.8176 split_gain=781.384 128.779
threshold=15.950000286102297 25.85000038146973 threshold=15.950000286102297 inf
decision_type=8 2 decision_type=8 8
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=-0.50156944513320922 0.1882326394319534 0.47938890457153316 leaf_value=-0.58666250705718992 0.39862325191497805 0.032365272504587962
leaf_weight=4.9999999999999991 4 4 leaf_weight=4.9999999999999991 3.9999999999999991 6.0000000000000009
leaf_count=5 4 4 leaf_count=5 4 6
internal_value=0.0125107 0.333811 internal_value=-0.0763085 0.178868
internal_weight=13 8 internal_weight=15 10
internal_count=13 8 internal_count=15 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -50,18 +50,18 @@ shrinkage=0.05
Tree=2 Tree=2
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=10 0 split_feature=7 1
split_gain=763.646 100.764 split_gain=714.365 143.208
threshold=20.04999923706055 25.85000038146973 threshold=15.950000286102297 20.500000000000004
decision_type=10 2 decision_type=8 10
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=-0.43713240964072081 0.10051891766488551 0.45541944503784171 leaf_value=-0.55982939004898025 0.065748141493116127 0.41610464572906491
leaf_weight=7.0000000000000009 4 4 leaf_weight=4.0000000000000027 6.9999999999999982 5
leaf_count=7 4 4 leaf_count=4 7 5
internal_value=-0.0557449 0.277969 internal_value=0.0188402 0.21173
internal_weight=15 8 internal_weight=16 12
internal_count=15 8 internal_count=16 12
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -69,56 +69,56 @@ shrinkage=0.05
Tree=3 Tree=3
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=10 0 split_feature=10 1
split_gain=466.421 90.9391 split_gain=481.327 111.706
threshold=20.04999923706055 25.85000038146973 threshold=19.000000000000004 20.500000000000004
decision_type=10 2 decision_type=8 10
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=-0.35153238058090203 0.095492970943450911 0.43264847993850702 leaf_value=-0.39178395509719849 0.07259848924974599 0.41371505260467523
leaf_weight=5.0000000000000009 4 4 leaf_weight=4.9999999999999991 6 4
leaf_count=5 4 4 leaf_count=5 6 4
internal_value=0.0273003 0.264071 internal_value=0.00876876 0.209045
internal_weight=13 8 internal_weight=15 10
internal_count=13 8 internal_count=15 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=4 Tree=4
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=8 20 split_feature=9 1 9
split_gain=680.381 113.467 split_gain=692.581 166.399 14.5487
threshold=16.19999980926514 inf threshold=16.150000095367435 20.500000000000004 21.35000038146973
decision_type=2 8 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.44872442086537651 0.38909818649292011 0.066590625792741762 leaf_value=-0.50974870681762663 -0.040919089317321793 0.37483656803766885 0.093935826048254956
leaf_weight=6.0000000000000027 4.9999999999999973 6.0000000000000009 leaf_weight=5.0000000000000027 3.9999999999999982 6 4
leaf_count=6 5 6 leaf_count=5 4 6 4
internal_value=-0.0204301 0.213185 internal_value=-0.00461354 0.175792 0.0265084
internal_weight=17 11 internal_weight=19 14 8
internal_count=17 11 internal_count=19 14 8
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=5 Tree=5
num_leaves=2 num_leaves=3
num_cat=0 num_cat=0
split_feature=3 split_feature=10 19
split_gain=658.731 split_gain=180.29 52.216
threshold=13.449999809265138 threshold=19.000000000000004 23.500000000000004
decision_type=10 decision_type=10 10
left_child=-1 left_child=-1 -2
right_child=-2 right_child=1 -3
leaf_value=-0.3789437881537846 0.33501165111859638 leaf_value=-0.23234437108039849 0.071550059318542497 0.30477037429809561
leaf_weight=7 6 leaf_weight=4.0000000000000009 5.9999999999999982 4
leaf_count=7 6 leaf_count=4 6 4
internal_value=-0.0494259 internal_value=0.0513575 0.164838
internal_weight=13 internal_weight=14 10
internal_count=13 internal_count=14 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -126,18 +126,18 @@ shrinkage=0.05
Tree=6 Tree=6
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=7 20 split_feature=10 1
split_gain=619.423 90.8198 split_gain=514.677 88.2508
threshold=15.950000286102297 inf threshold=19.000000000000004 20.500000000000004
decision_type=8 8 decision_type=10 10
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=-0.47567430973052949 0.35289269924163835 0.064359399676322912 leaf_value=-0.35969944695631645 0.079533948642866961 0.34085621833801266
leaf_weight=5.0000000000000027 4.9999999999999973 6.0000000000000009 leaf_weight=6.0000000000000027 6.9999999999999982 6
leaf_count=5 5 6 leaf_count=6 7 6
internal_value=-0.0142345 0.195511 internal_value=0.0233515 0.200144
internal_weight=16 11 internal_weight=19 13
internal_count=16 11 internal_count=19 13
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -145,94 +145,94 @@ shrinkage=0.05
Tree=7 Tree=7
num_leaves=3 num_leaves=3
num_cat=0 num_cat=0
split_feature=10 0 split_feature=7 19
split_gain=520.638 78.456 split_gain=536.147 90.9495
threshold=20.04999923706055 25.85000038146973 threshold=15.950000286102297 23.500000000000004
decision_type=8 2 decision_type=8 10
left_child=-1 -2 left_child=-1 -2
right_child=1 -3 right_child=1 -3
leaf_value=-0.38976687689622219 0.067351022859414439 0.33552634239196771 leaf_value=-0.39410252372423787 0.043377760052680979 0.29825801338468277
leaf_weight=6.0000000000000027 5.9999999999999982 5 leaf_weight=6.0000000000000027 6.9999999999999982 7
leaf_count=6 6 5 leaf_count=6 7 7
internal_value=-0.0151096 0.189249 internal_value=0.00134176 0.170818
internal_weight=17 11 internal_weight=20 14
internal_count=17 11 internal_count=20 14
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=8 Tree=8
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=10 2 split_feature=10 1 19
split_gain=499.553 74.407 split_gain=488.557 89.3384 13.4331
threshold=20.04999923706055 19.94999980926514 threshold=19.000000000000004 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.37027853230635305 0.063983469704786952 0.31299318869908649 leaf_value=-0.37621160050233188 -0.011120753735303883 0.30890050729115803 0.11846074610948561
leaf_weight=6.0000000000000027 5.9999999999999982 6 leaf_weight=6.0000000000000027 3.9999999999999982 6 4
leaf_count=6 6 6 leaf_count=6 4 6 4
internal_value=0.00223271 0.188488 internal_value=0.00127467 0.163055 0.05367
internal_weight=18 12 internal_weight=20 14 8
internal_count=18 12 internal_count=20 14 8
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=9 Tree=9
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=7 21 split_feature=7 1 19
split_gain=453.956 67.1434 split_gain=443.948 80.0165 11.7632
threshold=15.950000286102297 3.6000000238418584 threshold=15.950000286102297 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.3529831647872923 0.31961423397064215 0.07971531493323189 leaf_value=-0.35862923761208831 -0.0087223708629608175 0.29345548550287875 0.11253771036863325
leaf_weight=6.0000000000000027 4.9999999999999982 7 leaf_weight=6.0000000000000027 3.9999999999999982 6 4
leaf_count=6 5 7 leaf_count=6 4 6 4
internal_value=0.00212108 0.179673 internal_value=0.00121094 0.155428 0.0519077
internal_weight=18 12 internal_weight=20 14 8
internal_count=18 12 internal_count=20 14 8
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=10 Tree=10
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=18 19 split_feature=18 1 19
split_gain=417.969 98.6176 split_gain=408.359 104.122 22.3723
threshold=10.500000000000002 23.500000000000004 threshold=10.500000000000002 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.44873919486999481 -0.0019017819847379415 0.26350565637860973 leaf_value=-0.45071191787719683 -0.045747331281503052 0.27878270943959554 0.10691082179546355
leaf_weight=4.0000000000000027 6.9999999999999982 7 leaf_weight=4.0000000000000027 5.9999999999999982 5.9999999999999991 4
leaf_count=4 7 7 leaf_count=4 6 6 4
internal_value=0.00201502 0.130802 internal_value=0.00115039 0.114116 0.0153159
internal_weight=18 14 internal_weight=20 16 10
internal_count=18 14 internal_count=20 16 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=11 Tree=11
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=10 10 split_feature=18 1 19
split_gain=379.422 54.6231 split_gain=368.544 93.9702 20.191
threshold=20.04999923706055 27.150000572204593 threshold=10.500000000000002 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.32273159126440665 0.074079313874244698 0.29045824527740471 leaf_value=-0.42817632555961577 -0.043459965785344445 0.26484357118606566 0.10156528204679488
leaf_weight=6.0000000000000027 6.9999999999999982 5 leaf_weight=4.0000000000000027 5.9999999999999982 5.9999999999999991 4
leaf_count=6 7 5 leaf_count=4 6 6 4
internal_value=0.00191427 0.164237 internal_value=0.00109287 0.10841 0.0145501
internal_weight=18 12 internal_weight=20 16 10
internal_count=18 12 internal_count=20 16 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -240,56 +240,56 @@ shrinkage=0.05
Tree=12 Tree=12
num_leaves=4 num_leaves=4
num_cat=0 num_cat=0
split_feature=18 2 6 split_feature=10 3 19
split_gain=349.161 79.9137 12.1022 split_gain=335.123 58.0754 13.7912
threshold=10.500000000000002 19.94999980926514 1.5500000119209292 threshold=19.000000000000004 21.500000000000004 21.500000000000004
decision_type=8 10 8 decision_type=8 10 10
left_child=-1 2 -2 left_child=-1 2 -2
right_child=1 -3 -4 right_child=1 -3 -4
leaf_value=-0.41016564369201625 0.077571737766265914 0.25746693611145016 -0.045422995835542657 leaf_value=-0.31160237689812964 -0.0012943979352712635 0.29604412913322448 0.11856331576903661
leaf_weight=4.0000000000000027 3.9999999999999973 6 4.0000000000000009 leaf_weight=6.0000000000000027 3.9999999999999982 3.9999999999999991 6
leaf_count=4 4 6 4 leaf_count=6 4 4 6
internal_value=0.00181856 0.119528 0.0160744 internal_value=0.00103823 0.135027 0.0706202
internal_weight=18 14 8 internal_weight=20 14 10
internal_count=18 14 8 internal_count=20 14 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=13 Tree=13
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=18 19 split_feature=18 1 19
split_gain=315.118 72.4693 split_gain=307.6 76.0482 15.3887
threshold=10.500000000000002 23.500000000000004 threshold=10.500000000000002 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.38965735435485804 -0.00020638235977717812 0.22731021472385948 leaf_value=-0.39118738174438444 -0.036050447821617135 0.23975720206896464 0.090558854490518551
leaf_weight=4.0000000000000027 6.9999999999999982 7 leaf_weight=4.0000000000000027 5.9999999999999982 5.9999999999999991 4
leaf_count=4 7 7 leaf_count=4 6 6 4
internal_value=0.00172763 0.113552 internal_value=0.000986321 0.0990297 0.0145933
internal_weight=18 14 internal_weight=20 16 10
internal_count=18 14 internal_count=20 16 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=14 Tree=14
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=7 21 split_feature=18 1 19
split_gain=287.831 40.4927 split_gain=277.609 68.6335 13.8883
threshold=15.950000286102297 3.6000000238418584 threshold=10.500000000000002 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.28111823151508952 0.25169647216796881 0.065395631534712659 leaf_value=-0.37162801623344394 -0.034247924884160362 0.22776933908462527 0.086030908674001677
leaf_weight=6.0000000000000027 4.9999999999999982 7 leaf_weight=4.0000000000000027 5.9999999999999982 5.9999999999999991 4
leaf_count=6 5 7 leaf_count=4 6 6 4
internal_value=0.00164124 0.143021 internal_value=0.000937003 0.0940783 0.0138636
internal_weight=18 12 internal_weight=20 16 10
internal_count=18 12 internal_count=20 16 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -297,56 +297,56 @@ shrinkage=0.05
Tree=15 Tree=15
num_leaves=4 num_leaves=4
num_cat=0 num_cat=0
split_feature=18 2 6 split_feature=7 10 6
split_gain=263.177 58.9207 10.397 split_gain=252.191 44.3705 10.4139
threshold=10.500000000000002 19.94999980926514 1.5500000119209292 threshold=15.950000286102297 27.450000762939457 3.6000000238418584
decision_type=8 10 8 decision_type=8 10 8
left_child=-1 2 -2 left_child=-1 2 -2
right_child=1 -3 -4 right_child=1 -3 -4
leaf_value=-0.35611858367919891 0.071921156719327015 0.22219576636950175 -0.042079883068799957 leaf_value=-0.27032166918118777 0.11185126662254335 0.25786558985710145 0.0098028752207756035
leaf_weight=4.0000000000000027 3.9999999999999973 6 4.0000000000000009 leaf_weight=6.0000000000000027 4.9999999999999982 3.9999999999999991 5
leaf_count=4 4 6 4 leaf_count=6 5 4 5
internal_value=0.00155919 0.103753 0.0149206 internal_value=0.000890153 0.117124 0.0608271
internal_weight=18 14 8 internal_weight=20 14 10
internal_count=18 14 8 internal_count=20 14 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=16 Tree=16
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=7 21 split_feature=18 1 19
split_gain=237.631 32.9682 split_gain=231.712 55.2789 10.7397
threshold=15.950000286102297 3.6000000238418584 threshold=10.500000000000002 20.500000000000004 21.500000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.25544037123521152 0.22800186157226565 0.059899282455444326 leaf_value=-0.3395305335521695 -0.028356930613517767 0.2059211631615957 0.077412404865026457
leaf_weight=6.0000000000000027 4.9999999999999982 7 leaf_weight=4.0000000000000027 5.9999999999999982 5.9999999999999991 4
leaf_count=6 5 7 leaf_count=4 6 6 4
internal_value=0.00148123 0.129942 internal_value=0.000845644 0.0859397 0.0139508
internal_weight=18 12 internal_weight=20 16 10
internal_count=18 12 internal_count=20 16 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=17 Tree=17
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=18 19 split_feature=10 3 18
split_gain=219.898 47.5691 split_gain=209.605 36.6466 6.77648
threshold=10.500000000000002 23.500000000000004 threshold=19.000000000000004 21.500000000000004 22.000000000000004
decision_type=8 10 decision_type=8 10 10
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.3255406379699704 0.0026553549936839515 0.18698629140853881 leaf_value=-0.24645142853260027 0.022000332176685337 0.23467625677585602 0.10601718723773955
leaf_weight=4.0000000000000027 6.9999999999999982 7 leaf_weight=6.0000000000000027 5.9999999999999982 3.9999999999999991 4
leaf_count=4 7 7 leaf_count=6 6 4 4
internal_value=0.00140717 0.0948208 internal_value=0.00080336 0.10677 0.0556071
internal_weight=18 14 internal_weight=20 14 10
internal_count=18 14 internal_count=20 14 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -354,37 +354,37 @@ shrinkage=0.05
Tree=18 Tree=18
num_leaves=4 num_leaves=4
num_cat=0 num_cat=0
split_feature=11 21 12 split_feature=18 3 19
split_gain=200.198 25.8458 5.04583 split_gain=193.435 44.5018 13.9622
threshold=16.19999980926514 3.6000000238418584 22.10000038146973 threshold=10.500000000000002 21.500000000000004 21.500000000000004
decision_type=8 8 10 decision_type=8 10 10
left_child=-1 -2 -3 left_child=-1 2 -2
right_child=1 2 -4 right_child=1 -3 -4
leaf_value=-0.23448222527901319 0.22302051782608043 0.027650000527501103 0.10706844031810758 leaf_value=-0.31023144423961613 -0.02356490443150203 0.22294244468212129 0.084301546216011047
leaf_weight=6.0000000000000027 3.9999999999999973 4 4 leaf_weight=4.0000000000000027 5.9999999999999982 3.9999999999999991 6
leaf_count=6 4 4 4 leaf_count=4 6 4 6
internal_value=0.0013368 0.119246 0.0673592 internal_value=0.000763193 0.0785119 0.0303683
internal_weight=18 12 8 internal_weight=20 16 12
internal_count=18 12 8 internal_count=20 16 12
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
Tree=19 Tree=19
num_leaves=3 num_leaves=4
num_cat=0 num_cat=0
split_feature=10 10 split_feature=7 3 6
split_gain=180.679 24.1787 split_gain=173.45 29.4571 6.36567
threshold=20.04999923706055 27.150000572204593 threshold=15.950000286102297 21.500000000000004 3.6000000238418584
decision_type=8 10 decision_type=8 10 8
left_child=-1 -2 left_child=-1 2 -2
right_child=1 -3 right_child=1 -3 -4
leaf_value=-0.22275811135768878 0.053300471178122935 0.19726094961166379 leaf_value=-0.22419602423906315 0.091142139434814473 0.21179532408714297 0.011356965601444243
leaf_weight=6.0000000000000027 6.9999999999999982 5 leaf_weight=6.0000000000000027 4.9999999999999982 3.9999999999999991 5
leaf_count=6 7 5 leaf_count=6 5 4 5
internal_value=0.00126997 0.113284 internal_value=0.000725034 0.0971198 0.0512496
internal_weight=18 12 internal_weight=20 14 10
internal_count=18 12 internal_count=20 14 10
is_linear=0 is_linear=0
shrinkage=0.05 shrinkage=0.05
@@ -392,19 +392,15 @@ shrinkage=0.05
end of trees end of trees
feature_importances: feature_importances:
gem=9 max_so_far=12
open_meteo=5 actual_high_lag_2=11
current_temp=5 gem=8
actual_high_lag_1=4 current_temp=7
actual_high_lag_3=4 open_meteo=6
wind_speed_kt=4 actual_high_lag_7=4
max_so_far=3
actual_high_trend_3=2 actual_high_trend_3=2
humidity=2 gfs=2
actual_high_lag_7=1 humidity=1
ecmwf=1
jma=1
icon=1
parameters: parameters:
[boosting: gbdt] [boosting: gbdt]
+13 -13
View File
@@ -42,25 +42,25 @@
"nws" "nws"
], ],
"model_path": "artifacts\\models\\lgbm_daily_high.txt", "model_path": "artifacts\\models\\lgbm_daily_high.txt",
"sample_count": 18, "sample_count": 20,
"train_count": 6, "train_count": 8,
"validation_count": 12, "validation_count": 12,
"metrics": { "metrics": {
"validation": { "validation": {
"sample_count": 12, "sample_count": 12,
"lgbm_mae": 7.992, "lgbm_mae": 5.867,
"deb_mae": 2.375, "deb_mae": 1.825,
"best_single_mae": 1.05, "best_single_mae": 0.567,
"median_mae": 2.292 "median_mae": 1.7
}, },
"full_sample": { "full_sample": {
"sample_count": 18, "sample_count": 20,
"lgbm_mae": 3.034, "lgbm_mae": 2.66,
"deb_mae": 1.689, "deb_mae": 1.68,
"best_single_mae": 0.822, "best_single_mae": 0.775,
"median_mae": 1.711 "median_mae": 1.695
} }
}, },
"generated_at": "2026-04-15T16:41:56.814421Z", "generated_at": "2026-04-18T19:27:39.228210Z",
"trained_at": "2026-04-15T16:41:56.814421Z" "trained_at": "2026-04-18T19:27:39.228210Z"
} }
+45 -39
View File
@@ -1,20 +1,20 @@
{ {
"version": "emos-20260415170349", "version": "emos-20260418192717",
"trained_at": "2026-04-15T17:03:49.122865+00:00", "trained_at": "2026-04-18T19:27:17.348931+00:00",
"global": { "global": {
"mu": { "mu": {
"intercept": 2.45853035, "intercept": 2.60074353,
"raw_mu_coef": 2.03689031, "raw_mu_coef": 1.97765258,
"deb_coef": -1.41207502, "deb_coef": -1.37457626,
"ens_median_coef": 0.08616811, "ens_median_coef": 0.10693472,
"max_so_far_gap_coef": -0.5886898 "max_so_far_gap_coef": -0.58256593
}, },
"sigma": { "sigma": {
"intercept": 0.61260118, "intercept": 0.6373609,
"raw_sigma_coef": -1.48747774, "raw_sigma_coef": -1.41537225,
"spread_coef": 2.24562634, "spread_coef": 2.12997577,
"peak_flag_coef": -0.15906747, "peak_flag_coef": -0.08633203,
"max_so_far_gap_coef": -0.01835251 "max_so_far_gap_coef": -0.00716383
} }
}, },
"sigma_constraints": { "sigma_constraints": {
@@ -30,77 +30,83 @@
}, },
"blending": { "blending": {
"alpha_mu": 0.05, "alpha_mu": 0.05,
"alpha_sigma": 1.0 "alpha_sigma": 0.7
}, },
"cities": { "cities": {
"tokyo": { "tokyo": {
"samples": 5, "samples": 5,
"mu_bias": 2.223946, "mu_bias": 2.101101,
"sigma_scale": 2.0, "sigma_scale": 2.0,
"confidence": 0.625 "confidence": 0.625
}, },
"ankara": { "ankara": {
"samples": 6, "samples": 6,
"mu_bias": -0.396953, "mu_bias": -0.523145,
"sigma_scale": 1.094474, "sigma_scale": 1.139849,
"confidence": 0.75 "confidence": 0.75
}, },
"istanbul": { "istanbul": {
"samples": 3, "samples": 3,
"mu_bias": -0.163153, "mu_bias": -0.285183,
"sigma_scale": 0.5, "sigma_scale": 0.550171,
"confidence": 0.375 "confidence": 0.375
}, },
"hong kong": { "hong kong": {
"samples": 7, "samples": 7,
"mu_bias": 3.267553, "mu_bias": 3.234676,
"sigma_scale": 2.0, "sigma_scale": 2.0,
"confidence": 0.875 "confidence": 0.875
}, },
"taipei": { "taipei": {
"samples": 5, "samples": 5,
"mu_bias": 4.80044, "mu_bias": 4.731246,
"sigma_scale": 2.0, "sigma_scale": 2.0,
"confidence": 0.625 "confidence": 0.625
}, },
"busan": {
"samples": 3,
"mu_bias": 0.177772,
"sigma_scale": 2.0,
"confidence": 0.375
},
"seoul": { "seoul": {
"samples": 3, "samples": 3,
"mu_bias": -3.080962, "mu_bias": -3.070325,
"sigma_scale": 1.437353, "sigma_scale": 1.462196,
"confidence": 0.375 "confidence": 0.375
}, },
"milan": { "milan": {
"samples": 3, "samples": 3,
"mu_bias": -4.20255, "mu_bias": -4.249866,
"sigma_scale": 2.0, "sigma_scale": 2.0,
"confidence": 0.375 "confidence": 0.375
}, },
"shanghai": { "shanghai": {
"samples": 3, "samples": 3,
"mu_bias": 1.185335, "mu_bias": 1.080039,
"sigma_scale": 1.68386, "sigma_scale": 1.638119,
"confidence": 0.375 "confidence": 0.375
}, },
"warsaw": { "warsaw": {
"samples": 3, "samples": 3,
"mu_bias": -1.574246, "mu_bias": -1.68611,
"sigma_scale": 1.343402, "sigma_scale": 1.38114,
"confidence": 0.375 "confidence": 0.375
} }
}, },
"metrics": { "metrics": {
"sample_count": 71, "sample_count": 74,
"mean_crps": 3.226613, "mean_crps": 3.181501,
"legacy_mean_crps": 3.608885, "legacy_mean_crps": 3.474108,
"legacy_mean_mae": 3.81507, "legacy_mean_mae": 3.679324,
"legacy_bucket_hit_rate": 0.492958, "legacy_bucket_hit_rate": 0.5,
"legacy_bucket_brier": 0.873776, "legacy_bucket_brier": 0.855395,
"selected_mean_crps": 3.44742, "selected_mean_crps": 3.322469,
"selected_mean_mae": 3.749078, "selected_mean_mae": 3.618254,
"selected_bucket_hit_rate": 0.492958, "selected_bucket_hit_rate": 0.5,
"selected_bucket_brier": 0.878621, "selected_bucket_brier": 0.863048,
"selected_score": 5.241857, "selected_score": 5.08158,
"legacy_score": 5.406287, "legacy_score": 5.233586,
"filled_actual_from_history": 0, "filled_actual_from_history": 0,
"settlement_history_city_count": 30, "settlement_history_city_count": 30,
"legacy_archive_samples": 54 "legacy_archive_samples": 54
@@ -1,284 +1,293 @@
{ {
"summary": { "summary": {
"sample_count": 71, "sample_count": 74,
"filled_actual_from_history": 0, "filled_actual_from_history": 0,
"legacy": { "legacy": {
"mean_crps": 3.608885, "mean_crps": 3.474108,
"mean_mae": 3.81507, "mean_mae": 3.679324,
"bucket_hit_rate": 0.492958 "bucket_hit_rate": 0.5
}, },
"emos": { "emos": {
"mean_crps": 3.881798, "mean_crps": 3.33124,
"mean_mae": 4.378282, "mean_mae": 3.622584,
"bucket_hit_rate": 0.225352 "bucket_hit_rate": 0.5
}, },
"delta": { "delta": {
"crps": 0.272913, "crps": -0.142868,
"mae": 0.563211, "mae": -0.056741,
"bucket_hit_rate": -0.267606 "bucket_hit_rate": 0.0
} }
}, },
"by_city": { "by_city": {
"ankara": { "ankara": {
"samples": 6, "samples": 6,
"legacy_mean_crps": 1.365135, "legacy_mean_crps": 1.365135,
"emos_mean_crps": 1.454394, "emos_mean_crps": 1.392829,
"legacy_mean_mae": 1.466667, "legacy_mean_mae": 1.466667,
"emos_mean_mae": 1.781865, "emos_mean_mae": 1.444819,
"legacy_bucket_hit_rate": 0.666667, "legacy_bucket_hit_rate": 0.666667,
"emos_bucket_hit_rate": 0.333333 "emos_bucket_hit_rate": 0.666667
}, },
"atlanta": { "atlanta": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 30.449382, "legacy_mean_crps": 30.449382,
"emos_mean_crps": 30.2136, "emos_mean_crps": 29.886236,
"legacy_mean_mae": 32.015, "legacy_mean_mae": 32.015,
"emos_mean_mae": 31.431544, "emos_mean_mae": 31.322804,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"buenos aires": { "buenos aires": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 9.113412, "legacy_mean_crps": 9.113412,
"emos_mean_crps": 9.25091, "emos_mean_crps": 8.463522,
"legacy_mean_mae": 10.27, "legacy_mean_mae": 10.27,
"emos_mean_mae": 10.234011, "emos_mean_mae": 10.024533,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"busan": { "busan": {
"samples": 1, "samples": 3,
"legacy_mean_crps": 0.451701, "legacy_mean_crps": 0.276202,
"emos_mean_crps": 1.176676, "emos_mean_crps": 0.326485,
"legacy_mean_mae": 0.3, "legacy_mean_mae": 0.3,
"emos_mean_mae": 1.887548, "emos_mean_mae": 0.239636,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 1.0
}, },
"chengdu": { "chengdu": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 0.306469, "legacy_mean_crps": 0.306469,
"emos_mean_crps": 0.555327, "emos_mean_crps": 0.378812,
"legacy_mean_mae": 0.3, "legacy_mean_mae": 0.3,
"emos_mean_mae": 0.929502, "emos_mean_mae": 0.153224,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 1.0
}, },
"chicago": { "chicago": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 1.250268, "legacy_mean_crps": 1.250268,
"emos_mean_crps": 2.090175, "emos_mean_crps": 0.714669,
"legacy_mean_mae": 0.0, "legacy_mean_mae": 0.0,
"emos_mean_mae": 3.396557, "emos_mean_mae": 0.319756,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 1.0
}, },
"dallas": { "dallas": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 2.173363, "legacy_mean_crps": 2.173363,
"emos_mean_crps": 1.05572, "emos_mean_crps": 0.840297,
"legacy_mean_mae": 0.0, "legacy_mean_mae": 0.0,
"emos_mean_mae": 1.653475, "emos_mean_mae": 1.028146,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"hong kong": { "hong kong": {
"samples": 7, "samples": 7,
"legacy_mean_crps": 0.706099, "legacy_mean_crps": 0.706099,
"emos_mean_crps": 1.573367, "emos_mean_crps": 0.731926,
"legacy_mean_mae": 0.657143, "legacy_mean_mae": 0.657143,
"emos_mean_mae": 1.88803, "emos_mean_mae": 0.669911,
"legacy_bucket_hit_rate": 0.714286, "legacy_bucket_hit_rate": 0.714286,
"emos_bucket_hit_rate": 0.142857 "emos_bucket_hit_rate": 0.571429
}, },
"istanbul": { "istanbul": {
"samples": 3, "samples": 3,
"legacy_mean_crps": 1.264103, "legacy_mean_crps": 1.264103,
"emos_mean_crps": 1.266844, "emos_mean_crps": 1.214967,
"legacy_mean_mae": 1.5, "legacy_mean_mae": 1.5,
"emos_mean_mae": 1.415758, "emos_mean_mae": 1.469837,
"legacy_bucket_hit_rate": 0.333333, "legacy_bucket_hit_rate": 0.333333,
"emos_bucket_hit_rate": 0.666667 "emos_bucket_hit_rate": 0.666667
}, },
"london": { "london": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 3.885033, "legacy_mean_crps": 3.885033,
"emos_mean_crps": 4.057521, "emos_mean_crps": 3.799841,
"legacy_mean_mae": 4.135, "legacy_mean_mae": 4.135,
"emos_mean_mae": 4.313103, "emos_mean_mae": 4.027503,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.5
}, },
"lucknow": { "lucknow": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 2.487193, "legacy_mean_crps": 2.487193,
"emos_mean_crps": 2.021264, "emos_mean_crps": 2.107441,
"legacy_mean_mae": 3.205, "legacy_mean_mae": 3.205,
"emos_mean_mae": 2.47462, "emos_mean_mae": 2.876943,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.5 "emos_bucket_hit_rate": 0.0
}, },
"madrid": { "madrid": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 6.27726, "legacy_mean_crps": 6.27726,
"emos_mean_crps": 6.588692, "emos_mean_crps": 5.810228,
"legacy_mean_mae": 7.33, "legacy_mean_mae": 7.33,
"emos_mean_mae": 7.486713, "emos_mean_mae": 7.195133,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"miami": { "miami": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 28.637631, "legacy_mean_crps": 28.637631,
"emos_mean_crps": 28.800796, "emos_mean_crps": 27.592664,
"legacy_mean_mae": 30.175, "legacy_mean_mae": 30.175,
"emos_mean_mae": 30.107593, "emos_mean_mae": 29.284979,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"milan": { "milan": {
"samples": 3, "samples": 3,
"legacy_mean_crps": 4.401392, "legacy_mean_crps": 4.401392,
"emos_mean_crps": 4.947416, "emos_mean_crps": 3.782613,
"legacy_mean_mae": 4.06, "legacy_mean_mae": 4.06,
"emos_mean_mae": 5.6958, "emos_mean_mae": 3.989808,
"legacy_bucket_hit_rate": 0.666667, "legacy_bucket_hit_rate": 0.666667,
"emos_bucket_hit_rate": 0.333333 "emos_bucket_hit_rate": 0.666667
}, },
"munich": { "munich": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 3.145192, "legacy_mean_crps": 3.145192,
"emos_mean_crps": 3.200946, "emos_mean_crps": 2.990712,
"legacy_mean_mae": 3.64, "legacy_mean_mae": 3.64,
"emos_mean_mae": 3.634475, "emos_mean_mae": 3.61502,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"new york": { "new york": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 3.692845, "legacy_mean_crps": 3.692845,
"emos_mean_crps": 3.881457, "emos_mean_crps": 3.021798,
"legacy_mean_mae": 4.94, "legacy_mean_mae": 4.94,
"emos_mean_mae": 4.954702, "emos_mean_mae": 4.54437,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"paris": { "paris": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 4.013782, "legacy_mean_crps": 4.013782,
"emos_mean_crps": 4.130614, "emos_mean_crps": 3.915303,
"legacy_mean_mae": 4.265, "legacy_mean_mae": 4.265,
"emos_mean_mae": 4.314216, "emos_mean_mae": 4.179694,
"legacy_bucket_hit_rate": 0.5, "legacy_bucket_hit_rate": 0.5,
"emos_bucket_hit_rate": 0.5 "emos_bucket_hit_rate": 0.5
}, },
"sao paulo": { "sao paulo": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 5.540967, "legacy_mean_crps": 5.540967,
"emos_mean_crps": 5.483258, "emos_mean_crps": 5.018605,
"legacy_mean_mae": 6.57, "legacy_mean_mae": 6.57,
"emos_mean_mae": 6.358434, "emos_mean_mae": 6.314389,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"seattle": { "seattle": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 0.315488, "legacy_mean_crps": 0.315488,
"emos_mean_crps": 0.271998, "emos_mean_crps": 0.524119,
"legacy_mean_mae": 0.0, "legacy_mean_mae": 0.0,
"emos_mean_mae": 0.105037, "emos_mean_mae": 0.673609,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 1.0 "emos_bucket_hit_rate": 0.0
}, },
"seoul": { "seoul": {
"samples": 3, "samples": 3,
"legacy_mean_crps": 0.508331, "legacy_mean_crps": 0.508331,
"emos_mean_crps": 1.718042, "emos_mean_crps": 0.520762,
"legacy_mean_mae": 0.2, "legacy_mean_mae": 0.2,
"emos_mean_mae": 2.57121, "emos_mean_mae": 0.247862,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 1.0
}, },
"shanghai": { "shanghai": {
"samples": 3, "samples": 3,
"legacy_mean_crps": 0.299116, "legacy_mean_crps": 0.299116,
"emos_mean_crps": 0.553444, "emos_mean_crps": 0.402453,
"legacy_mean_mae": 0.1, "legacy_mean_mae": 0.1,
"emos_mean_mae": 0.71746, "emos_mean_mae": 0.189437,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.666667 "emos_bucket_hit_rate": 1.0
}, },
"shenzhen": { "shenzhen": {
"samples": 1, "samples": 1,
"legacy_mean_crps": 1.198351, "legacy_mean_crps": 1.198351,
"emos_mean_crps": 0.507942, "emos_mean_crps": 1.490963,
"legacy_mean_mae": 1.3, "legacy_mean_mae": 1.3,
"emos_mean_mae": 0.644561, "emos_mean_mae": 1.628189,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"singapore": { "singapore": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 0.281993, "legacy_mean_crps": 0.281993,
"emos_mean_crps": 0.877023, "emos_mean_crps": 0.370374,
"legacy_mean_mae": 0.15, "legacy_mean_mae": 0.15,
"emos_mean_mae": 1.142765, "emos_mean_mae": 0.118005,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.5 "emos_bucket_hit_rate": 1.0
}, },
"taipei": { "taipei": {
"samples": 5, "samples": 5,
"legacy_mean_crps": 0.950739, "legacy_mean_crps": 0.950739,
"emos_mean_crps": 1.257972, "emos_mean_crps": 1.042332,
"legacy_mean_mae": 0.94, "legacy_mean_mae": 0.94,
"emos_mean_mae": 1.687014, "emos_mean_mae": 0.951241,
"legacy_bucket_hit_rate": 0.6, "legacy_bucket_hit_rate": 0.6,
"emos_bucket_hit_rate": 0.2 "emos_bucket_hit_rate": 0.6
}, },
"tel aviv": { "tel aviv": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 0.446758, "legacy_mean_crps": 0.446758,
"emos_mean_crps": 0.482341, "emos_mean_crps": 0.578691,
"legacy_mean_mae": 0.3, "legacy_mean_mae": 0.3,
"emos_mean_mae": 0.62659, "emos_mean_mae": 0.116966,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.5 "emos_bucket_hit_rate": 1.0
}, },
"tokyo": { "tokyo": {
"samples": 5, "samples": 5,
"legacy_mean_crps": 0.879366, "legacy_mean_crps": 0.879366,
"emos_mean_crps": 0.989336, "emos_mean_crps": 0.876608,
"legacy_mean_mae": 1.022, "legacy_mean_mae": 1.022,
"emos_mean_mae": 1.450474, "emos_mean_mae": 1.008317,
"legacy_bucket_hit_rate": 0.2, "legacy_bucket_hit_rate": 0.2,
"emos_bucket_hit_rate": 0.2 "emos_bucket_hit_rate": 0.4
}, },
"toronto": { "toronto": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 5.497916, "legacy_mean_crps": 5.497916,
"emos_mean_crps": 6.296632, "emos_mean_crps": 5.268783,
"legacy_mean_mae": 6.33, "legacy_mean_mae": 6.33,
"emos_mean_mae": 7.003984, "emos_mean_mae": 6.388522,
"legacy_bucket_hit_rate": 0.0, "legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.0
}, },
"warsaw": { "warsaw": {
"samples": 3, "samples": 3,
"legacy_mean_crps": 1.618875, "legacy_mean_crps": 1.618875,
"emos_mean_crps": 1.649515, "emos_mean_crps": 1.524219,
"legacy_mean_mae": 2.056667, "legacy_mean_mae": 2.056667,
"emos_mean_mae": 2.073494, "emos_mean_mae": 2.006524,
"legacy_bucket_hit_rate": 0.333333, "legacy_bucket_hit_rate": 0.333333,
"emos_bucket_hit_rate": 0.0 "emos_bucket_hit_rate": 0.333333
}, },
"wellington": { "wellington": {
"samples": 2, "samples": 2,
"legacy_mean_crps": 0.364919, "legacy_mean_crps": 0.364919,
"emos_mean_crps": 0.939463, "emos_mean_crps": 0.484124,
"legacy_mean_mae": 0.15, "legacy_mean_mae": 0.15,
"emos_mean_mae": 1.007263, "emos_mean_mae": 0.123335,
"legacy_bucket_hit_rate": 1.0, "legacy_bucket_hit_rate": 1.0,
"emos_bucket_hit_rate": 0.5 "emos_bucket_hit_rate": 1.0
},
"wuhan": {
"samples": 1,
"legacy_mean_crps": 0.476225,
"emos_mean_crps": 0.578405,
"legacy_mean_mae": 0.8,
"emos_mean_mae": 0.962852,
"legacy_bucket_hit_rate": 0.0,
"emos_bucket_hit_rate": 0.0
} }
} }
} }
+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-20260418192717`
- 当前默认运行模式应继续保持 `emos_shadow` - 训练时间:`2026-04-18T19:27:17Z`
- 现阶段 **不建议切换到 `emos_primary`** - 样本数:`74`
## 2. 本次训练版本
- 校准版本:`emos-20260320130245`
- 训练时间:`2026-03-20T13:02:45.903772+00:00`
- 参数文件:[default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json) - 参数文件:[default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json)
- 离线评估报告:[evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.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 构建出的结算标签 - `CRPS` 改善,说明整体概率分布质量更好。
文件:[settlement_history.json](/E:/web/PolyWeather/artifacts/probability_calibration/settlement_history.json) - `MAE` 小幅改善,不再出现上一版“误差持平或略差”的问题。
- `bucket_hit_rate` 持平,没有牺牲结算桶命中率。
### 3.2 样本规模 因此本轮可以先把 EMOS 作为主概率路径上线,但仍需要线上持续观察。
- 总训练样本数:`105` ## 4. LGBM 本轮结果
- 通过历史天气 CSV 补回的缺失 `actual_high``2`
- 历史结算标签覆盖城市数:`30`
说明 本轮 LGBM 训练完成,但验证集表现不足
- 当前样本已覆盖 30 个城市,但有效监督样本量仍偏小。 | 指标 | Validation |
- 部分城市样本数只有 `2-7` 条,城市级参数容易波动。 | :-- | --: |
| 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` 等特征 未设置环境变量时,系统默认走 `emos_primary`
- 输出:校准后的 `mu / sigma / distribution`
### 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` - `CRPS`
- `max_mae_increase = 0.02` - `MAE`
- `max_bucket_hit_drop = 0.01` - `bucket_hit_rate`
- `max_bucket_brier_increase = 0.05` - 城市级样本分布
- 概率是否过度摊平
- 高温/低温尾部桶是否系统性低估
这两类约束的目的不是追求“更激进的拟合”,而是防止 EMOS 为了降低 CRPS 而把分布摊得过平,导致业务上更关键的顶桶命中和概率质量变差 如果连续回归显示 EMOS 退化,应先切回 `emos_shadow`,保留 shadow 观测,再决定是否回退到 `legacy`
### 5.2 当前选中的 blending ## 8. 已验证
本次训练产物中最终选择 本次上线前已执行
- `alpha_mu = 0.0` ```text
- `alpha_sigma = 0.0` 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 主路径 ```text
- 因此当前正式选中的可用结果,本质上仍然锚定在 legacy 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 end
subgraph S["状态与概率"] subgraph S["状态与概率"]
S1["EMOS shadow -> primary 门禁稳定化"] S1["EMOS primary 线上监控"]
end end
A --> P A --> P
@@ -49,13 +49,13 @@ flowchart TD
- 钱包异动支持独立频道路由。 - 钱包异动支持独立频道路由。
- 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。 - 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。
- 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。 - 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。
- EMOS/CRPS 校准链路已上线 shadow 模式 - EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关
## 3. 高优先级技术债 ## 3. 高优先级技术债
| 项目 | 影响 | 建议动作 | | 项目 | 影响 | 建议动作 |
| :-- | :-- | :-- | | :-- | :-- | :-- |
| EMOS 上线门禁 | 当前 `hold`,不能切 primary | 继续积累样本,重点压 `bucket_brier` | | EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` |
| 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 | | 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 |
| 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 | | 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 |
@@ -76,6 +76,6 @@ flowchart TD
## 6. 下阶段里程碑 ## 6. 下阶段里程碑
1. 稳定 EMOS shadow,达到 rollout `observe/promote` 条件 1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚
2. 补外部监控抓取与告警阈值。 2. 补外部监控抓取与告警阈值。
3. 评估并推进支付合约 V2 升级。 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 end
subgraph S["状态与概率"] subgraph S["状态与概率"]
S1["EMOS shadow -> primary 门禁稳定化"] S1["EMOS primary 线上监控"]
end end
A --> P A --> P
@@ -49,13 +49,13 @@ flowchart TD
- 钱包异动支持独立频道路由。 - 钱包异动支持独立频道路由。
- 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。 - 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。
- 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。 - 轻量可观测性已上线(`/healthz``/api/system/status``/metrics`)。
- EMOS/CRPS 校准链路已上线 shadow 模式 - EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关
## 3. 高优先级技术债 ## 3. 高优先级技术债
| 项目 | 影响 | 建议动作 | | 项目 | 影响 | 建议动作 |
| :-- | :-- | :-- | | :-- | :-- | :-- |
| EMOS 上线门禁 | 当前 `hold`,不能切 primary | 继续积累样本,重点压 `bucket_brier` | | EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` |
| 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 | | 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 |
| 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 | | 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 |
@@ -76,6 +76,6 @@ flowchart TD
## 6. 下阶段里程碑 ## 6. 下阶段里程碑
1. 稳定 EMOS shadow,达到 rollout `observe/promote` 条件 1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚
2. 补外部监控抓取与告警阈值。 2. 补外部监控抓取与告警阈值。
3. 评估并推进支付合约 V2 升级。 3. 评估并推进支付合约 V2 升级。
+3 -2
View File
@@ -13,6 +13,7 @@ from src.analysis.settlement_rounding import apply_city_settlement, is_exact_set
ENGINE_MODE_LEGACY = "legacy" ENGINE_MODE_LEGACY = "legacy"
ENGINE_MODE_EMOS_SHADOW = "emos_shadow" ENGINE_MODE_EMOS_SHADOW = "emos_shadow"
ENGINE_MODE_EMOS_PRIMARY = "emos_primary" ENGINE_MODE_EMOS_PRIMARY = "emos_primary"
DEFAULT_ENGINE_MODE = ENGINE_MODE_EMOS_PRIMARY
VALID_ENGINE_MODES = { VALID_ENGINE_MODES = {
ENGINE_MODE_LEGACY, ENGINE_MODE_LEGACY,
ENGINE_MODE_EMOS_SHADOW, ENGINE_MODE_EMOS_SHADOW,
@@ -53,10 +54,10 @@ def resolve_probability_engine_mode(explicit_mode: Optional[str] = None) -> str:
mode = str( mode = str(
explicit_mode explicit_mode
or os.getenv("POLYWEATHER_PROBABILITY_ENGINE") or os.getenv("POLYWEATHER_PROBABILITY_ENGINE")
or ENGINE_MODE_EMOS_SHADOW or DEFAULT_ENGINE_MODE
).strip().lower() ).strip().lower()
if mode not in VALID_ENGINE_MODES: if mode not in VALID_ENGINE_MODES:
return ENGINE_MODE_EMOS_SHADOW return DEFAULT_ENGINE_MODE
return mode return mode
+12
View File
@@ -8,6 +8,7 @@ from src.analysis.probability_calibration import (
apply_probability_calibration, apply_probability_calibration,
build_probability_features, build_probability_features,
fit_calibration, fit_calibration,
resolve_probability_engine_mode,
) )
@@ -51,6 +52,17 @@ def _write_calibration(tmp_path: Path):
return path return path
def test_default_probability_engine_is_emos_primary(monkeypatch):
monkeypatch.delenv("POLYWEATHER_PROBABILITY_ENGINE", raising=False)
assert resolve_probability_engine_mode() == ENGINE_MODE_EMOS_PRIMARY
assert resolve_probability_engine_mode("unknown-mode") == ENGINE_MODE_EMOS_PRIMARY
monkeypatch.setenv("POLYWEATHER_PROBABILITY_ENGINE", ENGINE_MODE_EMOS_SHADOW)
assert resolve_probability_engine_mode() == ENGINE_MODE_EMOS_SHADOW
def test_shadow_mode_keeps_legacy_distribution(tmp_path): def test_shadow_mode_keeps_legacy_distribution(tmp_path):
calibration_path = _write_calibration(tmp_path) calibration_path = _write_calibration(tmp_path)
features = build_probability_features( features = build_probability_features(