ARIMA 模型

时间序列

        时间序列是指将某种现象的指标数值按照时间顺序排列而成的数值序列。

        时间序列分析大致可分成三大部分,分别是描述过去、分析规律和预测未来,

        时间序列数据

        对同一对象在不同时间连续观察所取得的数据

        它具备两个要素,第一个要素是时间要素,第二个要素是数值要素

        例如:

  •         从出生到现在,你的体重的数据
  •         在某地方每隔一小时测得的温度数据

        时间序列根据时间和数值性质的不同,可以分为时期时间序列和时点时间序列

  •         时期序列中,数值要素反映现象在一定时期内发展的结果(比如GDP)
  •         时点序列中,数值要素反映现象在一定时点上的瞬间水平 (比如体重)

        时期序列可加,时点序列不可加。 

ARIMA模型

总流程

目的

        对时间序列数据进行预测

要求

        数据具有平稳性——“惯性”,平稳性要求数据的均值和方差不发生明显变化。

  •         严平稳:分布不随时间的改变而改变。
  •         弱平稳(大部分):期望与相关系数(依赖性)不变。未来某时刻的值X要依赖于它过去信息,所以需要依赖性。

差分法

        用以让不够平稳的数据变平稳

        方法如其名

        差分的实现

import sys
import os
import pandas as pd
import numpy as np

import statsmodels.api as sm
import statsmodels.formula.api as smf
import statsmodels.tsa.api as smt
import matplotlib.pylab as plt

import seaborn as sns

pd.set_option('display.float_format', lambda x: '%.5f' % x)
np.set_printoptions(precision=5, suppress=True)
pd.set_option('display.max_columns', 100)
pd.set_option('display.max_rows', 100)
sns.set(style='ticks', context='poster')

Sentiment = 'data.csv'
Sentiment = pd.read_csv(Sentiment, index_col=0, parse_dates=[0])
print(Sentiment)
Sentiment.plot(figsize=(12,8))
plt.legend(bbox_to_anchor=(1.25, 0.5))
plt.title("Consumer Sentiment")
sns.despine()


Sentiment['col3'] = Sentiment['col2'].diff(1)  # 求差分值,一阶差分。1指的是1个时间间隔,可更改。

Sentiment['col4'] = Sentiment['col3'].diff(1)  # 再求差分,二阶差分。
print(Sentiment)
Sentiment.plot(subplots=True, figsize=(18, 12))

plt.show()

自回归模型(AR)

        描述当前值与历史值之间的关系,用变量自身的历史时间数据对自身进行预测

        必须满足平稳性

        阶数指时间间隔

        p阶自回归过程的公式

                y_t = \mu + \sum_{i=1}^{p} \gamma_i y_{t - i} + \epsilon_t

        \mu是常数项,\gamma_i是自相关系数,\epsilon_t是误差。

        p人为选定 

        限制:必须具有自相关性,若自相关系数小于0.5则不宜采用。

移动平均模型(MA)

        关注自回归模型中的误差项的累加

        即时间序列当前值与历史值没有关系,而只依赖于历史白噪声的线性组合

        q阶自回归过程的公式

        y_t = \mu + \epsilon_t + \sum_{i=1}^{q} \theta_i \epsilon_{t - i}

        有效消除随机波动

差分自回归移动模型(ARIMA) 

        AR 与 MA结合,I指差分

        y_t = \mu + \sum_{i=1}^{p} \gamma_i y_{t - i} + \epsilon_t + \sum_{i=1}^{q} \theta_i \epsilon_{t - i}

        指定参数(p,d,q),d是差分的次数,一般1次就够

        该式表明:

  •         一个随机时间序列可以通过一个自回归移动平均模型来表示,即该序列可以由其自身的过去或滞后值以及随机扰动项来解释。
  •         如果该序列是平稳的,即它的行为并不会随着时间的推移而变化,那么我们就可以通过该序列过去的行为来预测未来。 

 参数p、q的选取

        自相关函数ACF(autocorrelation function)

                有序的随机变量序列与其自身相比较

                反映同一序列在不同时序的取值之间的相关性

                公式

                        ACF(k) = \rho_k = \frac{Cov(y_t,y_{t-k})}{Var(y_t)}

                取值范围[-1, 1] 

        偏自相关函数(PACF)

                ACF还受其他阶数变量影响,PACF剔除中间的影响,只保留yt和yt-k的关系。

import statsmodels.api as sm
import pandas as pd
import matplotlib.pylab as plt

# read data
rd_data = pd.read_csv('data.csv')
data = pd.Series([x for x in rd_data['col2']], index=[y for y in rd_data['col1']])
print(data)

