DEB 接入小时级误差计算,多模型权重基于每日+小时 MAE 融合
新增 compute_hourly_model_errors 聚合逐模型小时 MAE/RMSE 新增 _blend_mae 按样本数加权混合每日/小时误差(24样本=70%小时权重) calculate_dynamic_weights 从 daily_record 读取 hourly_error 参与权重计算 update_daily_record 接受并持久化 hourly_error 字段 Tested: ruff check, pytest 186/186
This commit is contained in:
@@ -89,3 +89,60 @@ def test_deb_weighted_path_uses_deduped_family_values(monkeypatch):
|
||||
assert blended < 30.0
|
||||
assert "ICON-D2" in info
|
||||
assert "家族去重" in info
|
||||
|
||||
|
||||
def test_compute_hourly_model_errors_basic():
|
||||
from src.analysis.deb_algorithm import compute_hourly_model_errors
|
||||
|
||||
hourly_forecasts = {
|
||||
"ECMWF": [15.0, 15.5, 16.0, 16.5, 17.0, 17.5],
|
||||
"GFS": [14.5, 15.0, 15.5, 16.0, 16.5, 17.0],
|
||||
}
|
||||
hourly_actuals = [15.2, 15.8, 16.3, 16.8, 17.4, 18.0]
|
||||
|
||||
result = compute_hourly_model_errors(hourly_forecasts, hourly_actuals)
|
||||
|
||||
assert "ECMWF" in result
|
||||
assert "GFS" in result
|
||||
assert result["ECMWF"]["samples"] == 6
|
||||
assert result["GFS"]["samples"] == 6
|
||||
# ECMWF predicted lower, should have smaller MAE
|
||||
assert result["ECMWF"]["mae"] < result["GFS"]["mae"]
|
||||
assert result["ECMWF"]["rmse"] > 0
|
||||
assert result["GFS"]["rmse"] > 0
|
||||
|
||||
|
||||
def test_compute_hourly_model_errors_too_few_samples():
|
||||
from src.analysis.deb_algorithm import compute_hourly_model_errors
|
||||
|
||||
hourly_forecasts = {"ECMWF": [15.0, 15.5]}
|
||||
hourly_actuals = [15.0, 15.5]
|
||||
|
||||
result = compute_hourly_model_errors(hourly_forecasts, hourly_actuals)
|
||||
assert result == {} # < 6 samples, returns empty
|
||||
|
||||
|
||||
def test_blend_mae_with_hourly():
|
||||
from src.analysis.deb_algorithm import _blend_mae
|
||||
|
||||
# Full 24 hourly samples → 0.7 hourly weight
|
||||
h_err = {"mae": 0.8, "rmse": 1.0, "samples": 24}
|
||||
blended = _blend_mae(1.5, h_err)
|
||||
# 1.5 * 0.3 + 0.8 * 0.7 = 0.45 + 0.56 = 1.01
|
||||
assert abs(blended - 1.01) < 0.01
|
||||
|
||||
# 12 hourly samples → ~0.35 hourly weight
|
||||
h_err2 = {"mae": 1.0, "rmse": 1.2, "samples": 12}
|
||||
blended2 = _blend_mae(2.0, h_err2)
|
||||
# 12/24 * 0.7 = 0.35 hourly weight
|
||||
expected = 2.0 * (1 - 0.35) + 1.0 * 0.35 # 1.30 + 0.35 = 1.65
|
||||
assert abs(blended2 - expected) < 0.01
|
||||
|
||||
# No hourly error → returns daily MAE unchanged
|
||||
blended3 = _blend_mae(2.5, None)
|
||||
assert blended3 == 2.5
|
||||
|
||||
# Too few samples (< 6) → returns daily MAE unchanged
|
||||
h_err4 = {"mae": 0.5, "samples": 3}
|
||||
blended4 = _blend_mae(3.0, h_err4)
|
||||
assert blended4 == 3.0
|
||||
|
||||
Reference in New Issue
Block a user