时间序列的R语言实现

这部分是用指数平滑法做的时间序列的R语言实现,建议先看看指数平滑算法。

用指数平滑做预测

简单指数平滑(Simple Exponential Smoothing)

对可用加性模型描述的,非周期性的时间序列数据,可用简单指数平滑来做短期的预测。指数平滑是根据平滑常熟α来做的,α取值在0-1的区间上,α越小越接近0,就表示做预测时对近期观测所取的比重较大。

说明:指数平滑算法的原理就是利用历史观测数据对未来做预测,α的取值决定着对近期和远期观测数据所取的权重。详细的可以去了解该算法。

下面是伦敦1813年到1912年的降雨量英尺数的时间序列数据:

由图可以看出,数据随时间的随机波动幅度是大致不变的,所以可以说该时间序列是稳定的。在R中用简单指数平滑做预测,我们可以用HoltWinters()方法,使用时需要设置两个参数beta=FALSE和gamma=FALSE。

说明:HoltWinters有三个类似的参数,alpha,beta,gamma,这三个参数跟上面讲到的简单指数平滑的取值范围一样在0-1之间。可以简单理解alpha是平滑指数,beta是趋势指数,gamma是季节指数。rainseries时间序列没有明显上升或下降的趋势,也没有季节性的变化,所以这里这两个参数取false。

结果alpha很接近0,说明预测中对近期观测数据取值权重较大。结果存储在rainseriesforecasts这个list变量中,预测结果储存在这个list变量的fitted元素中,它的结果可以查看到。

在图中将原始时间序列和新的时间序列对照看:

黑色线是原始数据,红色线是预测数据。检验结果的准确度,可以用SSE(误差项平方和)的值来判断。SSE也是list变量rainseriesforecasts中的一个元素。查看SSE的值如下:

这个预测结果原始数据对比误差项平方和是1828.855。

上面例子中,HoltWinters()方法默认的预测仅覆盖有原始数据的那个时间段,也就是1813年到1912年的降水量的时间序列。用R中的forecast包中的forecast.HoltWinters()方法可以来做这个预测。首先安装forecast包。安装方法很简单就不说了。安装完成后加载forecast包。

上面forecast.HoltWinters()的两个参数,第一个是上一步rainseriesforecasts用默认的HoltWinters()得到的结果,第二个h是你想要预测的期数,为8,所以得到的预测结果是从1912年往后推的8年即1913-1920。预测结果有5列数据,第一列Forecast是预测值,第二列第三列是80%的置信区间的下限和上限,第四列第五列是95%置信区间的下限和上限。这个预测结果用图表展示出来如下:

蓝线是从1913年到1920年的预测值,颜色较深的部分是预测值80%的置信区间,颜色较淡的蓝色是预测值95%的置信区间。对未来数据进行的预测,因为没有同期观测数据,所以没办法用前面讲到的SSE来检测预测误差。

这个例子中样本的预测误差存在forecast.HoltWinters()方法返回的list变量中的residuals(残差)元素中。如果做预测模型不可改良,那预测误差和连续预测结果不相关。也就是说如果预测误差和预测结果间存在相关性,那所用的简单指数平滑模型可以用其他预测方法优化。

R中提供了acf()方法可以查看样本预测误差的相关性图。若要定义我们想要查看的最大滞后期数,可以定义acf()方法中的lag.max参数。

例如,计算滞后期在1-20时的样本预测误差的相关性,如下操作:

从上面的相关性图可以看出来,在滞后期为3时的自相关结果接近意义界限。

说明:

acf()的说明,自相关公式:

k是在acf方法中定义的lag.max的值,伦敦降雨量预测的例子中,k的取值就是1-20的范围内。两条蓝色的虚线是意义界限,acf值在这个界限之间,可以认为相关性接近0,可以忽略,如果超出这个范围就需要另外的判断了。这个是我自己的理解,仅供参考。如果有问题,欢迎指正!

测试在1-20的延迟期中,是否有意义的非零相关值,我们可以用Ljung-Boxt测试。在R中,用Box.test()的方法。Box.test()方法中的lag参数用来定义我们想要查看的最大延迟期。用上面伦敦降雨量的预测误差,作如下操作:

