季节 - 趋势分解(STL)方法详解
在分析时间序列数据时,我们经常需要理解数据中隐藏的规律。比如零售商想知道销售额的增长是真实的业务增长还是仅仅是季节性因素,气候学家需要从温度数据中分离出长期变暖趋势和正常的季节变化,这些都需要一种强大的分解方法。STL(Seasonal and Trend decomposition using Loess)正是为此而生的统计方法,它能够将复杂的时间序列数据优雅地分解为三个易于理解的组成部分:趋势、季节性和余项。
数学原理与核心思想
STL 的核心思想非常直观:任何时间序列都可以表示为三个加法组成部分的和。用数学公式表达就是:
$$Y_\nu = T_\nu + S_\nu + R_\nu$$
其中 $Y_\nu$ 代表在时间 $\nu$ 的观测值,$T_\nu$ 是趋势分量,$S_\nu$ 是季节分量,$R_\nu$ 是余项分量。
STL 方法的独特之处在于它使用了 LOESS (Locally Weighted Scatterplot Smoothing,局部加权散点图平滑)这一强大的非参数回归技术。LOESS 的核心理念是'近朱者赤'——在估计某一点的值时,距离越近的点权重越大,距离越远的点权重越小。这种局部性使得 STL 能够灵活地适应数据的变化,而不像传统方法那样假设整个序列遵循同一个固定模式。
具体来说,LOESS 使用一个优雅的权重函数,称为 三次立方权重函数 :
$$W(u) = \begin{cases} (1 - |u|^3)^3 & \text{当 } |u| \leq 1 \ 0 & \text{否则} \end{cases}$$
这个函数的妙处在于它在 $u=0$ 时权重为 1,随着距离增加权重平滑下降,到达边界时恰好为 0,避免了突兀的截断。对于每个待估计的点 $x$,我们首先找到 $q$ 个最近的邻居点($q$ 是平滑参数),然后计算每个邻居点的权重:
$$v_i = W\left(\frac{|x_i - x|}{\lambda_q(x)}\right)$$
其中 $\lambda_q(x)$ 是到第 $q$ 个最远邻居的距离。接下来,我们用这些权重进行局部多项式拟合,通常是线性或二次多项式,通过最小化加权误差平方和来估计该点的值。
算法的精妙设计:双循环结构
STL 算法采用了一个巧妙的双循环结构,这种设计既保证了算法的稳健性,又提供了足够的灵活性。
内循环:交替估计的艺术
内循环是 STL 的核心,它通过反复迭代来交替估计季节分量和趋势分量。这个过程就像是两位艺术家轮流作画,每次都在对方的基础上进行改进,直到作品趋于完美。
第一步:去趋势。我们从原始序列中减去当前的趋势估计 $T_\nu^{(k)}$,得到去趋势序列。这一步的目的是让季节模式更加清晰,不受趋势干扰。
第二步:循环子序列平滑。这是 STL 的独特创新。假设我们分析的是月度数据,那么我们把所有的一月份数据放在一起,所有的二月份数据放在一起,以此类推。对每个这样的子序列应用 LOESS 平滑,平滑参数为 $n_s$(季节窗口)。这种方法允许季节模式随时间缓慢变化,比如夏季销售高峰可能逐年提前或推迟。
第三步:低通滤波。对上一步得到的结果进行低通滤波,目的是去除季节分量中可能包含的趋势成分。这通过连续两次长度为 3 的移动平均,再加上一次 LOESS 平滑来实现。
第四步:计算季节分量。将循环子序列平滑的结果减去低通滤波的结果,得到纯净的季节分量:
$$S_\nu^{(k+1)} = C_\nu^{(k+1)} - L_\nu^{(k+1)}$$
第五步:趋势平滑。从原始序列中减去新的季节分量,对得到的序列进行 LOESS 平滑,平滑参数为 $n_t$(趋势窗口),得到新的趋势估计。
这个过程通常重复 2-3 次就能收敛,每次迭代都让趋势和季节的估计更加准确。
外循环:稳健性的保证
外循环是 STL 处理异常值的秘密武器。在现实数据中,异常值是不可避免的——可能是测量错误、特殊事件或者真实的极端情况。传统方法往往会被这些异常值严重影响,而 STL 通过外循环巧妙地解决了这个问题。
外循环使用双平方权重函数来计算稳健性权重:
$$\rho_\nu = B\left(\frac{|R_\nu|}{h}\right)$$
其中 $B(u) = (1 - u^2)^2$ 当 $0 \leq u \leq 1$,否则为 0,$h = 6 \times \text{median}(|R_\nu|)$ 是基于余项中位数的尺度参数。
这个设计的精妙之处在于:正常的观测值(余项较小)获得接近 1 的权重,而异常值(余项较大)的权重会被大幅降低甚至降为 0。这样,异常值主要影响余项分量,而不会扭曲趋势和季节的估计。


