Entenda a previsão de série temporal Python em um artigo (etapas, modelos, código python)

A previsão inclui ajuste numérico, regressão linear, regressão múltipla, séries temporais, rede neural, etc.

Para previsão de série temporal univariada: os modelos incluem AR, MA, ARMA e ARIMA. De modo geral, ARIMA pode representar todos.

Links de dados e código: dados e arquivos Jupyter

Tomemos a previsão de mudanças no PIB dos EUA nos próximos 10 anos como uma coluna:

Índice

O primeiro passo é importar dados

A segunda etapa é realizar a análise de sequência estacionária

O terceiro passo é realizar a operação de diferença da sequência instável

A quarta etapa é realizar a ordenação do modelo, seleção e ajuste do modelo.

Etapa 5: realizar a análise dos resultados do modelo e o teste do modelo 

Etapa 6: fazer previsões de modelo

PS: Comparação de AUTO-ARIMA automatizado


O fluxograma ARIMA é o seguinte:

O primeiro passo é importar os dados:


    Observe os dados das variáveis ​​​​a serem previstas, remova dados diversos e obtenha os atributos dos próprios dados, como tamanho, tipo, etc.

import pandas as pd,numpy as np
from matplotlib import pyplot as plt

#加载数据,sheet_name指定excel表的数据页面,header指定指标column属性,loc去除杂数据,可选:parse_dates=[''],index_col='',use_cols=['']
df=pd.read_excel('./data/time1.xls',sheet_name='数据',header=1).loc[1:,:]

#DateFrame索引重置
df=df.set_index('DATE')#df.set_index('DATE',inplace=True)

#查看前5行
print(df.head(5))

#查看列索引
print(df.columns)#print(df.keys())

#查看表的维度
print(df.shape)

#查看行索引
print(df.index)

#np.array()  array1.reshape(,)  df.values.astype(int).tolist() np.vstack((a1,a2))  np.hstack((a1,a2))  round()  iloc

#时间索引拆分
# dates=pd.date_range(start='1991-01-01',end='2007-08-01',freq='MS')#日期取值和格式转换,MS代表每月第一天
# years=[d.strftime('%Y-%m') for d in dates][0:200:25]
# years.append('2007-09')

O resultado é o seguinte:

A segunda etapa é realizar a análise de sequência estacionária:


    A série temporal que estudamos e analisamos, ou seja, dados em painel, só tem importância para a pesquisa se for amplamente estacionária. Se for uma sequência não estacionária, sua diferença precisa ser convertida em uma sequência estacionária antes que a análise possa ser realizada. Para sequências estritamente estacionárias, as propriedades não mudam, ou seja, a sequência é uma sequência de ruído branco, tal sequência não tem significado de pesquisa.
    
    Portanto, depois de obter os dados da série temporal do PIB aqui, primeiro realizamos um teste de ruído branco na sequência original, usando a estatística LB. Se o valor p for menor que o nível significativo a = 0,05, a sequência original é considerada um sequência de ruído não branco, o que é significativo para a pesquisa.
    
    Em seguida, desenhe um diagrama de série temporal e julgue subjetivamente a estacionariedade da série temporal do PIB. Se houver uma tendência óbvia, é uma série não estacionária. Se não houver uma tendência óbvia ou for difícil para você julgar a estacionariedade, então você precisa usar a unidade ADF.As estatísticas raiz são usadas para ajudar a avaliar se ela está estacionária. Para a estatística ADF, você pode comparar o valor da estatística para julgar, ou você pode comparar o valor p para julgar. Por exemplo, quando o nível de significância é a = 0,05, se a estatística ADF da sua variável for menor que a ADF estatística para a = 0,05, então significa que a série temporal correspondente à variável é uma série estacionária; um método mais direto é apenas julgar que se o valor p da variável for menor que 0,05, também se diz que é uma série estacionária.

   

plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
plt.rc('font',family='SimHei')
plt.style.use('ggplot')

df.plot(secondary_y=['CS','INV','P_GDP','GOV_NET'])#单个指标时序图 df['CS'].plot()
plt.xlabel('Date')
plt.ylabel('Value')
plt.title('Time Series Plot')
#plt.grid()
plt.show()

from statsmodels.tsa.stattools import adfuller# ADF检验

