時系列予測-ARIMA実際の戦闘

ガイド

この記事は主に4つの部分に分かれています:
パンダを使用して時系列データを処理する方法、時系列データ
の安定性を確認する
方法、時系列データを安定させる方法、および
時系列データの予測

パンダを使用した時系列データのインポートと処理

ステップ1:一般的に使用されるライブラリをインポートする

import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from matplotlib.pylab import rcParams
#rcParams设定好画布的大小
rcParams['figure.figsize'] = 15, 6

ステップ2:時系列データをインポートする:
データファイルはgithubから
ダウンロードできます:http : //github.com/aarshayj/Analytics_Vidhya/tree/master/Articles/Time_Series_Analysis

#导入数据
data = pd.read_csv("../testdata/AirPassengers.csv")
print (data.head())
print ('\n Data types:')
print (data.dtypes)

運行結果は次のとおりです。データには、各月に対応する乗客数が含まれています。
データがすでに2つの列Monthと#Passengersを持つDataFrameであることがわかります。ここで、Monthのタイプはオブジェクトで、インデックスは0,1,2 ...です。
filelist
ステップ3:時系列データを処理するに
は、Monthのタイプをdatetimeに変更する必要があります。インデックスと同時に。

#处理时序数据
#我们需要将Month的类型变为datetime,同时作为index
dateparse = lambda dates: pd.datetime.strptime(dates, '%Y-%m')
#---其中parse_dates 表明选择数据中的哪个column作为date-time信息,
#---index_col 告诉pandas以哪个column作为 index
#--- date_parser 使用一个function(本文用lambda表达式代替),使一个string转换为一个datetime变量
data = pd.read_csv('../testdata/AirPassengers.csv', parse_dates=['Month'], index_col='Month',date_parser=dateparse)
print (data.head())
print (data.index)

結果は次のようになります。データのインデックスがMonth of datetime型になっていることがわかります。
在这里插入图片描述

時系列データの安定性をチェックする方法(定常性)

因为ARIMA模型要求数据是稳定的,所以这一步至关重要。
1. 判断数据是稳定的常基于对于时间是常量的几个统计量:
常量的均值
常量的方差
与时间独立的自协方差
用图像说明如下:
均值
filelist
X是时序数据的值,t是时间。可以看到左图,数据的均值对于时间轴来说是常量,即数据的均值不是时间的函数,所有它是稳定的;右图随着时间的推移,数据的值整体趋势是增加的,所有均值是时间的函数,数据具有趋势,所以是非稳定的。
方差
filelist
可以看到左图,数据的方差对于时间是常量,即数据的值域围绕着均值上下波动的振幅是固定的,所以左图数据是稳定的。而右图,数据的振幅在不同时间点不同,所以方差对于时间不是独立的,数据是非稳定的。但是左、右图的均值是一致的。
自协方差
filelist
一个时序数据的自协方差,就是它在不同两个时刻i,j的值的协方差。可以看到左图的自协方差于时间无关;而右图,随着时间的不同,数据的波动频率明显不同,导致它i,j取值不同,就会得到不同的协方差,因此是非稳定的。虽然右图在均值和方差上都是与时间无关的,但仍是非稳定数据。
2. python判断时序数据稳定性
有两种方法:
1.Rolling statistic-- 即每个时间段内的平均的数据均值和标准差情况。
2. Dickey-Fuller Test – 这个比较复杂,大致意思就是在一定置信水平下,对于时序数据假设 Null hypothesis: 非稳定。
if 通过检验值(statistic)< 临界值(critical value),则拒绝null hypothesis,即数据是稳定的;反之则是非稳定的。

# python判断时序数据稳定性
#ARIMA模型要求数据是稳定的,所以这一步至关重要
# 有两种方法:
# 1.Rolling statistic-- 即每个时间段内的平均的数据均值和标准差情况。
# 2. Dickey-Fuller Test -- 这个比较复杂,大致意思就是在一定置信水平下,对于时序数据假设 Null hypothesis: 非稳定。
# if 通过检验值(statistic)< 临界值(critical value),则拒绝null hypothesis,即数据是稳定的;反之则是非稳定的。
from statsmodels.tsa.stattools import adfuller
def test_stationarity(timeseries):
    # 这里以一年为一个窗口,每一个时间t的值由它前面12个月(包括自己)的均值代替,标准差同理。
    rolmean = timeseries.rolling(12).mean()
    rolstd = timeseries.rolling(12).std()

    # plot rolling statistics:
    fig = plt.figure()
    fig.add_subplot()
    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 standard deviation')

    plt.legend(loc='best')
    plt.title('Rolling Mean & Standard Deviation')
    plt.show(block=False)

    # Dickey-Fuller test:

    print ('Results of Dickey-Fuller Test:')
    dftest = adfuller(timeseries, autolag='AIC')
    # dftest的输出前一项依次为检测值,p值,滞后数,使用的观测数,各个置信度下的临界值
    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)
