使用statsmodels进行预测

7
我有一个包含五年时间序列的.csv文件,分辨率为每小时(商品价格)。基于历史数据,我想创建第六年价格的预测。
我已经阅读了一些关于这些过程的文章,并且基本上根据那里发布的代码编写了我的代码,因为我对Python(特别是statsmodels)和统计知识的了解非常有限。
以下是链接,供有兴趣的人使用:

http://www.seanabu.com/2016/03/22/time-series-seasonal-ARIMA-model-in-python/

http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/

首先,这里是一个.csv文件的样本。在这种情况下,数据以每月的分辨率显示,这不是真实数据,只是随机选择的数字,以便在此处提供示例(在这种情况下,我希望一年足以开发第二年的预测;如果不行,则完整的csv文件可用):

              Price
2011-01-31    32.21
2011-02-28    28.32
2011-03-31    27.12
2011-04-30    29.56
2011-05-31    31.98
2011-06-30    26.25
2011-07-31    24.75
2011-08-31    25.56
2011-09-30    26.68
2011-10-31    29.12
2011-11-30    33.87
2011-12-31    35.45

我的当前进度如下:

读取输入文件并将日期列设置为日期时间索引后,使用以下脚本开发可用数据的预测:

model = sm.tsa.ARIMA(df['Price'].iloc[1:], order=(1, 0, 0))  
results = model.fit(disp=-1)  
df['Forecast'] = results.fittedvalues  
df[['Price', 'Forecast']].plot(figsize=(16, 12))  

,它会产生以下输出:

5-year timeseries, hourly resolution data

现在,正如我所说的那样,我没有统计技能,也不知道如何得出这个输出(基本上,更改第一行中的顺序属性会更改输出),但“实际”预测看起来相当不错,我想将其延长一年(2016年)。
为了做到这一点,在数据框中创建了额外的行,如下所示:
start = datetime.datetime.strptime("2016-01-01", "%Y-%m-%d")
date_list = pd.date_range('2016-01-01', freq='1D', periods=366)
future = pd.DataFrame(index=date_list, columns= df.columns)
data = pd.concat([df, future])

最后,当我使用statsmodels的.predict函数时:
data['Forecast'] = results.predict(start = 1825, end = 2192, dynamic= True)  
data[['Price', 'Forecast']].plot(figsize=(12, 8))

我得到的预测结果是一条直线(见下文),这似乎完全不像一个预测。此外,如果我将范围扩展到整个6年时间跨度(2011-2016年),现在从第1825天到第2192天(2016年),预测线在整个期间都是一条直线。
我还尝试使用“statsmodels.tsa.statespace.sarimax.SARIMAX.predict”方法,该方法考虑了季节变化(在这种情况下是有意义的),但我遇到了关于“模块”没有属性“SARIMAX”的错误。但这是次要问题,如果需要可以深入讨论。

forecast output

我感觉自己在某些地方失去了掌控,但我不知道具体是哪里。谢谢阅读。干杯!


我有一个类似的问题。你能解决吗?谢谢。 - kthouz
没有,我还没有解决它。由于工作中的某些干扰,我在某个时候放弃了它,从未回到这个问题上来。 - davidr
3个回答

4

ARIMA(1,0,0)是一个一阶自回归模型。因此,它是遵循以下公式的模型:

enter image description here

那意味着,在时间段t内的值等于某个常数(phi_0)加上通过拟合ARMA模型得出的值(phi_1),乘以前一时期r_(t-1)的值,再加上白噪声误差项(a_t)。您的模型只有一个周期的记忆,因此当前预测完全由前一个周期的值决定。这不是一个非常复杂的模型;它没有对所有先前的值进行任何花哨的处理。它只是取昨天的价格,乘以某个值并添加一个常数。您应该期望它很快达到平衡状态,然后永远停留在那里。顶部图片预测看起来非常好的原因是它只显示了数百个新周期开始的1周期预测。它不会显示像您可能认为的那样长期的预测。看一下您发送的链接:

http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/

请阅读他讨论为什么这个模型无法给您想要的结果的部分。
“乍一看,似乎这个模型表现得非常好。但是尽管预测看起来非常接近(毕竟线条几乎无法区分),请记住我们使用了未差分的系列!相对于总绝对值,指数每天只波动很小的百分比。我们真正想要的是预测第一差分或日常变化。我们可以使用差分系列重新运行模型,或者在ARIMA模型中添加一个“I”项(导致(1,1,0)模型),这应该能够达到同样的效果。让我们尝试使用差分系列。”
要做你正在尝试做的事情,你需要更多地研究这些模型,并弄清楚如何格式化你的数据以及哪种模型适合。最重要的是知道你认为数据中包含的信息。你的模型目前正在尝试说:“今天价格是45美元。明天的价格会是多少?”就这样。它没有关于动量、波动率等方面的任何信息。这不足以支持太多。

3

看起来您正在使用一个不支持SARIMAX的旧版本statsmodels。您需要安装最新发布的版本0.8.0,请参见http://statsmodels.sourceforge.net/devel/install.html

我正在使用Anaconda并通过pip安装。

pip install -U statsmodels

SARIMAX模型的结果类具有许多有用的方法,包括预测。
data['Forecast'] = results.forecast(100)

将使用您的模型预测未来100步。

1
如果你想要进行样本外预测,并且你有外生变量,那么你首先需要提供这些变量的预测值(可能你并没有这些预测值)。 - fccoelho
向Geoff D和fccoelho致敬。文档中的语言很令人困惑。看到这个终于让它变得有意义了。 - JJFord3

-1

在进行预测时,尝试将dynamic参数设置为False


1
你能否详细阐述你的答案,而不是提供一行答案。这样做无法帮助OP进行故障排除。 - Joe Ferndz

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