Ljung-Box测试的统计值是17.4,p值是0.6,所以样本预测误差的非零相关的可能很小。再次确认预测模型不可再改进,查看预测误差是不是以均值0和不变方差按正态分布。

要查看预测误差是否有不变方差,可以被预测误差的结果做一个时序图:

从上图可以看出,尽管1820-1830年这前十年的波动幅度相比1840-1850期间的波动幅度要小一些,预测误差的方差在时间上还是大致稳定的。

查看预测误差是否按0正态分布,可以查看预测误差的直方图和以0和相同标准误差呈正态分布的曲线图,两者对比查看。还是同一个例子,需要自己写一个R的方法plotForecastErrors()来实现可实现:

上面是plotForecastErrors()方法代码,行末$符号表示不换行,#开始的行表示是注释。下面使用这个方法:

图上能看出来,预测误差基本上是以0为中心,大致正态分布的,与正态分布曲线相比可能有些向右偏,但右偏量相对小。所以,可以说预测误差是以0为中心呈正态分布的。

Ljung-Box测试的结果表明预测误差的非零自相关的结果很少,它的分布也满足以0为中心呈正态分布。至此,我们可以下结论,简单指数平滑方法足够用来做伦敦降雨量的预测模型,也不需要进一步的改进了。并且,80%和95%的预测区间也是基于上述结论得到,可以说是有效的。

霍特双参数指数平滑(Holt’s Exponential Smoothing)

说明:了解一下霍特双参数指数平滑法,推荐看博文http://blog.csdn.net/cl1143015961/article/details/42098919 在文章中讲到的第三个算法。

霍特指数平滑法,包含两个参数α和β。α平滑常数,β是趋势常数。跟HoltWinters方法的参数一样,这两个参数的取值范围也在0-1间。所以对满足加性模型,存在增加趋势或者递减趋势的非季节性的数据,可以选择用霍特指数平滑法来做短期的预测。

霍特指数平滑法能预估在当前时间点的水平和趋势。下面是一个非季节性的存在增减趋势的时间序列例子。从1866年到1911年每年女性裙子边缘直径的数据:

可以看出女性裙子边缘直径从1866年600左右增大到了1880年的1050,在这之后又降到了1911年的520。

还是用R中的HoltWinters()方法,这里我们需要用到alpha和beta两个参数,所以只需要设置gamma=FALSE就行。给女性裙子边缘直径的变化这个时间序列做预测模型过程如下:

alpha和beta的值分别为0.838和1,都很大,说明时间序列水平和趋势部分的预测值,对近期观测数据所取的权重较大。这个结果从该时间序列随时间的水平和趋势变化都很大,就能很直观看出来。改时间序列预测的误差项平方和SSE结果是16954.18。

查看预测结果时间序列图:

上图可以看出,除了预测结果有很小的滞后外,预测值时间序列和实际值序列很接近。

也可以自己设置初始的水平值和趋势值,HoltWinters()方法中的l.start和b.start这两个参数用来设置初始值。初始水平值一般取第一个时间点的值,初始趋势值则常取第二个值与第一个值的差值。这个例子中,分别是608和9(617-608)。

尝试设置l.start和b.start的值,再对女性裙子边缘直径时间序列做预测,结果如下,与之前的结果有了一些不同。

前面是同期的预测,同样可以用forecast包中的forecast.HoltWinters()方法对未来做预测。女性裙子边缘直径数据是从1866年到1911年的,对此我们可以做从1911年之后的预测。如若想要1912年到1930这19期的预测数据,如下操作:

与之前用HoltWinters()方法做预测结果一样,蓝线是预测值,深色区域是预测结果的80%置信区间,浅色部分是95%的置信区间。

重复前面用相关性函数来看看是否需要优化模型的过程。

在滞后期为5时,预测误差的自相关结果超过了意义界限,所以,这里我们需要进一步的检测。查看Box-Ljung测试的结果,可以看看到,p值为0.4749,这个值很小,样本的预测误差在1-20的滞后期内,存在非零自相关的可能很小。

对简单指数平滑,还需要查看预测误差是不是存在不变方差,并以0为中心呈正态分布。类似的过程,使用之前的plotForecastErrors()方法。

