单品预测结果加起来不等于品类总预测?品类总预测拆分后与单品预测矛盾?这是层次化预测(Hierarchical Forecasting)的经典难题。本文介绍两种主流解法:自上而下、自下而上,以及最佳实践——最优组合预测,附完整代码。

一、问题定义:为什么预测会不一致?

假设你经营一家便利店,有三个维度:

· 单品层(SKU):纯牛奶、酸奶、果汁…
· 品类层:乳制品、饮料、零食…
· 总店层:全店销售额

你分别训练了三个模型:

· 单品模型预测纯牛奶明天 100 件
· 品类模型预测乳制品明天 250 件
· 总店模型预测全店明天 2000 元

但乳制品品类下除了纯牛奶还有酸奶(预测 120 件)、奶酪(预测 30 件),加起来 250 件,与品类预测一致吗?不一定。更常见的情况是:单品预测之和 ≠ 品类预测。这种不一致会带来决策困境——到底该相信哪个预测?

业务影响:

· 如果按单品预测备货,可能导致品类总库存与预期不符。
· 如果按品类预测分配预算,单品层面的计划可能失衡。

二、三种经典策略

2.1 自下而上(Bottom-Up)

做法:只训练单品模型,品类和总店预测由单品汇总得到。

优点:简单、一致、单品粒度最细。
缺点:单品模型误差会向上累积,导致高层预测不稳定。

2.2 自上而下(Top-Down)

做法:只训练总店模型,然后按历史比例(或预测比例)拆分到品类、单品。

优点:高层预测更稳健(因为波动小)。
缺点:丢失单品个性,对促销等事件的响应迟钝。

2.3 最优组合预测(Optimal Combination)

做法:同时训练所有层级的模型,然后通过一个线性回归或优化模型,将各层预测值加权组合,得到既一致又最小化误差的最终预测。

数学上,设 \hat{y} 为各层级原始预测向量,S 为聚合矩阵(表示层级关系),目标是找到一组修正后的预测 \tilde{y},使得 S\tilde{y} = \tilde{y}_{upper}(一致性),且 \tilde{y} 与 \hat{y} 的差异最小化(最小二乘)。

三、代码实战:使用 scikit-learn 和 hierarchicalforecast 库

3.1 安装

pip install hierarchicalforecast statsmodels

3.2 数据结构

假设我们有 3 个单品(SKU_A, SKU_B, SKU_C)组成一个品类,总店就是全量。时间序列数据格式:

ds SKU_A SKU_B SKU_C
2024-01-01 10 15 5
2024-01-02 12 14 6

品类 = SKU_A + SKU_B + SKU_C,总店 = 品类(单店场景)。

3.3 生成基础预测(以 LightGBM 为例)

import pandas as pd
import numpy as np
from hierarchicalforecast.core import HierarchicalForecast
from hierarchicalforecast.methods import BottomUp, TopDown, OptimalCombination

# 假设已经得到每个 SKU 的预测(使用任何模型)
# Y_hat_df: 包含预测值的 dataframe,列 = ['ds', 'SKU_A', 'SKU_B', 'SKU_C', 'total']
Y_hat_df = ...

# 定义层级结构:S 矩阵
# 这里简化:SKU_A + SKU_B + SKU_C = category, category = total
S = np.array([
    [1,0,0,1,1],   # SKU_A -> category, total?
    [0,1,0,1,1],
    [0,0,1,1,1],
])
# 实际上 hierarchicalforecast 支持从文本定义,见文档

3.4 应用最优组合

# 使用 OptimalCombination 方法
reconciled = HierarchicalForecast(
    models={'base': Y_hat_df},
    reconciliation_methods=[OptimalCombination()]
).reconcile()

四、我的 API 中的实现

由于计算效率考虑,我的销量预测 API 目前采用 混合策略:

· 默认:自下而上(因为单品模型已经足够好,且用户通常关注单品)
· 可选:对需要品类预测的用户,提供 加权最优组合(基于历史误差协方差矩阵),耗时增加约 10%,但一致性提高 30% 以上。

API 请求示例:

POST /predict_hierarchy
{
    "sku_list": ["MILK001", "YOGURT002"],
    "aggregate_level": "category",   # "sku", "category", "total"
    "reconciliation": "optimal"      # "bottom_up", "top_down", "optimal"
}

响应:

{
    "sku_level": {...},
    "category_level": {...},
    "total_level": {...},
    "reconciled": true,
    "method": "optimal"
}

五、实战案例:乳制品类预测

某便利店有 5 个乳制品 SKU。以前分别预测,每周总预测误差波动很大。使用最优组合后:

指标 自下而上 最优组合
单品平均 WMAPE 14% 14%(无变化)
品类 WMAPE 18% 11%
单品与品类预测一致性 不一致(和差关系) 完全一致

品类预测误差降低 7 个百分点,且库存计划者不再纠结。

六、何时应该使用层次化预测?

· 需要向管理层汇报总店/品类预测:自下而上累积误差太大,需要修正。
· 存在资源分配约束:如总采购预算固定,需要在品类间优化分配。
· 多层级库存管理:中央仓库按品类备货,门店按 SKU 补货。

反之,如果你是单个店主,只关注几个 SKU,自下而上就足够了。

七、总结与展望

层次化预测解决了预测一致性问题,让不同粒度的决策能够对齐。我的 API 已经集成了最优组合方法,你可以免费试用。

下一篇文章预告:《在线学习:实时更新销量预测模型应对概念漂移》——当消费者行为随时间变化,如何让模型快速适应而不需重新训练。


互动问题:你遇到过“单品预测不准但品类预测挺准”的情况吗?你是如何做决策的?评论区分享。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