fig = plt.figure(figsize=(12, 8))
# acf
ax1 = fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(data, lags=20, ax=ax1)
ax1.xaxis.set_ticks_position('bottom')
fig.tight_layout()
# pacf
ax2 = fig.add_subplot(212)
fig = sm.graphics.tsa.plot_pacf(data, lags=20, ax=ax2)
ax2.xaxis.set_ticks_position('bottom')

plt.show()

阶数确定

        截尾:落入置信区间内 

        奇异点、离群点不管

        散点图 

        

# 散点图
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns
# read data
rd_data = pd.read_csv('data.csv')
data = pd.Series([x for x in rd_data['col2']], index=[y for y in rd_data['col1']])

lags = 9
ncols = 3
nrows = int(np.ceil(lags / ncols))

fig, axes = plt.subplots(ncols=ncols, nrows=nrows, figsize=(4 * ncols, 4 * nrows))

for ax, lag in zip(axes.flat, np.arange(1, lags + 1, 1)):
    lag_str = 't-{}'.format(lag)
    X = (pd.concat([data, data.shift(-lag)], axis=1, keys=['y'] + [lag_str]).dropna())

    X.plot(ax=ax, kind='scatter', y='y', x=lag_str)
    corr = X.corr().values[0][1]
    ax.set_ylabel('Original')
    ax.set_title('Lag: {} (corr={:.2f})'.format(lag_str, corr))
    ax.set_aspect('equal')
    sns.despine()

fig.tight_layout()
plt.show()

ARIMA建模流程

  1. 将序列平稳(差分法确定d)
  2. p阶和q阶数确定:ACF与PACF
  3. ARIMA(p,d,q) 

模板

# 模板
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns
import statsmodels.api as sm
def tsplot(y, lags=None, title='', figsize=(14, 8)):
    fig = plt.figure(figsize=figsize)
    layout = (2, 2)
    ts_ax = plt.subplot2grid(layout, (0, 0))
    hist_ax = plt.subplot2grid(layout, (0, 1))
    acf_ax = plt.subplot2grid(layout, (1, 0))
    pacf_ax = plt.subplot2grid(layout, (1, 1))

    y.plot(ax=ts_ax)
    ts_ax.set_title(title)
    y.plot(ax=hist_ax, kind='hist', bins=25)
    hist_ax.set_title('Histogram')
    sm.graphics.tsa.plot_acf(y, lags=lags, ax=acf_ax)
    sm.graphics.tsa.plot_pacf(y, lags=lags, ax=pacf_ax)
    [ax.set_xlim(0) for ax in [acf_ax, pacf_ax]]
    sns.despine()
    plt.tight_layout()
    return ts_ax, acf_ax, pacf_ax


# read data
rd_data = pd.read_csv('data.csv')
data = pd.Series([x for x in rd_data['col2']], index=[y for y in rd_data['col1']])


tsplot(data, title='Random data', lags=36)
plt.show()

评估

        模型选择AIC与BIC:选择更简单的模型

        AIC = 2k - sln(L)

        BLC = kln(n) - 2ln(L)

        k为模型参数个数,n为样本数量,L为似然函数

        选小的

        

import sys
import os
import pandas as pd
import numpy as np

import statsmodels.api as sm
import statsmodels.formula.api as smf
import statsmodels.tsa.api as smt

# Display and Plotting
import matplotlib.pylab as plt
import seaborn as sns

pd.set_option('display.float_format', lambda x: '%.5f' % x)  # pandas
np.set_printoptions(precision=5, suppress=True)  # numpy

pd.set_option('display.max_columns', 100)
pd.set_option('display.max_rows', 100)

# seaborn plotting style
sns.set(style='ticks', context='poster')

filename_ts = 'data.csv'
ts_df = pd.read_csv(filename_ts, index_col=1, parse_dates=[0])

n_sample = ts_df.shape[0]

print(ts_df.shape)
print(ts_df.head())
# Create a training sample and testing sample before analyzing the series
n_train = int(0.95 * n_sample) + 1
# 计算训练样本的大小。这里使用 95% 的数据作为训练集,+1 用于确保至少有一个样本在测试集中。
n_forecast = n_sample - n_train
# 计算预测样本的大小。
ts_train = ts_df.iloc[:n_train]['col1']
# 从时间序列数据框中选择前 n_train 行作为训练样本.
ts_test = ts_df.iloc[n_train:]['col1']
# 从时间序列数据框中选择从第 n_train 行开始到最后一行的数据作为测试样本,
print(ts_train.shape)
print(ts_test.shape)
print("Training Series:", "\n", ts_train.tail(), "\n")
print("Testing Series:", "\n", ts_test.head())


