【译】用Python开发向量自动回归模型

788 阅读6分钟

初学者数据科学机器学习Python时间序列预测

用Python开发向量自回归模型!

neha30 ,2021年8月9日

文章视频书

这篇文章是作为数据科学博客马拉松的一部分发表的

简介

单变量时间序列是一个只包含一个时间变量的序列,而多变量时间序列有一个以上的时间变量。每个变量不仅取决于其过去的值,而且对其他变量也有一些依赖性。

向量自回归(VAR)

向量自回归(VAR)是一种多变量预测算法,当两个或多个时间序列相互影响时,就会使用这种算法。

让我们以一个例子来理解这一点。在一般的单变量预测算法(AR,ARMA,ARIMA)中,我们只预测一个随时间变化的变量。这里'钱'是依赖于时间的。

univariate data | Vector autoregressive

现在,假设我们还有一个依赖于时间的特征,并且也可以影响另一个依赖于时间的变量。让我们添加另一个特征'消费'。

multivariate data | Vector autoregressive

在这里,我们将同时预测'金钱'和'支出'。 如果我们绘制它们,我们可以看到两者将显示类似的趋势。

plot money and spending | Vector autoregressive

其他自回归模型(AR、ARMA和ARIMA)与VAR模型的主要区别在于,前者是单向的(预测变量影响目标变量,反之亦然),而VAR是双向的。

一个典型的AR(P)模型看起来像这样。

AR model

这里:
c->截距
phiphi -> Y的滞后系数,直到P阶
epsilon -> 误差

一个P阶的K维VAR模型,表示为VAR(P),考虑K=2,那么方程式将是。

k dimensional var model

对于VAR模型,我们有多个相互影响的时间序列变量,在这里,它被建模为一个方程系统,每个时间序列变量有一个方程。这里k代表时间序列变量的数量。

以矩阵形式。

in matrix form | Vector autoregressive

VAR(P)的方程是。

equation of var | Vector autoregressive

Python中的VAR模型

让我们看看使用Kaggle的货币和支出数据集的VAR模型。我们把这些数据集合并成一个数据集,显示出货币和支出相互影响。最终合并的数据集时间跨度为2013年1月至2017年4月。

我们建立VAR模型需要遵循的步骤是。

1.检查数据
2.测试静止性
2.1 如果数据是非静止的,取其差值。
2.2 重复这个过程,直到得到静止的数据。
3.训练测试分割
4.网格搜索顺序P
5.应用具有P阶的VAR模型
6.对新数据进行预测。
7.如果有必要,对先前的转换进行反转。

1.检查数据

首先导入所有需要的库

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

现在读取数据集

money_df = pd.read_csv('M2SLMoneyStock.csv')
spending_df = pd.read_csv('PCEPersonalSpending.csv')
df = money_df.join(spending_df)

(252,2)

df.head()

货币支出

日期

1/1/1995 3492.4 4851.2

2/1/1995 3489.9 4850.8

3/1/1995 3491.1 4885.4

4/1/1995 3499.2 4890.2

5/1/1995 3524.2 4933.2

2.检查静止性

在应用VAR模型之前,数据中的所有时间序列变量应该是静止的。静止性是一种统计学属性,其中时间序列显示出恒定的平均值和方差随时间变化。

进行静止性检查的常用方法之一是Augmented Dickey-Fuller检验。

在ADF检验中,有一个无效假设,即时间序列被认为是非平稳的。因此,如果测试的p值小于显著性水平,那么它就会拒绝无效假设,认为时间序列是静止的。

def adf_test(series,title=''):
    """
    Pass in a time series and an optional title, returns an ADF report
    """
    print(f'Augmented Dickey-Fuller Test: {title}')
    result = adfuller(series.dropna(),autolag='AIC') # .dropna() handles differenced data
    labels = ['ADF test statistic','p-value','# lags used','# observations']
    out = pd.Series(result[0:4],index=labels)
    for key,val in result[4].items():
        out[f'critical value ({key})']=val
    print(out.to_string())          # .to_string() removes the line "dtype: float64"
    if result[1] <= 0.05:
        print("Strong evidence against the null hypothesis")
        print("Reject the null hypothesis")
        print("Data has no unit root and is stationary")
    else:
        print("Weak evidence against the null hypothesis")
        print("Fail to reject the null hypothesis")
        print("Data has a unit root and is non-stationary")

检查这两个特征是否是静止的。

adf_test(df['Money'])

Augmented Dickey-Fuller Test: 
ADF test statistic        4.239022
p-value                   1.000000
# lags used               4.000000
# observations          247.000000
critical value (1%)      -3.457105
critical value (5%)      -2.873314
critical value (10%)     -2.573044
Weak evidence against the null hypothesis
Fail to reject the null hypothesis
Data has a unit root and is non-stationary

现在检查变量 "支出"。

adf_test(df['Spending'])

Augmented Dickey-Fuller Test: 
ADF test statistic        0.149796
p-value                   0.969301
# lags used               3.000000
# observations          248.000000
critical value (1%)      -3.456996
critical value (5%)      -2.873266
critical value (10%)     -2.573019
Weak evidence against the null hypothesis
Fail to reject the null hypothesis
Data has a unit root and is non-stationary

这两个变量都不是静止的,所以我们将对整个DataFrame进行一阶差分,并重新运行增强的Dickey-Fuller检验。

df_difference = df.diff()
adf_test(df_difference['Money'])
Augmented Dickey-Fuller Test: 
ADF test statistic     -7.077471e+00
p-value                 4.760675e-10
# lags used             1.400000e+01
# observations          2.350000e+02
critical value (1%)    -3.458487e+00
critical value (5%)    -2.873919e+00
critical value (10%)   -2.573367e+00
Strong evidence against the null hypothesis
Reject the null hypothesis
Data has no unit root and is stationary
adf_test(df_difference['Spending'])

