0x06 简单的时间序列建模例子

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = (15, 6)

读取数据

将代表日期的列, 作为index, 并根据日期的格式转换为DatetimeIndex格式, 这样在后续的操作中很方便.

data = pd.read_csv("AirPassengers.csv", index_col="Month", date_parser=lambda x: pd.datetime.strptime(x, "%Y-%m"))
data.head()

#Passengers

Month

1949-01-01

112

1949-02-01

118

1949-03-01

132

1949-04-01

129

1949-05-01

121

data.index
DatetimeIndex(['1949-01-01', '1949-02-01', '1949-03-01', '1949-04-01',
               '1949-05-01', '1949-06-01', '1949-07-01', '1949-08-01',
               '1949-09-01', '1949-10-01',
               ...
               '1960-03-01', '1960-04-01', '1960-05-01', '1960-06-01',
               '1960-07-01', '1960-08-01', '1960-09-01', '1960-10-01',
               '1960-11-01', '1960-12-01'],
              dtype='datetime64[ns]', name='Month', length=144, freq=None)

画图分析

png

可以看出两点:

  • 有很强的趋势性, 因此肯定不是平稳序列, 需要进行转换处理, 成为平稳序列

  • 有季节性

检测平稳性

因为后面要多次使用, 所以封装成一个函数

adfuller函数返回6个值, 分别代表:

  • adf : float

    • Test statistic

  • pvalue : float

    • MacKinnon's approximate p-value based on MacKinnon (1994, 2010)

  • usedlag : int

    • Number of lags used

  • nobs : int

    • Number of observations used for the ADF regression and calculation of the critical values

  • critical values : dict

    • Critical values for the test statistic at the 1 %, 5 %, and 10 % levels. Based on MacKinnon (2010)

  • icbest : float

    • The maximized information criterion if autolag is not None.

png

单位根检验的结果是不平稳的, 因此要把这个非平稳序列, 转换成平稳序列

转换为平稳序列

  • 首先通过转换函数, 如loglog函数来转换, 缩小值域中的差距

png
  • 通过移动平均的方法进行平滑, 得到趋势, 然后在原有的序列中移除趋势.

这时因为趋势是造成时间序列不平稳的一个重要因素

png

因为我们使用了时间作为索引, 所以可以直接相减, 而不用人工进行对齐, 从而大大方便了操作.

之后抛弃掉这些为空的时间点. 因此使用这种方法抛弃趋势, 会造成样本的损失, 损失数量与求移动平均时的窗口大小有关.

png

也可以使用带权值的平均方法, 这样就不会造成样本的损失了, 如EWMA等.

png
png

使用EWMA方法得到的序列, 单位根检验得到P值只有0.0057, 小于1%, 因此是平稳的.

  • 使用差分

当然, 差分也会造成样本点的损失, 损失的数量为差分的阶数.

首先进行一阶差分:

png
png

看出, 如果以5%的显著性水平来判断, 此时的序列仍然是不平稳的.

再进行一次差分, 即使用二阶差分, 方法就是对一阶差分得到的序列再次进行差分. 更高阶的差分依次类推.

png
png

现在的效果就非常好了.

  • 分解方法

对时间序列进行分解, 分解成趋势, 季节性, 残差三部分, 剩余的残差部分就是我们需要继续分析建模的.

png
png
png

使用ARIMA模型拟合时间序列

对平稳的时间序列进行拟合.

为了确定模型的p, q参数, 需要观察ACFPACF图.

使用二阶差分得到的平稳的时间序列进行建模.

nlags参数指的是最多计算到滞后多少的相关系数.

如果将acf函数的qstat设为True, 会对每个得到的每个lag对应的acf值进行Ljung-Box检验, 得到其中的Q-Statistic与对应的p值

png

需要注意的是这条虚线, 这是用来判断ARIMA模型的pq参数的工具. 判断的原理为:

我们认为如果相关系数为0, 则不存在相关性. 而相关系数是符合标准正态分布的统计量, 即N(0,1)N(0,1). 对于显著性水平α=0.05\alpha=0.05, 对应的zα/2=1.96z_{\alpha/2}=1.96.

这是考虑其中某一个相关系数, 如果考虑多个相关系数, 即考虑每个lag对应的相关系的平均水平, 就变成了相关系数均值统计量的情况. 很显然, 这个均值仍服从期望为0的正态分布, 但此时的方差变为了1n\frac{1}{n}, nn为样本量的数量, 从而95%置信水平对应的置信区间变为了[1.96/n,1.96/n][-1.96/\sqrt{n}, 1.96/\sqrt{n}]

根据上面两幅图, 得到p=2p=2, q=2q=2.

ARIMA模型拟合

注意这里使用的还是原序列经过log转换后的序列.

这是因为, 我们确定了二阶差分的结果为稳定序列, 在ARIMA模型中可以指定dd参数进行差分. 当然也可以使用差分后, 或者其他方法处理后得到的平稳序列进行建模, 这样在ARIMA模型中指定dd参数为0就可以了.

需要注意的是: 如果使用处理后的平稳序列来建模, 需要考虑如何将ARIMA模型拟合出来的结果序列, 以及预测序列进行还原. 平滑, 分解, 差分等方法对应着不同的还原方法.

直接将非平稳序列投入到ARIMA模型中, 使用提前确定好的能使序列平稳的差分阶数进行处理, 得到的拟合结果是差分之后的, 需要进行差分的还原才能投入到模型中的原始的非平稳时间序列进行对比.

png
png
png

还原拟合序列

使用predict方法进行拟合结果的输出, 注意typ参数, 指定了两种输出的形式:

  • linear: 输出差分后的结果, 结果与.fittedvalues一模一样

  • levels: 输入原始的结果, 已经消除了差分之后的结果

png

对未来进行预测

使用forecast方法对未来进行预测, 可以指定返回的未来时间点的数量.

返回三个值, 分别是:

  • forecast : array

    • Array of out of sample forecasts

  • stderr : array

    • Array of the standard error of the forecasts.

  • conf_int : array

    • 2d array of the confidence interval for the forecast, 即每个预测点的置信区间

png

结果并不是很好.

最后更新于

这有帮助吗?