需求统计与预测 DSF · v0.11
discipline/benchmarks/dsf-bench.md
📑 本页目录

DSF-Bench · 需求预测基准(设计 + 结果)

状态:v0.1(Round 3 首发)· 代码:scripts/dsf_bench.py · 数据:data/dsf_bench/ 对应研究问题:RQ-D2(基础模型增益何时存在)、RQ-C1(分布交付)、RQ-C2(校准维护)

1. 设计原则

  1. 统计基线必选:naive / snaive / mean / drift / ETS,禁止只对比「ML vs 无基准」。
  2. 分布输出必评:所有模型输出分位(残差 bootstrap),用 pinball / CRPS 评分。
  3. 组合必评:简单平均组合作为对照(支柱 6 证据)。
  4. 滚动样本外:扩展窗口,避免单点切分。
  5. 活数据机制:本地信号(AppTrends 榜单热度)自动摄入,长度不足自动跳过; 随采集积累自动进入基准(当前仅 4 天,跳过)。
  6. 扩展模型槽:时序基础模型(Chronos/TimesFM 等)通过 forecast_fn 接口接入; 当前环境(1GB 内存)无法运行 torch,列为「待运行」,不伪造结果。

2. 数据集(v0.1)

数据集 来源 粒度/长度 用途 状态
ETTh1 ETDataset(公开) 小时级 17420 点 需求型时序(油温/负荷) 已就绪
ETTh2 ETDataset(公开) 小时级 17420 点 同上(更高波动) 已就绪
apptrends_board_heat 本项目 trends.db 日级(积累中) 榜单热度信号(数字尾气实例) 自动摄入,长度不足跳过

原始数据与许可:data/dsf_bench/raw/README.md。

3. 评估协议

4. 结果

追加规则:每次运行追加「结果快照」小节,标注日期、代码版本、环境;旧结果不删除。

结果快照 · 2026-08-10(v0.1 · 运行约 3 分钟)

协议:扩展窗口(train≥70%,每 96 步评估),horizon 24,指标按全部评估点平均。 模型:naive / snaive / mean / drift / ETS(固定平滑参数 0.3/0.1/0.1)+ 五模型简单平均组合。数据:ETTh1、ETTh2 的 OT 通道(小时级)。

数据集 模型 MASE pinball@0.1 @0.5 @0.9 QS
ETTh1 naive 1.7448 0.2949 0.6036 0.4392 0.4965
ETTh1 snaive 2.0251 0.4098 0.6920 0.3464 0.5481
ETTh1 mean 11.601 1.0885 3.4031 1.9854 2.5496
ETTh1 drift 1.7552 1.4489 2.0404 0.5281 1.6250
ETTh1 ets 2.2536 0.4420 0.7797 0.4353 0.6224
ETTh1 combination 2.5618 0.4616 0.8796 0.5962 0.7055
ETTh2 naive 4.4941 0.6873 2.0104 2.2870 1.7871
ETTh2 snaive 3.3634 0.7578 1.4792 0.7185 1.1384
ETTh2 mean 12.913 2.0356 5.6747 2.2667 3.9850
ETTh2 drift 4.5033 2.1181 3.6785 1.5345 2.8921
ETTh2 ets 3.9162 1.0036 1.7341 1.0959 1.4223
ETTh2 combination 4.2272 0.8771 2.1918 0.9995 1.5951

解读(v0.1)

  1. naive/snaive 是强基线:两个数据集上分位评分均优于固定参数 ETS; 与 M4/M5「简单方法不可小觑」的结论一致(支柱 7 基准纪律的实证支持)。
  2. 简单平均组合被差成员拖累:mean/drift 在趋势序列上大幅拉高组合误差; 支持 RQ-D1 的方向——组合需要修剪或加权(先剔除明显劣模型,或用中位数组合)。
  3. ETS 弱化:固定平滑参数 + 不优化的 ETS 是弱化版;优化版 ETS/ARIMA 作为 v0.2 升级项(运行时预算内)。

明细 JSON:data/dsf_bench/results/results-20260810-080244.json

5. 扩展接口

# 在 scripts/dsf_bench.py 的 MODELS 中注册新模型:
#   name: 模型名
#   fn(train_y, horizon, season) -> dict(quantiles=np.ndarray, point=np.ndarray)
# 时序基础模型示例(待运行环境):
#   def chronos_zero_shot(train_y, horizon, season):
#       import torch, chronos  # 需 torch(≥4GB 内存环境)
#       model = chronos.ChronosPipeline.from_pretrained("amazon/chronos-t5-small")
#       fc = model.predict(torch.tensor(train_y, dtype=torch.float32), prediction_length=horizon)
#       q = torch.quantile(fc, torch.tensor([0.05,...,0.95])).numpy()
#       return {"quantiles": q, "point": fc.mean().numpy()}

6. 已知边界