ts = data['Passengers']
test_stationarity(ts)

結果は次のとおりです。
在这里插入图片描述
在这里插入图片描述
データのローリング平均/標準偏差は増加傾向にあり、不安定であることがわかります。
また、DFテストは、データがどの程度の信頼度でも安定していないことを明確に指摘できます。

3.時系列データを安定させる方法
データが不安定になる主な理由は2つあります。

トレンドデータは時間とともに変化します。たとえば、増加または減少します。
季節性-特定の期間内のデータの変化。たとえば、休日、またはデータ異常を引き起こすイベント。
元のデータの範囲が比較的広いため、他の情報を保持しながら値の範囲を減らすために、一般的な方法は対数化して対数を取ることです。

ts_log = np.log(ts)

傾向
検出して削除するには、通常3つの方法があります
集計:時間軸を短縮し、一定期間内の週/月/年の平均値をデータ値として使用します。さまざまな期間の値のギャップを減らします。
平滑化:値間のギャップを狭くするために、スライディングウィンドウで元の値を平均値に置き換えます
多項式フィルタリング:回帰モデルを使用して既存のデータを近似し、データを滑らかにします。
この記事では主に平滑化法
移動平均移動平均を使用しています

#平滑方法
#Moving Average--移动平均
moving_avg = ts_log.rolling(12).mean()
plt.plot(ts_log ,color = 'blue')
plt.plot(moving_avg, color='red')
plt.show()

在这里插入图片描述
moving_averageは元の値よりもはるかに滑らかであることがわかります。
次に違いを生みます:

ts_log_moving_avg_diff = ts_log-moving_avg
ts_log_moving_avg_diff.dropna(inplace = True)
test_stationarity(ts_log_moving_avg_diff)

在这里插入图片描述
在这里插入图片描述
処理されたデータには基本的に経時的な傾向がないことがわかりますDFtestの結果から、データは95%の信頼度で安定していることがわかります。

上記の方法は、すべての時間を平等に扱うことであり、多くの場合、その瞬間に近いほど重要であると考えることができます。そのため、指数加重移動平均が導入されました-指数加重移動平均(この関数は、パンダのewm()関数によって提供されます)。

# halflife的值决定了衰减因子alpha:  alpha = 1 - exp(log(0.5) / halflife)
expweighted_avg = pd.DataFrame.ewm(ts_log,halflife=12).mean()
ts_log_ewma_diff = ts_log - expweighted_avg
test_stationarity(ts_log_ewma_diff)

在这里插入图片描述
在这里插入图片描述

新しいデータの平均標準偏差が通常の移動平均よりも小さいことがわかります。また、DFtestはデータが99%の信頼性で安定していると結論付けることができます。

检测和去除季节性
有两种方法:
1 差分化: 以特定滞后数目的时刻的值的作差
2 分解: 对趋势和季节性分别建模在移除它们
Differencing–差分

ts_log_diff = ts_log - ts_log.shift()
ts_log_diff.dropna(inplace=True)
test_stationarity(ts_log_diff)

在这里插入图片描述
在这里插入图片描述
如图,可以看出相比MA方法,Differencing方法处理后的数据的均值和方差的在时间轴上的振幅明显缩小了。DFtest的结论是在90%的置信度下,数据是稳定的。

3.Decomposing-分解

#分解(decomposing) 可以用来把时序数据中的趋势和周期性数据都分离出来:
from statsmodels.tsa.seasonal import seasonal_decompose
def decompose(timeseries):
    
    # 返回包含三个部分 trend(趋势部分) , seasonal(季节性部分) 和residual (残留部分)
    decomposition = seasonal_decompose(timeseries)
    
    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()
    
    return trend , seasonal, residual

在这里插入图片描述

如图可以明显的看到,将original数据 拆分成了三份。Trend数据具有明显的趋势性,Seasonality数据具有明显的周期性,Residuals是剩余的部分,可以认为是去除了趋势和季节性数据之后,稳定的数据,是我们所需要的。

#消除了trend 和seasonal之后,只对residual部分作为想要的时序数据进行处理
trend , seasonal, residual = decompose(ts_log)
residual.dropna(inplace=True)
test_stationarity(residual)

