Python 中的 Auto ARIMA 导致趋势预测拟合效果差。

5

我是ARIMA的新手,正在尝试使用auto ARIMA在Python中对数据集进行建模。 我使用auto-ARIMA,因为我相信它会更好地定义p、d和q的值,但结果很差,我需要一些指导。 请查看下面我可重现的尝试:

尝试如下:

    # DEPENDENCIES
    import pandas as pd 
    import numpy as np 
    import matplotlib.pyplot as plt
    import pmdarima as pm 
    from pmdarima.model_selection import train_test_split 
    from statsmodels.tsa.stattools import adfuller
    from pmdarima.arima import ADFTest
    from pmdarima import auto_arima
    from sklearn.metrics import r2_score 

# CREATE DATA
data_plot = pd.DataFrame(data removed)

# SET INDEX
data_plot['date_index'] = pd.to_datetime(data_plot['date']
data_plot.set_index('date_index', inplace=True)

# CREATE ARIMA DATASET
arima_data = data_plot[['value']]
arima_data

# PLOT DATA
arima_data['value'].plot(figsize=(7,4))

以上步骤会生成一个数据集,应该长这样。 在此输入图像描述
# Dicky Fuller test for stationarity 
adf_test = ADFTest(alpha = 0.05)
adf_test.should_diff(arima_data)

结果为0.9867,表示数据是非平稳的,需要在自动ARIMA过程中适当地进行差分处理。

# Assign training and test subsets - 80:20 split 

print('Dataset dimensions;', arima_data.shape)
train_data = arima_data[:-24]
test_data = arima_data[-24:]
print('Training data dimension:', train_data.shape, round((len(train_data)/len(arima_data)*100),2),'% of dataset')
print('Test data dimension:', test_data.shape, round((len(train_data)/len(arima_data)*100),2),'% of dataset')

# Plot training & test data
plt.plot(train_data)
plt.plot(test_data)

enter image description here

 # Run auto arima
    arima_model = auto_arima(train_data, start_p=0, d=1, start_q=0,
    max_p=5, max_d=5, max_q=5,
    start_P=0, D=1, start_Q=0, max_P=5, max_D=5,
    max_Q=5, m=12, seasonal=True,
    stationary=False,
    error_action='warn', trace=True,
    suppress_warnings=True, stepwise=True,
    random_state=20, n_fits=50)
        
    print(arima_model.aic())

模型输出表明最佳模型为 'ARIMA(1,1,1)(0,1,0)[12]',其 AIC 为 1725.35484

#Store predicted values and view resultant df

prediction = pd.DataFrame(arima_model.predict(n_periods=25), index=test_data.index)
prediction.columns = ['predicted_value']
prediction

# Plot prediction against test and training trends 

plt.figure(figsize=(7,4))
plt.plot(train_data, label="Training")
plt.plot(test_data, label="Test")
plt.plot(prediction, label="Predicted")
plt.legend(loc='upper right')
plt.show()

enter image description here

# Finding r2 model score
    test_data['predicted_value'] = prediction 
    r2_score(test_data['value'], test_data['predicted_value'])

结果:-6.985

2个回答

2

ARIMA模型在应用于数据之前需要检查其假设。其中之一是数据需要是平稳的,即不应该有趋势或季节性。您可以通过绘图来检查趋势,在您的图表中如果出现上升趋势,则说明存在趋势。

1. 您可以从图表中检查季节性,或使用Dicker Fuller测试来检查假设。

import statsmodels.tsa.stattools as ts
ts.adfuller(data.col) 

请查看这个答案,如何执行和读取ad fuller测试已经被很好地解释了。 如何解释adfuller测试结果?

  1. 始终检查ACF和PACF图,并查看哪些滞后超出了限制,显示自相关性。检查是否存在平稳性。

正如Jose所解释的那样,可以进行差分来使数据平稳。

SARIMA算法考虑了季节性组件(p,d,q)和(S,P',D',Q')以及外生变量。


0

auto_arima 是你们开发的方法吗?这取决于你如何区分和处理。你是否检查了自相关和偏自相关来确定重复的时间滞后?

此外,似乎每年都有一些季节性模式,如果你还没有尝试过,可以尝试使用 SARIMA 模型。

要尝试 SARIMA 模型,你需要:

  1. 使数据平稳化,在这种情况下,通过差分可以将移动平均值转换为平稳值。
data_stationarized = train_data.diff()[1:]
  • 检查自相关性和偏自相关性以检查季节性。 您可以使用statsmodels库来完成。
  • import statsmodels.api as sm
    sm.graphics.tsa.plot_acf(data_stationarized);
    

    enter image description here

    你可以看到最显著的旗帜是第十二个旗帜,因此数据的粒度是按月计算的,这意味着每12个月有明显的季节性模式。

    我们可以检查偏自相关图以确认它:

    sm.graphics.tsa.plot_pacf(data_stationarized);
    

    enter image description here

    再次提到最显著的标志是第十二个。

    1. 使用季节性阶数为12来拟合模型。还有更多参数需要解释,可以进行调整以获得更好的结果,但这篇文章会变得非常冗长。
    model = sm.tsa.SARIMAX(endog=train_data, order=(2,0,0), seasonal_order=(2,0,0,12))
    model_fit = model.fit()
    
    1. 评估结果
    from sklearn.metrics import mean_squared_error
    
    y_pred = model_fit.forecast(steps=24)
    
    # when squared=False then is equals to RMSE
    mean_squared_error(y_true=test_data.values, y_pred=y_pred, squared=False)
    

    这将输出12063.88,您可以使用它更严格地比较不同的结果。

    进行图形检查:

    prediction = pd.DataFrame(model_fit.forecast(steps=25), index=test_data.index)
    prediction.columns = ['predicted_value']
    prediction
    
    # Plot prediction against test and training trends
    
    plt.figure(figsize=(7,4))
    plt.plot(train_data, label="Training")
    plt.plot(test_data, label="Test")
    plt.plot(prediction, label="Predicted")
    plt.legend(loc='upper right')
    plt.xticks([])
    plt.yticks([])
    plt.show();
    

    enter image description here

    现在您可以看到预测结果越来越接近预期值。

    您可以继续微调顺序和季节性顺序以获得更好的结果,我建议查看statsmodel文档

    另一个建议是分析残差的自相关和偏自相关,以检查模型是否捕捉到所有模式。您可以在model_fit对象中找到它们。


    不,auto_arima是一个Python库,但由于某些原因我没有将其包含在导入/依赖项列表中。我将尝试SARIMA,谢谢。 - jimiclapton
    1
    @jimiclapton 我已经编辑了答案以更好地帮助你,如果你认为我对你有所帮助,可以给我一个赞 :) - Jose
    谢谢你的帮助,Jose。非常高兴接受这个答案。如果您可以在您的回答中也删除图表上y轴的值,我将不胜感激。 - jimiclapton
    Jose,你提到了季节性顺序为12,但你没有说明如何得出p、d和q的值为“2,0,0”。你能详细解释一下吗? - jimiclapton
    @jimiclapton 请查看此链接 https://analyticsindiamag.com/quick-way-to-find-p-d-and-q-values-for-arima/,其中详细解释了如何快速找到ARIMA模型的P、D和Q值。 - Jose
    显示剩余5条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接