本节摘要:当季节性或残差的幅度随时间序列水平变化时,加法模型会失真。本节用一段航空乘客数据演示"乘法季节性"现象,并给出从业务直觉到模型选择的决策表。
阅读完本节,你应当能够:
np.log 变换把乘法模型转化为加法模型。本节回到"结构"问题:四类成分之间到底应该是相加还是相乘?读完后你掌握"对数变换把乘法变加法"这一招,对 80% 业务量类数据都有效。
加法模型假设四类成分独立相加:
y(t) = T(t) + S(t) + C(t) + ε(t)
乘法模型假设相乘:
y(t) = T(t) × S(t) × C(t) × ε(t)
实际业务里"完全独立相加"和"完全相乘"都是理想化。常见的是混合:趋势独立、季节性随水平缩放、周期独立。乘法季节性是最常被讨论的混合情况:
y(t) = T(t) + T(t) × S(t) + ε(t) = T(t) × (1 + S(t)) + ε(t)
也就是说季节性的"幅度"和当前水平 T(t) 成正比。
国际航空乘客数据集(Box & Jenkins 经典案例)几乎被所有教科书用来演示乘法季节性。我们用 statsmodels 自带的版本做演示:
import matplotlib.pyplot as plt from statsmodels.datasets import airline # 加载航空乘客数据(144 个月,1949–1960) data = airline.load_pandas().data data["Month"] = pd.to_datetime(data["Month"]) data = data.set_index("Month") y = data["AirPassengers"] # 单位:千人 fig, axes = plt.subplots(2, 1, figsize=(10, 6)) axes[0].plot(y.index, y.values) axes[0].set_title("原始序列:水平 + 季节性幅度都在增长") axes[1].plot(y.index, y.values / y.rolling(12).mean()) # 季节性幅度 / 趋势 axes[1].set_title("季节性幅度(除以 12 月滚动均值)") plt.tight_layout()
第一张图:年峰值(7、8 月)和谷值(11、2 月)之间的差距随着年份增长——1950 年的峰谷差大约 50 千人,1960 年扩大到 250 千人。这是乘法季节性的典型视觉特征。
第二张图:把每个月的值除以"近 12 个月均值"消除水平影响。比率序列的振幅如果近似稳定在 ±20%,说明季节性幅度与水平成正比 → 乘法模型;如果比率序列的振幅随时间缩小 → 加法模型更合适。
| 信号 | 选加法 | 选乘法 |
|---|---|---|
| 季节性幅度 | 不随水平变化 | 随水平放大或缩小 |
| 业务直觉 | "季节性是固定偏移量" | "季节性是固定比例" |
| 典型场景 | 温度、产能、库存量 | 销售额、用户数、流量 |
| 残差 | 近似同方差 | 残差随水平放大 |
经验法则:业务量类指标(销量、用户、流量)通常是乘法;物理量类指标(温度、压力、占用率)通常是加法。但也有反例——比如某行业产能利用率可能既是乘法(百分比随总量放大)又近似加法(百分比天然在 0–100 之间),需要结合视觉判断。
工程上有个一劳永逸的技巧:对原始序列取对数,乘法季节性就变成加法季节性。数学上:
log(y) = log(T) + log(S) + log(ε)
对航空乘客序列:
import numpy as np log_y = np.log(y) # 现在 log_y 的季节性幅度是常数(与水平无关),可以用加法分解
对数变换后,加法模型在变换后的空间里工作;预测时再 np.exp 反变换回来。这是为什么 statsmodels 的指数平滑族、Holt-Winters 都默认支持"乘法季节性"参数——本质就是内部对数化。
⚠️ 常见坑:对数变换对零值和负值无效。如果你的序列有 0 值,需要先
log1p(y)或对零值做特殊处理(销量为 0 的日子,可能本来就该被剔除或单独标记)。
一个简洁的决策流程:
选错了模型会有什么后果?
最稳妥的做法是先对数变换,让乘法变加法;对数空间下用加法模型训练、预测,再反变换回原尺度。这一招对 80% 的业务量类数据都有效。
log(y) 把乘法变加法,statsmodels 的乘法季节性模型内部就在做这件事。判断用加法还是乘法分解,最快的方法是看"季节性波动的振幅是否随趋势同步放大"。
Y = T + S + C + RY = T * S * C * R(取对数后等价于加法)99% 的业务数据,加法模型就够用。乘法模型在两类场景下必用:一是销量随价格指数同比放大(电商旺季 vs 淡季),二是物理量(如光强、辐射)随基线变化。盲目用乘法模型会导致对数变换后出现负值(如果原序列有 0),得不偿失。