def tsplot(y, lags=None, title='', figsize=(14, 8)):
    fig = plt.figure(figsize=figsize)
    layout = (2, 2)
    ts_ax = plt.subplot2grid(layout, (0, 0))
    hist_ax = plt.subplot2grid(layout, (0, 1))
    acf_ax = plt.subplot2grid(layout, (1, 0))
    pacf_ax = plt.subplot2grid(layout, (1, 1))

    y.plot(ax=ts_ax)
    ts_ax.set_title(title)
    y.plot(ax=hist_ax, kind='hist', bins=25)
    hist_ax.set_title('Histogram')
    sm.graphics.tsa.plot_acf(y, lags=lags, ax=acf_ax)
    sm.graphics.tsa.plot_pacf(y, lags=lags, ax=pacf_ax)
    [ax.set_xlim(0) for ax in [acf_ax, pacf_ax]]
    sns.despine()
    plt.tight_layout()
    return ts_ax, acf_ax, pacf_ax


tsplot(ts_train, title='A Given Training Series', lags=20)
plt.show()

'''
arima200 = sm.tsa.SARIMAX(ts_train, order=(2, 0, 0))# order里边的三个参数p,d,q
model_results = arima200.fit()# fit模型
'''

train_results = sm.tsa.arma_order_select_ic(ts_train, ic=['aic', 'bic'], trend='n', max_ar=4, max_ma=4)

print('AIC', train_results.aic_min_order)
print('BIC', train_results.bic_min_order)

模型残差检查 

        残差是否是平均值为0且方差是常数的正态分布

        QQ图:线性即正态分布

import sys
import os
import pandas as pd
import numpy as np

import statsmodels.api as sm
import statsmodels.formula.api as smf
import statsmodels.tsa.api as smt

# Display and Plotting
import matplotlib.pylab as plt
import seaborn as sns

pd.set_option('display.float_format', lambda x: '%.5f' % x)  # pandas
np.set_printoptions(precision=5, suppress=True)  # numpy

pd.set_option('display.max_columns', 100)
pd.set_option('display.max_rows', 100)

# seaborn plotting style
sns.set(style='ticks', context='poster')

filename_ts = 'data.csv'
ts_df = pd.read_csv(filename_ts, index_col=1, parse_dates=[0])

n_sample = ts_df.shape[0]

print(ts_df.shape)
print(ts_df.head())
# Create a training sample and testing sample before analyzing the series
n_train = int(0.95 * n_sample) + 1
# 计算训练样本的大小。这里使用 95% 的数据作为训练集,+1 用于确保至少有一个样本在测试集中。
n_forecast = n_sample - n_train
# 计算预测样本的大小。
ts_train = ts_df.iloc[:n_train]['col1']
# 从时间序列数据框中选择前 n_train 行作为训练样本.
ts_test = ts_df.iloc[n_train:]['col1']
# 从时间序列数据框中选择从第 n_train 行开始到最后一行的数据作为测试样本,
print(ts_train.shape)
print(ts_test.shape)
print("Training Series:", "\n", ts_train.tail(), "\n")
print("Testing Series:", "\n", ts_test.head())


def tsplot(y, lags=None, title='', figsize=(14, 8)):
    fig = plt.figure(figsize=figsize)
    layout = (2, 2)
    ts_ax = plt.subplot2grid(layout, (0, 0))
    hist_ax = plt.subplot2grid(layout, (0, 1))
    acf_ax = plt.subplot2grid(layout, (1, 0))
    pacf_ax = plt.subplot2grid(layout, (1, 1))

    y.plot(ax=ts_ax)
    ts_ax.set_title(title)
    y.plot(ax=hist_ax, kind='hist', bins=25)
    hist_ax.set_title('Histogram')
    sm.graphics.tsa.plot_acf(y, lags=lags, ax=acf_ax)
    sm.graphics.tsa.plot_pacf(y, lags=lags, ax=pacf_ax)
    [ax.set_xlim(0) for ax in [acf_ax, pacf_ax]]
    sns.despine()
    plt.tight_layout()
    return ts_ax, acf_ax, pacf_ax


tsplot(ts_train, title='A Given Training Series', lags=20)
plt.show()



train_results = sm.tsa.arma_order_select_ic(ts_train, ic=['aic', 'bic'], trend='n', max_ar=4, max_ma=4)

print('AIC', train_results.aic_min_order)
print('BIC', train_results.bic_min_order)

arima200 = sm.tsa.SARIMAX(ts_train, order=(2, 0, 0))# order里边的三个参数p,d,q
model_results = arima200.fit()# fit模型
model_results.plot_diagnostics(figsize=(16, 12))# statsmodels库
plt.show()

完整代码

 

import pandas
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.tsa.stattools import adfuller as ADF
from statsmodels.graphics.tsaplots import plot_pacf
from statsmodels.stats.diagnostic import acorr_ljungbox
from statsmodels.tsa.arima.model import ARIMA
import statsmodels.api as sm
# 读取数据,指定日期为索引列

data = pandas.read_csv(
    'LBMA-GOLD.csv',
    index_col='Date',
    infer_datetime_format=True
)

