使用Python建立时间序列(ARIMA、MA、AR)预测模型

文章内容整理自网上内容,作个人笔记分享使用,如有错误欢迎大家指正。o(`ω´ )o

文章目录

  • 时间序列定义
    • 1)数据导入和处理
    • 2)数据格式转换
    • 3)平稳性检验
      • 2)KPSS 测试
        • 消除趋势
    • 移动平均
    • 消除趋势和季节性变化
      • 1.差分Differencing
      • 2. 分解 Decomposing
    • 预测时间序列
      • ARIMA
      • AR model 自回归模型
      • MA model 移动平均模型
      • Combined Model
    • 预测
  • 参考资料


时间序列定义

时间序列(Time Series):按照时间的顺序吧一个随机事件变化发展的过程记录。最常见的时间序列应用,例如每个地区的降雨量、一天的温度变化情况等等。

1)数据导入和处理

数据来源&介绍 数据集包含了两组数据:数据里包含了月份以及每月的乘客数量。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline

from matplotlib.pylab import rcParams
rcParams['figure.figsize']=15,6

#数据导入和查看
data=pd.read_csv('Airpassengers.csv')
print(data.head())
print('\nData Types:')
print(data.dtypes)

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第1张图片

2)数据格式转换

将数据中的时间信息转换成索引。

#格式转换
dateparse=lambda dates: pd.datetime.strptime(dates,'%Y-%m')
data=pd.read_csv('Airpassengers.csv',parse_dates=['Month'],index_col='Month',date_parser=dateparse)
data.head()
# parse_dates:指定包含日期时间信息的列。例子里的列名是'Month‘
# index_col:在TS数据中使用pandas的关键是索引必须是日期等时间变量。所以这个参数告诉pandas使用'Month'列作为索引
# date_parser:它指定了一个将输入字符串转换为datetime可变的函数。pandas 默认读取格式为'YYYY-MM-DD HH:MM:SS'的数据。如果这里的时间格式不一样,就要重新定义时间格式,dataparse函数可以用于此目的。


#查看数据的索引
data.index

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第2张图片

注意到这里: dtype='datetime64[ns] 就可以确定是时间对象。这样将数据格式转换成Series object 就可以避免每次使用时都要提到列名。

3)平稳性检验

#导入包
from statsmodels.tsa.stattools import adfuller

def test_stationarity(timeseries):
    #Determing rolling statistics 
    rolmean=timeseries.rolling(12).mean()
    rolstd=timeseries.rolling(12).std()
    #Plot rolling statistics:
    orig=plt.plot(timeseries,color='blue',label='Original') 
    mean=plt.plot(rolmean,color='red',label='Rolling Mean') #均值
    std=plt.plot(rolstd,color='black',label='Rolling Std') #标准差
    plt.legend(loc='best')
    plt.title('Rolling Mean & Standard Deviation')
    plt.show(block=False)
    
    #Perform Dickey-Fuller Test:
    print('Results of Dickey-Fuller Test:')
    dftest=adfuller(timeseries,autolag='AIC')
    dfoutput=pd.Series(dftest[0:4],index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
    for key,value in dftest[4].items():
        dfoutput['Critical Value (%s)'%key]=value 
    print(dfoutput)

#检验结果
test_stationarity(ts)

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第3张图片
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第4张图片
虽然时间序列中的平均偏差不是很小,但很明显,这不是一个平稳的时间序列。此外,测试统计远远超过临界值。

在上面的例子中,检验统计量>临界值,这意味着序列是非平稳的。

2)KPSS 测试

KPSS测试,(Kwiatkowski-phillips-schmidt-Shin Test)
不如ADF方法流行。KPSS检验的原假设和备择假设与ADF检验相反。!!!
H0:序列是趋势平稳的
H1: 序列有一个单位根序列。(不是平稳的)

# define function for ADF 
from statsmodels.tsa.stattools import kpss

def kpss_test(timeseries):  #Perform KPSS Test:
    print('Results of KPSS Test:')
    kpsstest=kpss(timeseries,regression='c')
    kpss_output=pd.Series(kpsstest[0:3],index=['Test Statistic','p-value','#Lags Used'])
    for key,value in kpsstest[3].items():
        kpss_output['Critical Value (%s)'%key]=value 
    print(kpss_output)
    
kpss_test(train['#Passengers'])

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第5张图片
结果显示TS>cv, p <1% 表示拒绝数据是平稳的原假设,序列不是平稳的。

消除趋势

  • 转换:案例的数据很明显是一个显著的正趋势,所以可以使用转换方法惩罚高数值。对数、开方、开立方,等等。
ts_log=np.log(ts)
plt.plot(ts_log)
数据 图片
ts_log 使用Python建立时间序列(ARIMA、MA、AR)预测模型_第6张图片
t s_log & ts 使用Python建立时间序列(ARIMA、MA、AR)预测模型_第7张图片

注意两个图的单位不同,在第二幅图里,橙色(ts)是一条波浪线,蓝色(ts_log) 是经过对数转换后的结果,变成了一条直线。

在这个案例中,很容易看到数据的未来趋势。但在有噪音的情况下就不太直观了。因此,我们可以使用一些技术来估计或建模这种趋势,然后将其从序列中删除。

  • 汇总Aggregation取一段时间内的平均值,如月/周平均值
  • 平滑smoothing采用滚动平均
  • 多项式拟合Polynominal Fitting 拟合回归模型

移动平均

根据时间序列的频率取“k”连续值的平均值。这里我们可以取过去1年的平均值,即过去12个值。

moving_avg = ts_log.rolling(12).mean() #计算均值
ts_log_moving_avg_diff=ts_log-moving_avg #使用均值的差,使得整体平滑
ts_log_moving_avg_diff.dropna(inplace=True) #丢掉NAN
test_stationarity(ts_log_moving_avg_diff)#查看结果

因为我们取最后12个月的平均值,所以前11个月的移动平均值并没有定义。 数据是从1949年到1960年的每个月,1949年的前11个月,均不满12个月数据,因此不能计算平均值,结果显示空值,所以在之后处理中把这些空值删除。
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第8张图片
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第9张图片
滚动值似乎略有变化,但这里没有具体的趋势。而且,测试统计比5%的临界值小,所以我们可以用95%的置信度说这是一个平稳序列。然而,这种特殊方法的一个缺点是必须严格定义时间段。在这种情况下,我们可以取年平均值,但在复杂的情况下,如预测股票价格,很难得出一个数字。所以我们取一个“加权移动平均值”,其中最近的值被赋予更高的权重。可以有许多方法来分配权重。

  • EWMA 移动平均模型
    指数加权移动平均(Exponential Weighted Moving Average) 一种流行的方法是指数加权移动平均法,其中权重被分配给所有先前的值,并带有一个衰减因子。

panda库解释链接:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.ewm.html?highlight=ewm#pandas.DataFrame.ewm

“半衰期”用于定义指数衰减的量。

这只是一个假设,很大程度上取决于业务领域。其他参数,如跨度和质心也可以用来定义衰变,在上面的链接中进行了讨论。

expwighted_avg=pd.DataFrame.ewm(ts_log,halflife=12).mean()
plt.plot(ts_log)
plt.plot(expwighted_avg,color='yellow')
plt.plot(moving_avg,color='red')

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第10张图片
黄线是新增的EWMA。

ts_log_ewma_diff=ts_log-expwighted_avg
test_stationarity(ts_log_ewma_diff)
EWMA Moving-Average
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第11张图片 使用Python建立时间序列(ARIMA、MA、AR)预测模型_第12张图片
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第13张图片 使用Python建立时间序列(ARIMA、MA、AR)预测模型_第14张图片

EWMA在平均值和标准差上的变化更小。同时,检验统计量小于1%的临界值,这比以前的情况要好。请注意,在EWMA不会有遗漏的值(EWMA使用130,而MA使用119个观察值),因为从开始的所有值都是给定的权重。所以即使没有以前的值,它也可以工作。

消除趋势和季节性变化

上面的方法不适合于处理High seasonality的数据:

  1. 差分Differencing - t在一个特定的时间差取差分
  2. 分解Decomposition 对趋势和季节性进行建模,并将其从模型中移除

1.差分Differencing

取某一时刻的观测值与前一时刻的观测值之差。

#Differencing 
ts_log_diff=ts_log-ts_log.shift()

# reduced trend considerably
ts_log_diff.dropna(inplace=True)
test_stationarity(ts_log_diff)

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第15张图片
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第16张图片
由图可见,均值和标准差的变化都很小,并且在测试中小于10%的临界值,因此这个序列是平稳的,置信度为90%。我们也可以采用二阶或三阶差分,在某些应用中可能会得到更好的结果

2. 分解 Decomposing

both trend and seasonality are modeled separately and the remaining part of the series is returned.
将趋势和季节性分别建模,并返回序列的其余部分。

from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(ts_log)
trend = decomposition.trend
seasonal = decomposition.seasonal

#作图
residual = decomposition.resid
plt.subplot(411)
plt.plot(ts_log,label='Original')
plt.legend(loc='best')
plt.subplot(412)
plt.plot(trend,label='Trend')
plt.legend(loc='best')
plt.subplot(413)
plt.plot(seasonal,label='Seasonality')
plt.legend(loc='best')
plt.subplot(414)
plt.plot(residual,label='Residuals')
plt.legend(loc='best')
plt.tight_layout()

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第17张图片

ts_log_decompose = residual
ts_log_decompose.dropna(inplace=True)
test_stationarity(ts_log_decompose)

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第18张图片
使用Python建立时间序列(ARIMA、MA、AR)预测模型_第19张图片
从测试结果看到,P值远远小于1%的临界值,所以该序列非常符合平稳时间序列。

预测时间序列

对时间序列数据进行分析和预测比较完善和精确的算法是博克思-詹金斯(Box-Jenkins)方法,其常用模型包括:自回归模型(AR模型)、滑动平均模型(MA模型)、(自回归-滑动平均混合模型)ARMA模型、(差分整合移动平均自回归模型)ARIMA模型。

数据经过调整后,一般有两种情况:
1)严格平稳序列,各值之间不存在相关性,这是我们可以对残差的白噪声进行建模的一个简单的例子。但非常罕见。
2)值之间有显著相关性的序列。需要使用一些统计模型,如ARIMA来预测数据。

ARIMA

ARIMA模型(英语:Autoregressive Integrated Moving Average model),差分整合移动平均自回归模型,又称整合移动平均自回归模型(移动也可称作滑动),是时间序列预测分析方法之一。ARIMA(p,d,q)中,AR是“自回归”,p为自回归项数;MA为“滑动平均”,q为滑动平均项数,d为使之成为平稳序列所做的差分次数(阶数)。“差分”一词虽未出现在ARIMA的英文名称中,却是关键步骤。

它对平稳时间序列的预测只不过是一个线性(如线性回归)方程。预测因子取决于ARIMA模型的参数(p、d、q):

  1. AR(自回归)项的个数(p):AR项只是相依变量的滞后项。或者,如果p为5,x(t)的预测因子将是x(t-1)。x(t-5)
  2. 移动平均项数(g):MA项是预测方程中的滞后预测误差。例如,如果q为5,x(t)的预测值将为e(t-1)。e(t-5),其中e(i)是瞬时移动平均值与实际值之间的差值。
  3. 差异数(d):这是非季节性差异的数量,也就是说,在这种情况下,我们取一阶差分,这样我们就可以传递该变量,并将d=0传递给原始变量,将d=1放入。两者都会产生相同的结果
  • ACF(Autocorrelation Function),自协方差或自相关函数。
    时间序列Xt的自协方差是信号与其经过时间平移的信号之间的协方差。例如将t1,t2与t1-5和t2-5 相比。
    将有序的随机变量序列与其自身相比较,它反映了同一序列在不同时序的取值之间的相关性。

  • 偏自相关函数(PACF)计算的是严格的两个变量之间的相关性,是剔除了中间变量的干扰之后所得到的两个变量之间的相关程度。对于一个平稳的AR§模型,求出滞后为k的自相关系数p(k)时,实际所得并不是x(t)与x(t-k)之间的相关关系。这是因为在这两个变量之间还存在k-1个变量,它们会对这个自相关系数产生一系列的影响,而这个k-1个变量本身又是与x(t-k)相关的。这对自相关系数p(k)的计算是一个不小的干扰。而偏自相关函数可以剔除这些干扰。

  • 它是TS与自身滞后版本之间相关性的度量。例如lag5,ACF会比较时间瞬间“t1”的序列与瞬间t1-5的序列

ACF和PACF解释:https://blog.csdn.net/qq_41103204/article/details/105810742

#ACF and PACF plots:
from statsmodels.tsa.stattools import acf,pacf

lag_acf=acf(ts_log_diff,nlags=20)
lag_pacf=pacf(ts_log_diff,nlags=20,method='ols')

#Plot ACF:
plt.subplot(121)
plt.plot(lag_acf)
plt.axhline(y=0,linestyle='--',color='gray')
plt.axhline(y=-1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray')
plt.axhline(y=1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray')
plt.title('Autocorrelation Function')

#Plot PACF:
plt.subplot(122)
plt.plot(lag_pacf)
plt.axhline(y=0,linestyle='--',color='gray')
plt.axhline(y=-1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray')
plt.axhline(y=1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray')
plt.title('Partial Autocorrelation Function')
plt.tight_layout()

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第20张图片
在这个图上,两条在0附近的虚线是置信区间,可以用来决定’p’和‘q’

  1. p—PACF图第一次穿过置信区间上限的滞后值。如果你仔细观察,在这个例子中p=2
  2. q——ACF图第一次穿过置信区间上限的滞后值。如果你仔细观察,如果情况q=2,让我们制作3个不同的ARIMA模型,考虑到单个和组合的效果,我们还将为每个模型打印RSS。请注意,这里的RSS是残差值,而不是实际序列

AR model 自回归模型

自回归模型(英语:Autoregressive model,简称AR模型),是统计上一种处理时间序列的方法,用同一变数例如x的之前各期,亦即x1至xt-1来预测本期xt的表现,并假设它们为一线性关系。因为这是从回归分析中的线性回归发展而来,只是不用x预测y,而是用x预测 x(自己);所以叫做自回归。

from statsmodels.tsa.arima_model import ARIMA
model = ARIMA(ts_log,order=(2,1,0))
results_AR=model.fit(disp=-1)
plt.plot(ts_log_diff)
plt.plot(results_AR.fittedvalues,color='red')
plt.title('RSS: %.4f'% sum((results_AR.fittedvalues-ts_log_diff)**2))

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第21张图片

MA model 移动平均模型

移动平均模型关注的是自回归模型中的误差项的累加。它能够有效地消除预测中的随机波动。

model = ARIMA(ts_log,order=(0,1,2))
results_MA=model.fit(disp=-1)
plt.plot(ts_log_diff)
plt.plot(results_MA.fittedvalues,color='red')
plt.title('RSS: %.4f'% sum((results_MA.fittedvalues-ts_log_diff)**2))

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第22张图片

Combined Model

model = ARIMA(ts_log,order=(2,1,2))
results_ARIMA=model.fit(disp=-1)
plt.plot(ts_log_diff)
plt.plot(results_ARIMA.fittedvalues,color='red')
plt.title('RSS: %.4f'% sum((results_ARIMA.fittedvalues-ts_log_diff)**2))

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第23张图片
在这里我们可以看到,AR和MA型号的RSS几乎相同,但组合起来却要好得多。现在,我们只剩下最后一步,即将这些值返回原始值。

预测

predictions_ARIMA_diff =pd.Series(results_ARIMA.fittedvalues,copy=True)
predictions_ARIMA_diff.head()

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第24张图片

注意这些是从1949-02-01开始的,而不是第一个月。为什么?这是因为我们有1个月的滞后,并且第一个元素之前没有任何东西可以减去。将差分转换为对数标度的方法是将这些差分连续添加到基数上。一种简单的方法是首先确定索引的累计和,然后将其添加到基数中。累计和可以发现为

predictions_ARIMA_diff_cumsum= predictions_ARIMA_diff.cumsum()
predictions_ARIMA_diff_cumsum.head()

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第25张图片
您可以使用以前的输出快速进行一些事后计算,以检查这些计算是否正确。接下来我们要把它们加到基数上。为此,让我们创建一个以所有值为基数的系列,并将差异添加到其中。可以这样做

predictions_ARIMA_log=pd.Series(ts_log[0],index=ts_log.index)
predictions_ARIMA_log=predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum,fill_value=0)
predictions_ARIMA_log.head()

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第26张图片
这里的第一个元素是基数本身,从这个基础上累计相加的值。第一步是取指数并与原始系列预测ARIMA np exp(预测ARIMA log)进行比较

predictions_ARIMA=np.exp(predictions_ARIMA_log)
plt.plot(ts)
plt.plot(predictions_ARIMA)
plt.title('RMSE: %.4f'% np.sqrt(sum((predictions_ARIMA-ts)**2)/len(ts)))

使用Python建立时间序列(ARIMA、MA、AR)预测模型_第27张图片
橙色是我们的预测曲线

参考资料

  • EWMA 移动平均模型:https://blog.csdn.net/kuvinxu/article/details/6922138?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

  • ADF检验方法介绍:https://blog.csdn.net/FrankieHello/article/details/86766625/

  • Methods for TS forecasting:
    https://www.analyticsvidhya.com/blog/2018/02/time-series-forecasting-methods/

  • 数据链接:https://courses.analyticsvidhya.com/courses/take/a-comprehensive-learning-path-to-become-a-data-scientist-in-2020/texts/9775082-time-series-modeling-using-arima

你可能感兴趣的:(数据分析项目笔记,其他)