for i in df.columns:
    data=df[i]
    print(f'{i}的单位根检验')
    result = adfuller(data)#默认情况下,regression参数为'c',表示使用包含截距项的回归模型。
    print('ADF Statistic: %f' % result[0])#ADF统计量
    print('p-value: %f' % result[1])#p值
    print('Critical Values:')#在置信水平下的临界值
    for key, value in result[4].items():
        print('\t%s: %.3f' % (key, value))
    print()

Resultados do código:


A terceira etapa é realizar a operação de diferença da sequência não estacionária:


    Geralmente, a diferença da série temporal não excederá a terceira ordem. Execute a operação de diferença nos dados originais e repita a segunda etapa do diagrama de série temporal e a operação de teste de raiz unitária ADF. Se for descoberto que a sequência diferenciada é uma sequência estacionária, registre a ordem da diferença. Aqui, a ordem da diferença do PIB é 1, passando no teste da sequência estacionária. Execute novamente um teste de ruído branco na sequência diferenciada. Se passar como uma sequência de ruído não branco, prossiga para a próxima etapa.
    

#差分时序图
diff_data = df.diff(periods=1).dropna()# 创建一阶差分的时间序列,加上dropna()后续不需要执行[1:]
#print(diff_data)

diff_data.plot()
plt.xlabel('Date')
plt.ylabel('Value')
plt.title('Time Series Plot')
#plt.grid()
plt.show()

for i in diff_data.columns:
    data=diff_data[i]#Series索引选取,一阶差分第一个数据为NA
    
    print(f'{i}的单位根检验')
    result = adfuller(data)#结果对应位置的数据需要自己判断是什么含义
    print('ADF Statistic: %f' % result[0])#ADF统计量
    print('p-value: %f' % result[1])#p值
    print('Critical Values:')#在置信水平下的临界值
    for key, value in result[4].items():
        print('\t%s: %.3f' % (key, value))
    print()

from statsmodels.stats.diagnostic import acorr_ljungbox

#这里为一阶差分后的平稳序列进行白噪声检验,lags为1,否则lags为0,这里拿上述的GDP指标进行
lags = [1,4,8,16,32]

print('差分序列的白噪声检验结果为:'+'\n',acorr_ljungbox(diff_data['GDP'], lags))  # 返回统计量和p值,这里的lags对应差分阶数

print('原始数据序列的白噪声检验结果为:'+'\n',acorr_ljungbox(df['GDP'], lags))

Os resultados do código são os seguintes:

A quarta etapa é realizar a ordenação do modelo, seleção e ajuste do modelo:


    Para determinar a ordem do modelo, primeiro usamos o diagrama de autocorrelação e o diagrama de autocorrelação parcial para fazer um julgamento preliminar: Coeficiente de autocorrelação Coeficiente de autocorrelação parcial
           Diferença
    AR Tailing truncamento de ordem p 0
    MA truncamento de ordem q Tailing 0
    ARMA tailing Tailing 0
    ARIMA tailing Tailing d
    Resumindo, todos os modelos acima podem ser implementados usando ARIMA (p, d, q).AR, MA e ARMA são todos casos especiais de ARIMA.
    
    Julgamentos empíricos sobre cauda e truncamento:
    Cauda: o exponencial negativo converge monotonicamente para 0 ou exibe um decaimento de cosseno
    ; truncamento: decai rapidamente para 0 e flutua perto de 0;
    o truncamento se aproxima de 0 mais rapidamente do que a cauda se aproxima de 0. O truncamento não aumentará significativamente nas fases posteriores
    
       

        Depois de usar o gráfico para fazer um julgamento preliminar, se ainda não for possível determinar a ordem do modelo com precisão, você poderá usar os critérios AIC e BIC para auxiliar no julgamento ou na otimização. Por exemplo, julgo que a ordem do modelo pode ser 2, 1, 4 ou 3, 1, 3. No momento, não tenho certeza. Você pode fazer ARIMA (2, 1, 4) primeiro. Se você descubra que o modelo subsequente é significativo Se o teste e o teste de parâmetro forem aprovados, você poderá usar ARIMA(2,1,4) diretamente para fazer previsões e tirar conclusões, mas também poderá tentar várias ordens próximas, como ARIMA( 3,1,3), ARIMA (2,1,3) e assim por diante também passaram, mas os valores AIC e BIC de ARIMA (3,1,3) são os menores, ou seja, o modelo possui maior ajuste precisão e é um modelo relativamente ótimo. , esta etapa é a otimização do modelo.

    
    A configuração e otimização da ordem aqui são implementadas em Python da seguinte forma: de q a (comprimento dos dados/10), de p a 0 a (comprimento dos dados/10) e geralmente a ordem não excederá (comprimento dos dados/10); Então execute o ajuste do modelo q*p e use os resultados do ajuste do modelo para comparar os valores de AIC e BIC. Quanto menor o valor do BIC, menor o modelo é o modelo relativamente ideal e, em seguida, use a ordem do modelo como o modelo final. A ordem da combinação.

    

