调 α 救不了的症状
上一篇结尾留了个症状:SES 的误差几乎全为正。团队第一反应是调 α------从 0.3 调到 0.7,误差小了一点,但还是全为正。又调到 0.9,预测开始剧烈抖动,业务投诉「数字一天一个样」。
原因很简单,也很残酷:不是参数问题,是模型眼里没有「坡度」。 SES 像个只看海拔不看坡度的登山者:知道自己站在多高,不知道路在往上还是往下,于是每个转弯都慢一步。调 α 只是让他「回头看得更近」,并不能让他看见坡。
Holt 的改法只有一句话:再记一个数 b(t),每期大概涨多少。这块「坡度表」就是本篇全部。
两个状态方程 + 一个外推公式
lt=αyt+(1−α)(lt−1+ϕbt−1)
bt=β(lt−lt−1)+(1−β)ϕbt−1
y^t+h=lt+(ϕ+ϕ2+⋯+ϕh)bt
逐行翻译:
- 水平:先按上期坡度走一步(l + φb)得到「预期位置」,再和本期实际折中。人话:「我猜今天会比昨天高 b,实际呢?」
- 趋势:用本期水平的实际抬升(l_t − l_{t−1})修正坡度,但别全信------β 小则坡度估计稳,不被单期噪声带跑。人话:「这次抬升有多少是真坡、多少是颠簸?」
- 外推 :未来 h 期 = 当前水平 + 坡度累加 h 步。φ=1 是纯线性外推;φ<1 是阻尼------坡度逐期刹车。
手算全表:α=0.5,β=0.3,φ=1
初始化 l(1) = y(1) = 120,b(1) = y(2) − y(1) = 12。拿 t=3(y=125)走一遍三步:
- 预测:ŷ(3) = l(2) + φ·b(2) = 132 + 12 = 144.0
- 水平:l(3) = 0.5×125 + 0.5×(132 + 12) = 62.5 + 72 = 134.5
- 趋势:b(3) = 0.3×(134.5 − 132) + 0.7×12 = 0.75 + 8.4 = 9.15
| t | y(t) | 预测 ŷ(t) | 水平 l(t) | 趋势 b(t) |
|---|---|---|---|---|
| 1 | 120 | 120.0000 | 120.0000 | 12.0000 |
| 2 | 132 | 132.0000 | 132.0000 | 12.0000 |
| 3 | 125 | 144.0000 | 134.5000 | 9.1500 |
| 4 | 141 | 143.6500 | 142.3250 | 8.7525 |
| 5 | 138 | 151.0775 | 144.5388 | 6.7909 |
| 6 | 150 | 151.3296 | 150.6648 | 6.5914 |
| 7 | 145 | 157.2562 | 151.1281 | 4.7530 |
| 8 | 158 | 155.8811 | 156.9406 | 5.0708 |
未来 3 期(φ=1):162.01、167.08、172.15 (每期 +5.07,就是 b(8))。对比 SES 的第 9 期预测 145.10------差距 17 件,就是「承认坡度」的价值。
注意 b 列的戏剧性:从 12 一路被修正到 4.75 又回到 5.07。初始坡度 12 是拿头两期差值估的,太躁;β=0.3 让它几期内回归到 5 左右。这就是 β 的作用:让坡度估计「慢半拍但稳」。
交叉验证:Holt 的在线坡度 vs 全样本回归斜率
用最小二乘对同样 8 期数据拟合一条直线,斜率 = Σ(t−t̄)(y−ȳ) ÷ Σ(t−t̄)² = 201.5 ÷ 42 = 4.7976。
Holt 在第 8 期的在线坡度 b(8) = 5.0708 ------和用全部 8 个点算出的回归斜率同量级。区别在于:回归要等数据齐了才能算、且假设斜率恒定;Holt 每期都在更新、能跟踪斜率变化。在线估计与离线估计互相印证,是检查实现是否写错的最快方法。
刹车片:为什么「一直涨」是幻觉
φ=1 意味着模型相信当前增速永远持续。外推 12 期看代价:

| 外推 h | 1 | 4 | 8 | 12 |
|---|---|---|---|---|
| 线性 φ=1.0 | 2286.3 | 2738.4 | 3341.2 | 3944.0 |
| 阻尼 φ=0.85 | 2230.9 | 2479.4 | 2668.4 | 2767.1 |
| 差值 | 55.4 | 259.0 | 672.8 | 1177.0(+43%) |
12 期后线性外推比阻尼高 43%。拿这个数字去采购,就是 43% 的过剩库存。
阻尼的数学含义很干净:累加系数 φ + φ² + ... + φʰ 有上界。φ=0.85 时,h→∞ 的极限是 φ ÷ (1−φ) = 5.667 ------即无论外推多远,坡度最多再贡献 5.667 个 b 的增量,曲线自己会「累」。手算验证 h=12:Σ = 0.85×(1−0.85¹²)÷0.15 = 0.85×0.8578÷0.15 = 4.861,已经接近上限的 86%。
经验法则:预测步长 h ≥ 4,就用阻尼趋势(φ 取 0.8~0.98)。 商业世界几乎没有永远线性的增长:市场饱和、竞品跟进、基数变大。φ 是把「增长会放缓」这个先验写进模型------一块便宜的刹车片。
φ 的选择速查:
| 场景 | 建议 φ | 理由 |
|---|---|---|
| h ≤ 3 的短期补货 | 1.0 可接受 | 短期趋势近似线性 |
| h = 4~13 的周/月计划 | 0.9~0.98 | 轻刹车 |
| h ≥ 13 或年度预算 | 0.8~0.9 | 重刹车,防止趋势永动机 |
趋势断裂:坡突然变了怎么办
趋势不是恒定的。检测断裂的三个廉价信号:
-
残差连续同符号:连续 k ≥ 5 期残差同号 → 水平或趋势已漂移(第 15 篇归因树的第一层)。
-
坡度符号翻转:b(t) 由正转负且持续 2 期以上 → 增长结束,检查是否该切换模型或重置 b。
-
坡度幅度突变:|b(t) − b(t−1)| > 3 × 近期 |b| 的标准差 → 可能是一次性事件(大促、断货)污染,考虑剔除后重估。
实务做法:信号触发后不自动改模型,而是触发人工归因(第 15 篇)------因为趋势断裂和促销脉冲在数据上长得几乎一样,机器分不清,人能。
读者问答
Q1:β 和 α 能取一样吗? 可以但通常不该。经验上 β < α:水平该跟得快(信号强),坡度该估得慢(噪声大)。常见组合 α=0.30.5、β=0.050.2。β 太大时坡度会跟着噪声跳舞,外推立刻发散。
Q2:Holt 能处理季节吗? 不能。它的外推是一条(阻尼)直线加常数,周季节、年季节都看不见。日销数据上这致命------所以有第 7 篇。
Q3:初始坡度 b(1) = y(2) − y(1) 太躁,有更好做法吗? 有:用前 m 期的回归斜率,或 (y(m) − y(1)) ÷ (m−1)。手算本例:(158−120)÷7 = 5.43,比 12 稳得多。初始化用全局信息,递推用局部信息,是平滑模型的通用哲学。
实操清单
- 上线 Holt 前先跑 SES 对照:若误差符号从「全正」变「正负交替」,说明坡度装对了。
- 用全样本回归斜率校验在线 b(t),偏差 > 30% 时检查实现。
- h ≥ 4 一律加阻尼;φ 按步长查表,不拍脑袋。
- 三个断裂信号做成每日自动检测,触发后走人工归因而非自动改模。
- β 初始化扫描网格 {0.01, 0.05, 0.1, 0.2, 0.3},在滚动回测上选。
带走三句话:误差全为正先怀疑结构(没坡度)而非 α;Holt 手算顺序是先报 ŷ=l+φb、再更新 l、最后更新 b,β 让坡度慢而稳;h≥4 必加阻尼,φ÷(1−φ) 是坡度的总预算。
下一篇:最后一块积木是季节。三个状态量一起转的 Holt-Winters,我把初始化、逐期更新、和外推全部手算给你看。