Augmented Dickey-Fuller Test: 
ADF test statistic     -8.760145e+00
p-value                 2.687900e-14
# lags used             8.000000e+00
# observations          2.410000e+02
critical value (1%)    -3.457779e+00
critical value (5%)    -2.873609e+00
critical value (10%)   -2.573202e+00
Strong evidence against the null hypothesis
Reject the null hypothesis
Data has no unit root and is stationary

3.训练-测试分离

我们将使用过去1年的数据作为测试集(过去12个月)。

test_obs = 12
train = df_difference[:-test_obs]
test = df_difference[-test_obs:]

4.阶数P的网格搜索

for i in [1,2,3,4,5,6,7,8,9,10]:
    model = VAR(train)
    results = model.fit(i)
    print('Order =', i)
    print('AIC: ', results.aic)
    print('BIC: ', results.bic)
    print()
Order = 1
AIC:  14.178610495220896

Order = 2
AIC:  13.955189367163705

Order = 3
AIC:  13.849518291541038

Order = 4
AIC:  13.827950574458281

Order = 5
AIC:  13.78730034460964

Order = 6
AIC:  13.799076756885809

Order = 7
AIC:  13.797638727913972

Order = 8
AIC:  13.747200843672085

Order = 9
AIC:  13.768071682657098

Order = 10
AIC:  13.806012266239211

随着你不断增加P的值,模型变得更加复杂。AIC对复杂的模型进行惩罚。

我们可以看到,当我们拟合更复杂的模型时,AIC开始下降,但是,在一定时间后AIC又开始增加。这是因为AIC正在惩罚这些模型过于复杂。

VAR(5)返回的分数最低,之后AIC又开始增加,因此我们将建立5阶的VAR模型。

5.拟合VAR(5)模型

result = model.fit(5)
result.summary()
  Summary of Regression Results   
==================================
Model:                         VAR
Method:                        OLS
Date:           Thu, 29, Jul, 2021
Time:                     15:21:45
--------------------------------------------------------------------
No. of Equations:         2.00000    BIC:                    14.1131
Nobs:                     233.000    HQIC:                   13.9187
Log likelihood:          -2245.45    FPE:                    972321.
AIC:                      13.7873    Det(Omega_mle):         886628.
--------------------------------------------------------------------
Results for equation Money
==============================================================================
                 coefficient       std. error           t-stat            prob
------------------------------------------------------------------------------
const               0.516683         1.782238            0.290           0.772
L1.Money           -0.646232         0.068177           -9.479           0.000
L1.Spending        -0.107411         0.051388           -2.090           0.037
L2.Money           -0.497482         0.077749           -6.399           0.000
L2.Spending        -0.192202         0.068613           -2.801           0.005
L3.Money           -0.234442         0.081004           -2.894           0.004
L3.Spending        -0.178099         0.074288           -2.397           0.017
L4.Money           -0.295531         0.075294           -3.925           0.000
L4.Spending        -0.035564         0.069664           -0.511           0.610
L5.Money           -0.162399         0.066700           -2.435           0.015
L5.Spending        -0.058449         0.051357           -1.138           0.255
==============================================================================

6 预测测试数据

VAR .forecast()函数要求我们传入以前观测值的滞后阶数。

lagged_Values = train.values[-8:]
pred = result.forecast(y=lagged_Values, steps=12) 

7.颠倒转换

我们必须注意,预测值是一个二阶差值。为了让它与原始数据相似,我们必须回滚每个差值。这可以通过取原始系列训练数据的最新值并将其加入预测值的累积太阳中来完成。

df_forecast['Money1d'] = (df['Money'].iloc[-test_obs-1]-df['Money'].iloc[-test_obs-2]) + df_forecast['money2d'].cumsum()
df_forecast['MoneyForecast'] = df['Money'].iloc[-test_obs-1] + df_forecast['Money1d'].cumsum()
df_forecast['Spending1d'] = (df['Spending'].iloc[-test_obs-1]-df['Spending'].iloc[-test_obs-2]) + df_forecast['Spending2d'].cumsum()
df_forecast['SpendingForecast'] = df['Spending'].iloc[-test_obs-1] + df_forecast['Spending1d'].cumsum()

绘制结果

现在让我们绘制测试数据的 "金钱 "和 "支出 "的预测值和/或原始值。

test_original = df[-test_obs:]
test_original.index = pd.to_datetime(test_original.index)
test_original['Money'].plot(figsize=(12,5),legend=True)
df_forecast['MoneyForecast'].plot(legend=True)

plot forecast

test_original['Spending'].plot(figsize=(12,5),legend=True)
df_forecast['SpendingForecast'].plot(legend=True)

plot spending forecast

原始值和预测值对'金钱'和'支出'都显示出类似的模式。

结论

在这篇文章中,首先,我们给出了对单变量和多变量分析的基本理解,然后是VAR模型背后的直觉和在Python中实现VAR模型所需的步骤。

我希望你喜欢阅读这篇文章。如果你有任何疑问/建议,请在评论中告诉我。

本文所展示的媒体不属于Analytics Vidhya所有,由作者自行决定使用。

你也可以在我们的手机APP上阅读这篇文章 Get it on Google Play

标签 :博客马拉松, 机器学习, 时间序列

[

下一篇

探索数据可视化的Matplotlib样式表

](www.analyticsvidhya.com/blog/2021/0…

上一篇

医疗保健中的深度学习--医疗界的希望之光

](www.analyticsvidhya.com/blog/2021/0…)

neha30