#生成自相关图,偏自相关图
from statsmodels.graphics.tsaplots import plot_acf,plot_pacf

fig, ax = plt.subplots(figsize=(5, 4))
plot_acf(diff_data['GDP'],ax=ax)#可以换成df的数据,这里用一阶差分数据得到平稳序列
    
ax.set_title("Autocorrelation Plot")
lags=list(range(24))
ax.set_xticks(lags)#这里把x坐标刻度变更精细,加网格图更方便,xticklabels替换标签
ax.set_xlabel("Lag")
ax.set_ylabel("Autocorrelation")
ax.grid(alpha=0.5)
plt.legend(['GDP'])#这里区别直接放入df.columns[i],如果是多字符如‘CS’,这样会被认为是一个序列,拆成C和S的图例
plt.show()
    
fig, ax = plt.subplots(figsize=(5, 4))
lags=list(range(24))
ax.set_xticks(lags)#这里把x坐标刻度变更精细,加网格图更方便,xticklabels替换标签
plot_pacf(diff_data['GDP'], ax=ax,method='ywm')#ywm替换默认的yw,去除警告
ax.set_xlabel('Lags')
ax.set_ylabel('Partial Autocorrelation')
ax.grid(alpha=0.5)
plt.legend(['GDP'])
plt.show()

import warnings
warnings.filterwarnings("ignore")
import statsmodels.api as sm


#diff_data['GDP'].values.astype(float),这里发现Serise的dtype为object,模型用的应该为float或者int类型,需要注意原数据的数据类型是否一致

Min=float('inf')
for i in range(0,6):#AIC,BIC最小找到p,q阶数来定阶,从0开始定阶是否可行??
    for j in range(0,6):
        result=sm.tsa.ARIMA(df['GDP'].values.astype(float),order=(i,1,j)).fit()
        print([i,j,result.aic,result.bic])
        if result.bic<Min:
            Min=result.bic
            best_pq=[i,j,result.aic,result.bic]
print(f'最优定阶为{best_pq}')

Resultados do código:


A quinta etapa é conduzir a análise dos resultados do modelo e o teste do modelo. 

    O teste de modelo é dividido em teste de parâmetros de modelo e teste de significância de modelo.

    Teste de significância do modelo: ou seja, o teste de ruído branco do resíduo. Se o resíduo for uma sequência de ruído branco, ou seja, a informação da sequência original é totalmente extraída. Observe a estatística LB. A estatística LB do modelo resulta em python é a estatística LB do resíduo. , se o valor p for menor que 0,05, é uma sequência de ruído não branco. Se o valor p for maior que 0,05, significa que o resíduo é uma sequência de ruído branco. Este é o resultado que queremos. Aqui você pode retirar o valor residual do modelo separadamente, desenhar você mesmo o diagrama de série temporal residual, o diagrama QQ, o diagrama de distribuição normal ou realizar você mesmo um teste de ruído branco para auxiliar no julgamento. A sequência de ruído branco obedece à distribuição normal, o diagrama de série temporal flutua suavemente e os pontos numéricos no diagrama QQ estão próximos da diagonal.
    
    Teste de parâmetros do modelo: teste se cada parâmetro desconhecido é significativamente 0 e teste se o modelo é o mais simplificado. Se o parâmetro não for significativamente diferente de zero, ele poderá ser eliminado do modelo ajustado e ver a estatística t.
    
    Explicação parcial dos resultados do modelo:
    const: termo constante       
    ar.L1: coeficiente de termo autoregressivo
    ma.L1: coeficiente de termo médio móvel
    sigma2: variância
    P>|z| sob cada parâmetro, se for menor que a=0,05, a hipótese nula é rejeitado, considerando-se que os parâmetros são significativamente diferentes de zero, ou seja, não há necessidade de simplificação do modelo.
    Ljung-Box: estatística LB. Deve-se notar aqui que o valor P de LB precisa ser> 0,95, ou seja, a sequência residual é considerada uma sequência de ruído branco, e se for menor que 0,05, é uma sequência residual. sequência de ruído não branco.
    Jarque-Bera: Resultados do   
    teste de heterocedasticidade da estatística JB indicam um caso estável de variância