n_sample = data.shape[0]
n_train = int(0.95 * n_sample) + 1
# 计算训练样本的大小。这里使用 95% 的数据作为训练集,+1 用于确保至少有一个样本在测试集中。
n_forecast = n_sample - n_train
# 计算预测样本的大小。
ts_train = data.iloc[:n_train]['USD (PM)']
# 从时间序列数据框中选择前 n_train 行作为训练样本.
ts_test = data.iloc[n_train:]['USD (PM)']
# 从时间序列数据框中选择从第 n_train 行开始到最后一行的数据作为测试样本,
print(ts_train.shape)
print(ts_test.shape)
print("Training Series:", "\n", ts_train.tail(), "\n")
print("Testing Series:", "\n", ts_test.head())
print(data)

# 确保正常显示负号
plt.rcParams['axes.unicode_minus'] = False
# 绘制原始时间序列的趋势图。
plt.show()
# 绘制原始时间序列的自相关图
has_nan = np.isnan(data).any()
print('has_nan:', has_nan)
data.dropna(inplace=True)
plot_acf(data).show()


# 1 平稳性检测
# 用于格式化ADF(Augmented Dickey-Fuller)平稳性检验的结果,并对数据进行ADF检验。
def tagADF(t):
    # 创建一个空的DataFrame,用于存储ADF测试结果的格式化信息
    result = pandas.DataFrame(index=[
        "Test Statistic Value", "p-value", "Lags Used",
        "Number of Observations Used",
        "Critical Value(1%)", "Critical Value(5%)", "Critical Value(10%)"
    ], columns=['Value']
    )
    # 将ADF测试结果中的各项信息填入DataFrame中
    result['Value']['Test Statistic Value'] = t[0]  # 测试统计值
    result['Value']['p-value'] = t[1]  # p-value值
    result['Value']['Lags Used'] = t[2]  # 使用的滞后阶数
    result['Value']['Number of Observations Used'] = t[3]  # 使用的观测值数量
    # 从Critical Value中提取不同置信水平下的临界值
    result['Value']['Critical Value(1%)'] = t[4]['1%']
    result['Value']['Critical Value(5%)'] = t[4]['5%']
    result['Value']['Critical Value(10%)'] = t[4]['10%']

    return result


# 打印数据类型和ADF检验的结果。
# print(type(data))

print('ADF test result:', tagADF(ADF(data)))
# 平稳判断:
# 得到统计量大于三个置信度(1%,5%,10%)临界统计值,p值显著大于0.05,为非平稳序列。
# 得到的统计量显著小于3个置信度(1%,5%,10%)的临界统计值时,为平稳序列

# 2 差分,一般一阶差分就可以
D_data = data.diff(1).dropna()
# 这一行代码执行了一阶差分操作,通过diff(1)方法计算每个时间点和前一个时间点之间的差分。
# dropna()用于移除结果中的缺失值(NaN)。
D_data.columns = ['difference']
# 为差分后的数据框添加一个列名,以便后续的可视化。
# 差分图查看
D_data.plot()
plt.show()
# 自相关图
plot_acf(D_data).show()
# 自相关图显示了时间序列与其自身在不同滞后阶数上的相关性
plt.show()
# 偏自相关图
plot_pacf(D_data).show()
# 偏自相关图显示了时间序列与其自身在不同滞后阶数上的偏相关性

# 3 再次作平稳性检测
print('ADF test result after difference:', tagADF(ADF(D_data['difference'])))

# 4 白噪声检验
# 返回统计量和p值
print('white noise test result of the difference:', acorr_ljungbox(D_data, lags=1))
# 设置 lags 为 1 表示进行一阶滞后的检验。
# 通常关注的是 p-value 是否小于显著性水平(通常设为 0.05)。
# 如果 p-value 较小,可以拒绝原假设,即认为时间序列存在显著的自相关性。
# 结果分别为stat值(统计量)和p-value值


# 5 p,q定阶
train_results = sm.tsa.arma_order_select_ic(ts_train, ic=['aic', 'bic'], trend='n', max_ar=4, max_ma=4)
print('train_results', train_results)
print('AIC', train_results.aic_min_order)
print('BIC', train_results.bic_min_order)
p = train_results.aic_min_order
q = train_results.bic_min_order
# 6 建立模型和预测
model = ARIMA(data, order=(p, 1, q)).fit()
# 使用先前选择的最优 (p, d, q) 值来建立 ARIMA 模型。
# order 参数是一个包含 (p, d, q) 的元组,指定了 ARIMA 模型的阶数。
# fit() 方法用于拟合模型。
print(type(model))
# 给出一份模型报告
print(model.summary())
# 作为期10天的预测,返回预测结果、标准误差、置信区间。
print(model.forecast(n_forecast))

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值