R语言用LOESS(局部加权回归)季节趋势分解(STL)进行时间序列异常检测

这篇文章描述了一种对涉及季节性和趋势成分的时间序列的中点进行建模的方法。

由Kaizong Ye,Coin Ge撰写

我们将对一种叫做STL的算法进行研究,STL是 “使用_LOESS_(局部加权_回归_)的季节-趋势分解 “的缩写,以及如何将其应用于异常检测。


其基本思想是,如果你有一个有规律的时间序列,你可以通过STL算法运行该序列,并分离出规律的模式。剩下的是 “不规则的”,而异常检测相当于判定不规则性是否足够大。

例子:航空乘客,1949-1960

让我们在数据集上运行该算法,该数据集给出了1949-1960年期间每月的航空公司乘客数量。

×

1. 时间序列的成分

对于一个时间序列{y(t)},假设它是加性模型(an additive decomposition),则可以写成 

               y(t)=S(t)+T(t)+R(t),

其中S(t)、T(t)、R(t)分别是周期成分(seasonal component)、趋势成分(trend-cycle component)、残差成分(remainder component)。

类似地,一个乘性模型可以写成

               y(t)=S(t)×T(t)×R(t),

对于乘性模型,可以取对数(当然是有意义的前提下),将其转化为加性模型。


2. 经典分解法(Classical decomposition)

经典的时间序列分解算法,起于1920年,直到1950年之前仍在广泛使用。经典算法步骤相对简单,同时也是很多其他分解算法的基础。经典分解法是假设周期性成分在每个周期内都是相同的(【例如每年的月周期成分都相同】)。

(1)加性模型分解算法

Step1:如果m为偶数,则用2-m-MA【所谓2-m-MA,意思是对序列先进行4-MA,然后对移动平均之后的序列,计算其2-MA。的这样就实现了某种对称性。详情请参考原书6.2节:Moving averages】来计算序列的趋势成分T(t);如果m为奇数,则用m-MA来计算序列的趋势成分T(t)。

Step2:计算去掉趋势的时间序列 D(t)=y(t)-T(t)。

Step3:为了估计周期成分,只需要对同一周期的数据取均值即可。例如对于月度数据,要计算三月的周期性成分,对所有D(t)中的三月份的数据进行求均值即可。周期性成分会被调整(加上一个偏置)以使得它们的和为0。对周期性成分复制到D(t)的长度,即得到D(t)的所有周期性成分,记作S(t)。

Step4:残差成分R(t)=y(t)-T(t)-S(t)。

(2)乘性模型分解算法

乘性模型和加性模型的思想很类似,区别在于把上述加性模型的Step2改成D(t)=y(t)/T(t),Step4改成 R(t)=y(t)/(T(t)*S(t))。


首先,这是未经修改的时间序列。

plot(y)

这里显然有一个规律性的模式,但是在这个序列中没有任何明显的下降,无法在异常检测中显示出来。所以我们将设置一个。


课程

R语言数据分析挖掘必知必会

从数据获取和清理开始,有目的的进行探索性分析与可视化。让数据从生涩的资料,摇身成为有温度的故事。

立即参加

y\[40\] = 150

跌幅足够大,我们希望异常检测能发现它,但又不至于大到你只看一眼图就会发现。现在让我们通过STL检查它。

plot(fit)

首先,我不是在y上运行STL,而是在log(y)上。

该算法将序列分解为三个部分:季节性、趋势和剩余成分。季节性是周期性成分,趋势是一般的上升/下降,剩余成分是剩下的趋势成分。季节性和趋势共同构成了序列的 “常规 “部分,因此是我们在异常检测过程中要剔除的部分。

剩余部分基本上是原始序列的正常化版本,所以这是我们监测异常情况的部分。剩余序列的下降是很明显的。我们在1952年初设置的异常下降很可能算在内。

我们还可以调整每一时期的观测值数量,负责分离季节性和趋势成分的平滑方法,拟合模型的 “稳健性”(即对异常值不敏感)等等。这些参数中的大多数需要对基础算法的工作原理有一定的了解。

下面是一些显示实际数据与阈值的代码。

data <- merge(df, ba, by.x='x')
ggplot(data) +  geom(aes(x=x, ymin=ymin, ymax=ymax))

再次,聪明如你可能会注意到通过exp()进行的逆变换。我们现在讨论这个问题。

为什么要进行对数和逆变换?

并非所有的分解都涉及对数变换,但这个分解却涉及。其原因与分解的性质有关。STL的分解总是加法的。

y = s + t + r

时间序列分解和异常检测方法应用案例

阅读文章


但对于某些时间序列,乘法分解更适合。

y = str

这种情况发生在销售数据中,季节性成分的振幅随着趋势的增加而增加。这实际上是乘法序列的标志,航空旅客序列也表现出这种模式。


随时关注您喜欢的主题


为了处理这个问题,我们对原始值进行对数转换,这使我们进入加法领域,在那里我们可以进行STL分解。当我们完成后,我们再进行逆变换,回到原始序列。

多重季节性的情况如何?

一些时间序列有一个以上的季节性。例如,在酒店预订时间序列有三个季节性:每日、每周和每年。

虽然有一些程序可以生成具有多个季节性成分的分解,但STL并没有这样做。最高频率的季节性被作为季节性成分,而任何较低频率的季节性都被吸收到趋势中。


可下载资源

关于作者

Kaizong Ye拓端研究室(TRL)的研究员。

本文借鉴了作者最近为《R语言数据分析挖掘必知必会 》课堂做的准备。

​非常感谢您阅读本文,如需帮助请联系我们!

 
QQ在线咨询
售前咨询热线
15121130882
售后咨询热线
0571-63341498

关注有关新文章的微信公众号


永远不要错过任何见解。当新文章发表时,我们会通过微信公众号向您推送。

技术干货

最新洞察

This will close in 0 seconds