小林在城西开了家“晨光咖啡馆”,每天打烊后都要盘算:明天该进多少牛奶、多少咖啡豆?进少了,遇到周末人流高峰只能对客人说“抱歉,卖完了”;进多了,隔夜的可颂只能扔掉。他手上有三本小账本:一本记“基础销量”,工作日大约 300 杯;一本记“增长趋势”,开业半年来每月都在缓慢上涨;还有一本记“季节节奏”,周末比平日多三成,暑假冰美式销量翻倍。可惜这三本账各记各的,真正预测时常常打架。ETS 指数平滑状态空间模型,正是帮小林把三本账装进同一个“总账本系统”:水平、趋势、季节三个组件在同一套状态方程里协作,并根据每天的预测误差自动修正自己。这套从 1950 年代指数平滑进化而来的方法论,如今是时间序列预测最经典的基石。
掌握 ETS,你就提前拿到了业务预测中最常用、最可解释的模型钥匙:无论零售备货、云资源容量还是客服排班,都能快速给出带置信区间的预测,是时序分析岗位的必备基本功。
目录
可视化演示
展示ETS模型将时序分解为误差-趋势-季节三组件的过程,不同平滑参数对预测的影响,以及基于AIC准则的模型变体选择。
本节配有交互动效(进入视口后自动加载,约 3KB)。
ETS时序分解 OBS原始序列分解为LVL水平+TRD趋势+SEA季节 三组件独立可视化 y_t=l_t+b_t+s_t+e_t 状态空间框架下组件叠加
模型总览:三本账合成总账本
小林在城西经营“晨光咖啡馆”,打烊后总要做一件事:翻开三本沾着咖啡渍的账本。第一本记“今天的基础销量”,他称它为“水平”;第二本记“开业以来每月涨了多少”,是“趋势”;第三本记“周末和暑假的规律波动”,是“季节”。过去他用三套公式各自算数,结果周末+暑假+新店红利叠加时,三本账谁也说不清明天该备多少货。
ETS 指数平滑状态空间模型的全部智慧,就在于把这“三本账”合并成一个可以互相咬合的“总账本系统”。在这个系统里,每个组件都是一个“状态”:水平 ℓ_t、趋势 b_t、季节 s_t。每个时刻,观测值 y_t 由当前状态加上随机扰动生成,而状态又根据上一轮的预测偏差(也就是“误差”)自我修正。三个组件共享同一条误差信息,像三个合伙人因为同一个客人的反馈同时调整自己的记录。
以最简单的带趋势模型 ETS(A,A,N) 为例(A 表示加法误差,A 表示加法趋势,N 表示没有季节),它的总账本由三条方程构成:一条“观测方程”负责把状态变成明天的预测值,两条“状态方程”负责在打烊后根据误差更新水平和趋势。
周一小林发现实际卖出 350 杯,而账本预测是 320 杯,多出的 30 杯就是“误差”。他不会把整个账本推翻,而是按 α=0.3 的比例把水平调高 9 杯,再按 β=0.1 的比例调一调趋势。这就是“指数平滑”:用一个 0 到 1 的小数,把新信息柔柔地揉进旧账本,而不是推倒重来。账本就这样一天天变得更加贴合这家店的真实脾性。
- 观测方程明天的预测值等于上一期的水平加上趋势,再叠加一个随机误差。
- 水平更新把误差 ε_t 的 α 比例揉进水平状态,α 越大对新信息越敏感。
- 趋势更新把误差的 β 比例揉进趋势状态,让斜率也跟着现实慢慢调整。
误差组件:固定 30 杯,还是 10%
同样是差了 30 杯,社区小店和商场旗舰店的反应完全不同。对日销 100 杯的小店,这是个不小的风波;对日销 10000 杯的旗舰店,连零头都算不上。误差组件要回答的,正是“这个偏差是固定大小,还是按销量比例放大”。
加法误差(A)假设序列的随机波动幅度是绝对固定的,无论水平是高是低,噪声都像“±5 杯”这样恒定;乘法误差(M)则假设波动与当前水平成正比,水平越高,噪声的绝对幅度越大,像“±5%“那样按比例浮动。选错误差类型,等于把”小店的 30 杯偏差“和”旗舰店的 30 杯偏差”当成同一件事,预测自然失真。
数学上,加法误差写作“观测值 = 状态和 + 误差”,乘法误差写作“观测值 = 状态和 × (1 + 误差)”。后者相当于把误差放大或缩小到与当前水平匹配的尺度。
回到咖啡店:社区店销量稳定在 100 杯上下,波动就是“±5 杯”这个固定数值,用加法误差;连锁品牌在扩张期日销从 500 涨到 5000,波动随规模放大,用乘法误差。小林如果只经营一家小店,加法模型就足够诚实;只有当他开了十家分店、销量量级不断跃迁时,乘法模型才真正派上用场。
- 加法误差误差项 ε_t 以绝对量的形式直接加到状态和上,波动幅度不随水平变化。
- 乘法误差误差项先与状态和相加成 1+ε_t,再整体相乘,水平越高误差的绝对幅度越大。
趋势组件:给趋势装个阻尼器
小林刚开业那阵子,销量几乎每月涨 5%,他一度以为会永远涨下去。直到半年后增长慢了下来——新店的影响力总会饱和。如果硬按“每月 5%”直线外推十年,账本会算出“每天卖出百万杯咖啡”的笑话。趋势组件里的“阻尼”就是为这个而生的刹车片。
ETS 的趋势有三种状态:N 表示“没有趋势”,适合平稳序列;A 表示“加法趋势”,适合稳定线性增长;Ad 表示“阻尼加法趋势”,在加法趋势基础上加一个阻尼系数 φ。φ 越接近 1,刹车越轻,趋势几乎按原样延续;φ 越接近 0,趋势消失得越快,预测很快回归一条水平线。
阻尼趋势把原来的趋势更新方程 b_t = b_{t-1} + βε_t 改成了下面这个带“衰减因子”的形式:
小林把阻尼系数调到 φ=0.92,三个月后的预测不再是笔直的斜线,而是一条渐渐趋缓的曲线——像洒水车的水柱,初速再猛,也会在重力的牵引下慢慢弯向地面。他意识到,承认“增长有尽头”并不是悲观,而是让账本更接近真实世界的常识。
- 阻尼系数每一步趋势都被 φ 压缩一次,φ∈(0,1) 使趋势无法无限上涨。
- 长期收敛外推 h 步后趋势贡献约为 φ^h b_T,随 h 增大逐渐趋于 0。
- 误差修正β ε_t 项保留了实时纠偏能力,让阻尼趋势不会变成僵硬的直线。
季节组件:记住十二个月前的同一天
咖啡店最明显的规律不是趋势,而是“节奏”:工作日傍晚卖得飞快,周末上午排队到门口,暑假冰饮销量直接翻番。这些以固定周期重复的起伏,就是季节组件要记的账。小林把过去的日历翻出来,发现每年的七月初和十二月底,总有一些日子特别“能打”。
ETS 的季节同样分 N/A/M。加法季节认为每个周期的“加成量”固定,比如暑假每天多卖 50 杯;乘法季节认为“加成比例”固定,比如暑假每天多卖 20%。当水平本身在涨时,乘法季节的绝对波幅也会跟着放大,而加法季节始终保持同一个绝对数值。
以加法季节为例,观测方程需要把“上一年同期的季节账本”搬过来用:
小林把周期设为 m=12,模型会自动记住“去年七月的加成”。他发现加法季节就够用——毕竟店里的销量波动不是“翻倍级”的变化,还没上升到需要乘法季节的程度。季节组件让账本第一次拥有了“日历感”:它知道下个月是暑假,而不是把每天都当成平凡的工作日。
- 含季节的观测方程预测值要叠加 12 个月前的季节状态 s_{t-m},才能重现“去年七月的加成”。
- 季节更新用误差的 γ 比例刷新季节状态,让模型记住最新的周期规律。
组合命名:三字母配方代码
三个组件各有选项,就像咖啡店有“糖浆、奶泡、温度”三个可调旋钮:误差 2 种(A/M)× 趋势 3 种(N/A/Ad)× 季节 3 种(N/A/M),排列组合出 30 种模型。ETS 的命名就是给每种配方编一个三字母代码:ETS(误差,趋势,季节)。
读码规则是“对号入座”:第一个字母管误差,第二个管趋势,第三个管季节。Ad 是两个字符,代表“阻尼加法趋势”。比如 ETS(A,A,d,N) 表示加法误差+阻尼趋势+无季节;ETS(A,A,N) 则表示普通加法趋势、无季节。看懂代码,就能立刻说出这个模型脑子里装着哪些组件。
以 ETS(A,Ad,M) 为例,观测值 = (水平 + 阻尼趋势) × 季节指数 + 加性噪声,把三个组件的写法合并在一起:
30 种配方里并没有“哪个一定最好”,就像没有“哪种拉花一定最好喝”。ETS 要做的是让数据说话——用评分卡从 30 个候选里挑出最适合小林咖啡馆的那一个。命名这件事看似只是记代码,实际上是在强迫你思考:这家店的生意到底有没有趋势、有没有季节、波动是固定还是成比例。
- 括号内求和水平与阻尼趋势相加,构成非季节部分的基础值。
- 季节倍率s_{t-m} 是乘法季节指数,直接乘在基础值外面放大或缩小。
- 外层误差ε_t 以加法形式落在最外层,表示随机波动。
模型选择:AIC 评分卡
30 种模型,到底选哪个?小林的做法是请“顾客”投票打分:既要预测得准,又不能为了准而把食谱改得无比复杂。统计学家给出的评分卡叫 AIC(赤池信息准则),它给每个候选模型打一个综合分,分越低越值得录用。
AIC 由两项构成:第一项是拟合优度,用对数似然衡量模型解释数据的程度——模型越能解释历史销量,这一项越漂亮;第二项是复杂度惩罚,每多一个参数就扣一分——参数越多,越要拿出额外的解释力来“报销”这笔开销。两者相加,防止模型为了讨好数据而疯狂堆参数。
选择流程并不复杂:对 30 种组合逐一估计参数、算出各自的 AIC,然后在同一份数据上比较,取 AIC 最小的那个。它不关心哪个模型听起来高级,只关心“性价比”。
小林把 30 份“配方”全部跑一遍,每份算出 AIC,最后 AIC 最小的 ETS(A,Ad,A) 胜出。评分卡不会因为某个模型听起来高级就偏袒它——就像顾客不会因为拉花好看就原谅咖啡发酸。AIC 让他从“拍脑袋选模型”变成了“让数据投票”。
- 对数似然项L̂ 是最大似然值,越大拟合越好;取负号后整体变成“越小越好”。
- 复杂度惩罚k 是待估参数个数,每个参数额外贡献 2 分惩罚。
- 择优决策在同一数据集上比较所有候选模型的 AIC,取最小值对应的组合。
参数优化:调配方比例
选定配方后,还要定“用量”:平滑参数 α/β/γ 决定“新误差按多大比例揉进旧账本”,初始状态 ℓ₀、b₀ 以及季节初始值则决定账本从哪天开始记。这些参数就像是配方里的“糖浆几泵、肉桂几克”,直接决定成品风味。
估计参数的标准做法是极大似然:找到一组参数,使得“按这套参数生成我们看到的销量”的概率最大。对加法误差模型来说,这等价于最小化误差平方和(SSE)——误差越小,说明这套账本越贴近现实。由于目标函数通常不是凸函数,业界常用启发式初始化(如取 b₀ = y₂ − y₁)再交给数值优化器搜索。
似然函数在“高斯噪声”假设下的对数形式如下,优化器做的就是让这个值尽可能大(或让它的相反数尽可能小):
小林发现 α=0.3、β=0.05 时,模型对“昨天突然卖爆”的反应最适中——太快会跟着噪声起舞,太慢则跟不上真实变化。这就像调咖啡配方,多一份糖浆少一份肉桂,最终由“试喝分数”说了算。参数优化不是玄学,而是一次有目标、有边界、有数学依据的“调料巡航”。
- 误差平方和项残差平方和 Σ ε_t² 越小,对数似然越大,对应“拟合越好”。
- 方差估计σ² 由残差估计而来,处在分母位置,决定打分的宽严尺度。
- 数值搜索用 L-BFGS 等优化器在 (0,1) 区间内搜索 α/β/γ,并配多个初始点避免局部最优。
预测应用:打烊后的外推
账本系统最值钱的时刻,是打烊之后、明天开店之前。给定最新状态 ℓ_T 和 b_T,模型可以向未来任意步长外推。小林发现,ETS 的预测天然分成两件事:给出一个最可能的数字(点预测),以及给出这个数字“大概晃荡在什么范围”(预测区间)。
对 ETS(A,A,N),h 步后的点预测是当前水平加 h 倍的当前趋势;预测区间则随 h 放宽,因为误差会一步步累积——越远的未来,越像隔着晨雾看人,轮廓越来越模糊。以更简单的 ETS(A,N,N) 为例,预测方差随步长的增长公式清晰展示了这一规律:
第二天早上,小林的手机收到推送:“预计今日 342 杯,95% 区间 [310, 376]”。他按上界多备了货,晚上打烊一看,实际卖出 355 杯——账本没有完全猜中,但它猜中了自己的不确定性,而这份“诚实的区间”正是做生意最需要的东西。ETS 的预测应用,让小林从“凭感觉进货”升级为“带概率的理性决策”。
- 点预测直接复用最新的水平 ℓ_T 与趋势 b_T,h 越大走得越远。
- 方差累积1+(h−1)α² 随 h 增大而增大,说明预测步长越长,不确定性越高。
- 工程实践用滚动窗口回测多个组合,每周重估参数,把表现稳定且 AIC 小的模型上线。
AI 应用场景
连锁咖啡品牌备货与排班
阶段:时间序列建模与业务预测
解决的问题:传统手工按“上周同期 × 系数”备货,既漏掉缓慢趋势又漏掉周季节;几百家门店各自为政,损耗与缺货并存。ETS 能在门店粒度自动拟合水平、趋势与周/月季节,输出分位数预测,让采购单变成“数据说了算”。
具体案例:某连锁咖啡品牌对 300 家门店的每日牛奶用量拟合 ETS(A,Ad,A),按 75% 分位生成次日采购量,损耗率下降 18%,缺货投诉减少三成。
云资源容量规划
阶段:容量规划与成本优化
解决的问题:高峰期扩容靠人工盯监控,要么过度采购浪费预算,要么扩容太慢导致故障。ETS 能捕捉访问量的日/周季节与缓慢增长趋势,提前 7 天给出带区间的容量预测,让扩缩容从“被动救火”变成“主动预判”。
具体案例:某 SaaS 平台用 ETS 预测夜间批处理任务的资源用量,按预测上界自动扩容、按预测下界缩容,月度云成本下降 12%。
客服中心话务量排班
阶段:运营调度与人力优化
解决的问题:话务量有强烈的半小时级与星期级季节,人工排班要么人手不够、要么大量闲置。ETS 用乘法季节模型 ETS(M,A,M) 分时段预测话务曲线,与排班系统联动,让每个班次的人数贴合预测区间。
具体案例:某银行客服中心用 ETS 预测各时段话务量,按 85% 分位排班,接通率提升 9%,人力成本下降 6%。
Python 演示
import numpy as npfrom scipy.optimize import minimize def ets_aan_fit(y, max_iter=200): """ETS(A,A,N) 状态空间拟合, 返回最优平滑参数与初始状态.""" y = np.asarray(y, dtype=float) T = len(y) l0 = y[0] b0 = y[1] - y[0] if T > 1 else 0.0 def nll(params): alpha, beta = params if not (0.0 < alpha < 1.0 and 0.0 < beta < 1.0): return 1e9 l, b = l0, b0 sse = 0.0 for t in range(T): err = y[t] - (l + b) l += b + alpha * err b += beta * err sse += err * err sigma2 = sse / T if sigma2 <= 0.0: return 1e9 return T * np.log(sigma2) res = minimize(nll, [0.3, 0.1], method="L-BFGS-B", bounds=[(0, 1), (0, 1)], options={"maxiter": max_iter}) return res.x[0], res.x[1], l0, b0, res.fun def ets_aan_forecast(y, h=10): alpha, beta, l0, b0, _ = ets_aan_fit(y) l, b = l0, b0 T = len(y) fitted = np.empty(T) for t in range(T): fitted[t] = l + b err = y[t] - fitted[t] l += b + alpha * err b += beta * err fcst = np.array([l + (i + 1) * b for i in range(h)]) return fitted, fcst, alpha, beta if __name__ == "__main__": rng = np.random.default_rng(42) t = np.arange(60) y = 100 + 2.0 * t + rng.normal(0, 5, 60) fitted, fcst, alpha, beta = ets_aan_forecast(y, h=12) print("alpha=%.3f beta=%.3f" % (alpha, beta)) print("前5个拟合值:", np.round(fitted[:5], 2)) print("未来12步预测:", np.round(fcst, 2))
def nll(params):定义负对数似然目标函数,参数越不合理返回值越大,引导优化器远离非法区域。err = y[t] - (l + b)观测方程计算当前误差 ε_t,即“实际销量减预测销量”。l += b + alpha * err水平状态更新:把误差的 α 比例揉进水平,对应公式 ℓ_t = ℓ_{t-1} + b_{t-1} + αε_t。b += beta * err趋势状态更新:把误差的 β 比例揉进斜率,对应公式 b_t = b_{t-1} + βε_t。res = minimize(nll, [0.3, 0.1], method="L-BFGS-B",用 L-BFGS-B 在 (0,1) 区间内搜索最优 α 与 β,边界保证了平滑参数始终合法。fcst = np.array([l + (i + 1) * b for i in range(h)])点预测公式 ŷ_{T+h} = ℓ_T + h·b_T 的向量化实现。
常见误区
误区ETS 不就是把过去几天的销量求个加权平均嘛,跟移动平均没什么本质区别,换了个唬人的名字而已。
正解移动平均是静态权重,权重分配完就不再变化;ETS 是状态空间模型,水平、趋势、季节都是随每个新误差动态更新的状态变量,并配有显式的观测方程与状态方程。比喻:移动平均像一张印死的固定配方,ETS 像会根据顾客反馈不断微调火候的厨子。
为何常见:因为两者都涉及“加权历史数据”,小白只看表面权重,没看到状态更新的闭环机制才是 ETS 的灵魂。
误区乘法误差、乘法季节听起来更复杂,肯定比加法模型高级,直接选乘法准没错。
正解加乘之分不是精度高低,而是对“波动形态”的假设不同:加法适合波幅固定,乘法适合波幅随水平成比例。给销量稳定的店硬套乘法模型,会在高销量期放大噪声、压低销量期收缩波动,预测区间反而离谱。
为何常见:“复杂=更高级”的直觉,加上许多教材用乘法处理波动大的数据,容易让人误以为乘法是加法的升级版。
误区销量一直在涨,把趋势原样外推到三年后,预测数字越大老板越开心,何必加什么阻尼。
正解未阻尼的加法趋势长期外推会无限增长,与大多数业务的饱和规律相悖;阻尼趋势用 φ∈(0,1) 把长期增长率逐步压向 0,中远期预测明显更稳健。比喻:赛车直线加速很爽,但弯道不踩刹车就会冲出赛道。
为何常见:人们习惯用近期直线斜率外推远期,忽略了增长总有上限这一基本商业常识。
误区反正有优化器,初始参数随便设一设都会收敛到同一个最优解,没必要讲究。
正解对数似然函数通常非凸,L-BFGS 等局部优化器对初值敏感;业界常用前几期观测做启发式初始化(如 b₀ = y₂ − y₁),再配合多起点搜索降低陷入局部最优的风险。
为何常见:看到“自动优化”就以为有全局最优保证,忽略了数值优化本身的局部性与参数空间的结构。
面试题
Q1. ETS 中的三个字母 E/T/S 分别代表什么组件?
- A.误差、趋势、季节← 正确答案
- B.误差、时间、尺度
- C.指数、趋势、季节
- D.误差、趋势、标准
答案:A。ETS 命名源自 Error、Trend、Seasonal 三组件。B 把 T 误读成“时间”、D 把 S 误读成“标准”,C 把 E 误当成 Exponential,只有 A 与三组件定义完全对上。
Q2. ETS(A,A,N) 中的 N 表示哪一个组件被省略?
- A.误差组件被省略不参与建模
- B.季节组件被省略不参与建模← 正确答案
- C.趋势组件被省略不参与建模
- D.参数组件被省略不参与建模
答案:B。ETS 三个字母按顺序对应误差、趋势、季节,N 是 None 的缩写,表示该位置组件不参与建模。第三个位置是季节,因此 B 正确;A、C 把字母位置搞混,D 中“参数组件”根本不存在。
Q3. 乘法误差 (M) 更适用于什么形态的序列?
- A.波动幅度恒定的那类序列
- B.波动随水平成比例变化的序列← 正确答案
- C.完全没有任何随机波动的序列
- D.只有长期单调趋势的序列
答案:B。乘法误差假设波动幅度与当前水平成比例,像“±5% 的小费”;A 描述的是加法误差的适用场景,C 是理想无噪声场景,D 只提到趋势未涉及波动形态,均不符合乘法误差的核心假设。
Q4. 阻尼趋势中阻尼参数 φ 的取值范围及其效果?
- A.φ=1 趋势永远不衰减
- B.φ>1 会让趋势爆炸放大
- C.0<φ<1 趋势逐步收敛← 正确答案
- D.φ=0 趋势完全消失
答案:C。阻尼趋势方程 b_t = φb_{t-1} + βε_t 要求 0<φ<1,趋势每步乘 φ 后逐步衰减、长期预测趋于平缓。A 中 φ=1 是普通加法趋势,B 中 φ>1 会发散,D 中 φ=0 是瞬间无趋势而非逐步收敛。
Q5. 选择 ETS 组合模型时,AIC 的使用原则是?
- A.AIC 越大代表拟合越好
- B.AIC 越小且兼顾复杂度← 正确答案
- C.只比较拟合优度 R²
- D.随便挑个常用组合
答案:B。AIC = −2ln(L̂) + 2k,既奖励拟合似然又用 2k 惩罚参数数量,在同一数据集上取 AIC 最小者。A 方向反了,C 只看 R² 会忽略过拟合,D 属于拍脑袋,均不符合模型选择原则。
Q6. 模型 ETS(A,Ad,M) 表示的是哪种组合?
- A.加法误差加法趋势乘法季节
- B.加法误差阻尼趋势乘法季节← 正确答案
- C.乘法误差加法趋势阻尼季节
- D.加法误差阻尼趋势加法季节
答案:B。三字母按误差、趋势、季节排列:首字母 A 为加法误差,中间 Ad 为阻尼加法趋势,末字母 M 为乘法季节。A 漏掉阻尼,C 字母顺序错乱,D 把季节误写成加法,均不正确。
Q7. 与普通加权移动平均相比,ETS 的核心优势是什么?
- A.能显式建模趋势与季节← 正确答案
- B.计算复杂度一定更低
- C.不需要估计任何参数
- D.只能处理平稳数据
答案:A。ETS 用状态空间方程显式刻画水平、趋势、季节,并通过误差修正持续更新状态;移动平均只是静态权重,无法外推趋势与季节。B 不一定成立,C 与事实相反,D 描述的是移动平均的常见局限而非 ETS 优势。
Q8. ETS 的三组件包含以下哪些?
- A.误差组件← 正确答案
- B.趋势组件← 正确答案
- C.季节组件← 正确答案
- D.回归组件
答案:ABC。E-T-S 三个字母分别对应误差、趋势、季节三组件,缺一不可。回归是引入外部变量的机制,不属于 ETS 组件体系,因此 D 不选。
Q9. 关于加法与乘法组件的选择,下列说法正确的是?
- A.加法误差适合固定波动← 正确答案
- B.乘法误差适合比例波动← 正确答案
- C.加法季节适合波幅恒定← 正确答案
- D.乘法季节适合波动成比例← 正确答案
答案:ABCD。加法的前提是波动绝对幅度稳定,乘法假设波幅随水平成比例变化。四条描述分别对应误差与季节两种组件在加乘假设下的正确选择,全部成立。
Q10. 关于 AIC 与模型参数的关系,下列说法正确的是?
- A.AIC 用 2k 惩罚参数数量← 正确答案
- B.参数越多 AIC 必然越小
- C.复杂模型需要更大似然补偿← 正确答案
- D.只在同一数据上做比较← 正确答案
答案:ACD。AIC = −2ln(L̂) + 2k,k 是参数个数,参数越多惩罚越大,因此 B 错误。复杂模型必须用更高的拟合似然来“报销”惩罚才可能胜出;比较 AIC 的前提是同一数据集,跨数据集比较没有意义。