从上面两个图,能看出,预测误差的方差随时间的变化可以认为是大致稳定的,预测误差也基本满足正态分布。所以,结论是,用霍特双指数平滑模型对从1866年到1911年每年女性裙子边缘直径的时间序列做预测是合适的,预测结果经过检验也是有效的。

霍特季节性指数平滑(Holt-Winters Exponential Smoothing)

如果时间序列满足增量模型,存在升降趋势,并且是季节性的数据。这时,可用霍特季节性指数平滑法来做短期预测。

霍特季节性指数平滑法,包含三个参数α、β和γ。α平滑常数,β是趋势常数,γ是季节常数。三个参数的取值范围都是0-1。在R中的实现,还是使用HoltWinters()方法,这一次,它的三个类似参数,我们都需要用到。

使用的时间序列数据是前面取对数后的昆士兰沙滩旅游胜地的某一纪念品店的销售数据。

alpha,beta和gamma的值,分别是0.4134、0、0.956。alpha的值比较小,表明该时间序列的某一时间点的水平预测值,是基于近期观测值和远期观测值。beta为0,表明时间序列趋势部分值不随时间变化而改变的,也就是所有时间点上,趋势的预测值都是初始值。gamma为0.956,这说明季节性部分的预测值,对近期观测值所取得权重很大。

查看预测结果,如下:

从图上,可以看出,霍特季节性指数平滑方法在做这个时间序列的季节性预测时很成功,预测结果与原始数据的11月销售高峰很贴切。

接下来,对未来做预测,还是用forecast包。

下面对预测结果做检验,看预测模型是否需要改进。同样的方法计算相关性和做Ljung-Box检验。过程及结果如下:

样本的预测误差的自相关结果,在1-20的滞后期中,没有超出意义界限。并且Ljung-Box的p值小,说明在1-20的滞后期中,存在非零自相关的可能性很小。

然后检验预测误差是有不变方差,以0为中心呈正态分布。过程结果如下:

可看出,预测误差的方差可认为是随时间稳定的,其分布也符合正态分布。所以这个例子中,使用霍特季节性指数平滑所做的预测结果是有效的。

原文发布于微信公众号 - 大数据挖掘DT数据分析(datadw)

原文发表时间:2015-11-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏拭心的安卓进阶之路

Java 集合深入理解(6):AbstractList

今天心情比天蓝,来学学 AbstractList 吧! ? 什么是 AbstractList ? AbstractList 继承自 AbstractCollec...

19210
来自专栏Java Edge

AbstractList源码解析1 实现的方法2 两种内部迭代器3 两种内部类3 SubList 源码分析4 RandomAccessSubList 源码:AbstractList 作为 Lis

它实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换

462
来自专栏赵俊的Java专栏

从源码上分析 ArrayList

1181
来自专栏xingoo, 一个梦想做发明家的程序员

Spark踩坑——java.lang.AbstractMethodError

百度了一下说是版本不一致导致的。于是重新检查各个jar包,发现spark-sql-kafka的版本是2.2,而spark的版本是2.3,修改spark-sql-...

1210
来自专栏Phoenix的Android之旅

Java 集合 Vector

List有三种实现,ArrayList, LinkedList, Vector, 它们的区别在于, ArrayList是非线程安全的, Vector则是线程安全...

672
来自专栏后端之路

LinkedList源码解读

List中除了ArrayList我们最常用的就是LinkedList了。 LInkedList与ArrayList的最大区别在于元素的插入效率和随机访问效率 ...

19710
来自专栏项勇

笔记68 | 切换fragmengt的replace和add方法笔记

1444
来自专栏刘君君

JDK8的HashMap源码学习笔记

3068
来自专栏ml

朴素贝叶斯分类器(离散型)算法实现(一)

1. 贝叶斯定理:        (1)   P(A^B) = P(A|B)P(B) = P(B|A)P(A)   由(1)得    P(A|B) = P(B|...

3477
来自专栏MelonTeam专栏

ArrayList源码完全分析

导语: 这里分析的ArrayList是使用的JDK1.8里面的类,AndroidSDK里面的ArrayList基本和这个一样。 分析的方式是逐个API进行解析 ...

4519

扫码关注云+社区