在这里插入图片描述
在这里插入图片描述

如图所示,数据的均值和方差趋于常数,几乎无波动(看上去比之前的陡峭,但是要注意他的值域只有[-0.05,0.05]之间),所以直观上可以认为是稳定的数据。另外DFtest的结果显示,Statistic值原小于1%时的Critical value,所以在99%的置信度下,数据是稳定的。

4. 对时序数据进行预测
假设经过处理,已经得到了稳定时序数据。接下来,我们使用ARIMA模型
对数据已经预测。ARIMA的介绍可以见另一篇文章

step1: 通过ACF,PACF进行ARIMA(p,d,q)的p,q参数估计

由前文Differencing部分已知,一阶差分后数据已经稳定,所以d=1。
所以用一阶差分化的ts_log_diff = ts_log - ts_log.shift() 作为输入。
等价于 yt=Yt−Yt−1 作为输入。

先画出ACF,PACF的图像,代码如下:

#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()

在这里插入图片描述

この図では、上部の灰色の線と下部の灰色の線が信頼区間であり、pの値は、ACFが最初に上部信頼区間と交差したときの横軸の値です。qの値は、PACFが最初に上限信頼区間を横切る水平軸の値です。したがって、図からp = 2およびq = 2を取得できます。

ステップ2:パラメーター推定値p、d、qを取得した後
、違いを強調するためにモデルARIMA(p、d、q)を生成し、3つのパラメーター値を持つ3つのモデルを比較として使用します。
モデル1:ARモデル(ARIMA(2,1,0))

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))

在这里插入图片描述

この図では、青い線が入力値、赤い線がモデルの近似値、およびRSSの累積二乗誤差です。

モデル2:MAモデル(ARIMA(0,1,2))

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))

在这里插入图片描述

モデル3:ARIMAモデル(ARIMA(2,1,2))

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))

在这里插入图片描述

RSSから、モデル3-ARIMA(2,1,2)が最適であることがわかり、最終的な予測モデルを決定しました。

ステップ3:モデルを元のデータに置き換えて予測します。
上記のモデルの近似値は、元のデータを安定化した後の入力データの近似であるため、近似値に対応する処理の逆演算を実行して、元のデータと同じスケール。

#ARIMA拟合的其实是一阶差分ts_log_diff,predictions_ARIMA_diff[i]是第i个月与i-1个月的ts_log的差值。
#由于差分化有一阶滞后,所以第一个月的数据是空的,
predictions_ARIMA_diff = pd.Series(results_ARIMA.fittedvalues, copy=True)
print predictions_ARIMA_diff.head()
#累加现有的diff,得到每个值与第一个月的差分(同log底的情况下)。
#即predictions_ARIMA_diff_cumsum[i] 是第i个月与第1个月的ts_log的差值。
predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum()
#先ts_log_diff => ts_log=>ts_log => ts 
#先以ts_log的第一个值作为基数,复制给所有值,然后每个时刻的值累加与第一个月对应的差值(这样就解决了,第一个月diff数据为空的问题了)
#然后得到了predictions_ARIMA_log => predictions_ARIMA
predictions_ARIMA_log = pd.Series(ts_log.ix[0], index=ts_log.index)
predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum,fill_value=0)
predictions_ARIMA = np.exp(predictions_ARIMA_log)
plt.figure()
plt.plot(ts)
plt.plot(predictions_ARIMA)
plt.title('RMSE: %.4f'% np.sqrt(sum((predictions_ARIMA-ts)**2)/len(ts)))
plt.show()

在这里插入图片描述
在这里插入图片描述
step4:来年のデータの変化を予測する

5.总结
前面一篇文章,总结了ARIMA建模的步骤。
(1). 获取被观测系统时间序列数据;
(2). 对数据绘图,观测是否为平稳时间序列;对于非平稳时间序列要先进行d阶差分运算,化为平稳时间序列;
(3). 经过第二步处理,已经得到平稳时间序列。要对平稳时间序列分别求得其自相关系数ACF 和偏自相关系数PACF,通过对自相关图和偏自相关图的分析,得到最佳的阶层 p 和阶数 q
(4). 由以上得到的d、q、p,得到ARIMA模型。然后开始对得到的模型进行模型检验。
本文结合一个例子,说明python如何解决:
1.判断一个时序数据是否是稳定。对应步骤(1)
2. 怎样让时序数据稳定化。对应步骤(2)
3. 使用ARIMA模型进行时序数据预测。对应步骤(3,4)

おすすめ

転載: blog.csdn.net/qq_30868737/article/details/108472380