Result=sm.tsa.ARIMA(df['GDP'].values.astype(float),order=(best_pq[0],1,best_pq[1])).fit()
print(Result.summary())  #显示模型的所有信息

print(len(Result.resid))
#print(Result.resid)这里观察到残差的第一项为原数据的1239.5,即差分数据不管第一项,这里需要调整残差的观测

#这里就可以观察到原始模型的结果LB统计量和这里的白噪声检验是一致的,p>0.05,即认为残差为白噪声序列,原序列信息提取充分。
lags = [1,4,8,16,32]
print('差分序列的白噪声检验结果为:'+'\n',acorr_ljungbox(Result.resid[1:], lags))

## 查看模型的拟合残差分布
fig = plt.figure(figsize=(12,5))
ax = fig.add_subplot(1,2,1)
plt.plot(Result.resid[1:])
plt.title("ARIMA(2,1,1)残差曲线")

## 检查残差是否符合正太分布
ax = fig.add_subplot(1,2,2)
sm.qqplot(Result.resid[1:], line='q', ax=ax)
plt.title("ARIMA(2,1,0)残差Q-Q图")
plt.tight_layout()
plt.show()

fig = plt.figure(figsize=(12,5))
Residual=pd.DataFrame(Result.resid[1:])
Residual.plot(kind='kde', title='密度')
plt.legend('')
plt.show()

O resultado do código é:

  

A sexta etapa é realizar a previsão do modelo:


    A previsão do modelo consiste em usar o modelo relativamente ideal mencionado acima para prever os valores correspondentes às variáveis ​​​​de dados originais em momentos subsequentes.
    Observe que em python, se a função de previsão prevê dados diferenciais, preste atenção ao início do início e ao término do fim. Por exemplo, os dados de diferença de primeira ordem começam a partir do segundo valor de observação, e o erro residual correspondente também é o mesmo
    ... Ao desenhar posteriormente, você precisa prestar atenção ao desenho do modelo diferencial.

#预测,绘制原序列和预测序列值对比图

Predict=Result.predict(start=1, end=len(df['GDP'])-1+1+10); #不加参数默认0到n-1,要加预测个数在end后面N-1+预测n即可
#如果是一阶差分的序列预测,第一个数据已经差分消去了,应该start从第二个观测数据开始,即n=1;如果是0阶,则不需要按默认0到n-1

print(list(zip(range(193,203),Predict[-10:])))#打印预测值

plt.figure()
plt.plot(range(193),df['GDP'].values)#'o-k'
plt.plot(range(193+10),Predict)#'P--'
plt.legend(('原始观测值','预测值'))
plt.xticks(list(range(0,203,10)),rotation=90)
plt.show()

plt.figure()
plt.plot(range(193),df['GDP'].values)#'o-k'
plt.plot(range(192,193+10),Predict[-11:])#'P--'#接着原数据最后一个,进行拟合预测表示
plt.legend(('原始观测值','预测值'))
plt.xticks(list(range(0,203,10)),rotation=90)
plt.show()

Resultados do código:

PS: Comparação de AUTO-ARIMA automatizado

import pmdarima as pm
# ## 自动搜索合适的参数
model = pm.auto_arima(df['GDP'].values,
                      start_p=1, start_q=1, # p,q的开始值
                      max_p=12, max_q=12, # 最大的p和q
                      d = 0,            # 寻找ARMA模型参数
                      m=1,              # 序列的周期
                      seasonal=False,   # 没有季节性趋势
                      trace=True,error_action='ignore',  
                      suppress_warnings=True, stepwise=True)
 
print(model.summary())

Não estudei essa área a fundo. O método automático tem vantagens e desvantagens, mas também pode fornecer uma ideia para escrever código.

Acho que você gosta

Origin blog.csdn.net/weixin_56115549/article/details/130930187
Recomendado
Clasificación