时间序列预测模型既可以进行预测,也可以为这些预测提供预测区间。
预测区间提供对实际观测值的上限和下限预期。这对于评估预测的实际可能结果范围以及更好地理解模型的技能非常有用。
在本教程中,您将了解如何使用 Python 为时间序列预测计算和解释预测区间。
具体来说,您将学习
- 如何使用 ARIMA 模型进行预测并收集预测诊断信息。
- 如何计算和报告预测的预测区间。
- 如何解释预测的预测区间并配置不同的区间。
开始您的项目,阅读我的新书《Python 时间序列预测入门》,其中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。
- 2019 年 4 月更新:更新了数据集链接。
- 更新于 2019 年 6 月:已从预测区间更改为预测区间。
- 2019年8月更新:更新了数据加载以使用新的API。
- **2020 年 12 月更新**:针对 API 更改更新了建模。

使用 Python 的预测区间理解时间序列预测的不确定性
照片来源:Bernard Spragg. NZ,部分权利保留。
ARIMA 预测
statsmodels Python 库中的 ARIMA 实现可用于拟合 ARIMA 模型。
它返回一个 ARIMAResults 对象。此对象提供 get_forecast() 函数,该函数可用于预测训练数据末尾之后下一个时间步的值,并默认为预测下一个时间步。
假设我们只预测下一个时间步,get_forecast() 函数将返回一个 PredictionResults 对象,其中包含有用的信息,例如:
- predicted_mean。以训练时间序列单位表示的预测值。
- mean_se。模型的标准误差。
- conf_int。给定 alpha 水平的预测区间。
在本教程中,我们将更好地理解 ARIMA 预测提供的预测区间。
在我们开始之前,首先来看一下我们将用于本教程背景的每日女性出生数据集。
停止以**慢速**学习时间序列预测!
参加我的免费7天电子邮件课程,了解如何入门(附带示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
每日女性出生数据集
此数据集描述了 1959 年加利福尼亚州每日女性出生人数。
单位是计数,共有 365 个观测值。数据集的来源归功于 Newton (1988)。
下载数据集并将其保存在当前工作目录中,文件名为“daily-total-female-births.csv”。
下面的示例加载并绘制了数据集。
1 2 3 4 5 |
from pandas import read_csv from matplotlib import pyplot series = read_csv('daily-total-female-births.csv', header=0, index_col=0) series.plot() pyplot.show() |
运行示例将加载数据集并将其绘制为折线图。

每日女性出生数据集
预测区间
在本节中,我们将训练一个 ARIMA 模型,使用它进行预测,并检查预测区间。
首先,我们将训练数据集分割为训练集和测试集。几乎所有观测值都将用于训练,我们将最后一个观测值保留为测试数据集,以便进行预测。
训练了一个 ARIMA(5,1,1) 模型。这不是该问题的最优模型,仅为演示目的而选择了一个不错的模型。
然后,通过调用 get_forecast() 函数,使用训练好的模型进行预测。然后打印预测结果。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 总结 ARIMA 预测的置信区间 from pandas import read_csv from statsmodels.tsa.arima.model import ARIMA # 加载数据集 series = read_csv('daily-total-female-births.csv', header=0, index_col=0, parse_dates=True, squeeze=True) # 拆分为训练集和测试集 X = series.values X = X.astype('float32') size = len(X) - 1 train, test = X[0:size], X[size:] # 拟合 ARIMA 模型 model = ARIMA(train, order=(5,1,1)) model_fit = model.fit() # 预测 result = model_fit.get_forecast() # 总结预测和置信区间 print('Expected: %.3f' % result.predicted_mean) print('Forecast: %.3f' % test[0]) print('Standard Error: %.3f' % result.se_mean) ci = result.conf_int(0.05) print('95% Interval: %.3f to %.3f' % (ci[0,0], ci[0,1])) |
运行示例将打印测试集的预期值,然后是预测值的预测值、标准误差和预测区间。
1 2 3 4 |
Expected: 45.149 Forecast: 50.000 Standard Error: 7.009 95% Interval: 31.413 to 58.886 |
解释预测区间
get_forecast() 函数允许指定预测区间。
PredictionResult 上的 conf_int() 函数的 alpha 参数指定了预测水平。
alpha 为 0.05 意味着 ARIMA 模型将估计预测值周围的上限和下限,而实际值落在此范围之外的概率仅为 5%。
换句话说,95% 的预测区间表明实际观测值很可能落在该范围内。
在上例中,预测值为 45.149。95% 的预测区间表明实际观测值很可能落在 31.413 到 58.886 之间的值范围内。
实际观测值为 50.0,在该范围内。
我们可以通过几种方式来缩小可能值的范围:
- 我们可以要求一个更窄的范围,但会增加实际观测值超出范围的统计可能性。
- 我们可以开发一个具有更强预测能力的模型,从而做出更准确的预测。
此外,预测区间也受模型假设的限制,例如模型误差的分布符合具有零均值的(例如白噪声)高斯分布。
扩展上述示例,我们可以为 80%、90%、95% 和 99% 这几个常用的预测区间报告我们的预测。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 总结 ARIMA 预测的多个置信区间 from pandas import read_csv from statsmodels.tsa.arima.model import ARIMA # 加载数据 series = read_csv('daily-total-female-births.csv', header=0, index_col=0, parse_dates=True, squeeze=True) # 将数据分割为训练集和测试集 X = series.values X = X.astype('float32') size = len(X) - 1 train, test = X[0:size], X[size:] # 拟合 ARIMA 模型 model = ARIMA(train, order=(5,1,1)) model_fit = model.fit() result = model_fit.get_forecast() forecast = result.predicted_mean # 总结置信区间 intervals = [0.2, 0.1, 0.05, 0.01] for a in intervals: ci = result.conf_int(alpha=a) print('%.1f%% Confidence Interval: %.3f between %.3f and %.3f' % ((1-a)*100, forecast, ci[0,0], ci[0,1])) |
运行示例将打印每个 alpha 值的预测和预测区间。
我们可以看到每次都获得相同的预测值,并且区间随着我们对“更安全”区间的需求而扩大。我们可以看到,在这种特定情况下,80% 的区间可以很好地捕捉我们的实际值。
1 2 3 4 |
80.0% Confidence Interval: 45.149 between 36.167 and 54.131 90.0% Confidence Interval: 45.149 between 33.621 and 56.677 95.0% Confidence Interval: 45.149 between 31.413 and 58.886 99.0% Confidence Interval: 45.149 between 27.096 and 63.202 |
总结
在本教程中,您了解了如何使用 Python 计算和解释时间序列预测的预测区间。
具体来说,你学到了:
- 如何在使用点预测时报告预测诊断统计信息。
- 如何计算和报告预测的预测区间。
- 如何解释和配置时间序列预测的预测区间。
您对预测区间或本教程有任何疑问吗?
在下面的评论中提出你的问题,我会尽力回答。
你好,Jason。
您的内容很棒!只有一点
您是在谈论“置信区间”还是“预测区间”?有些书籍混淆了这两个术语,但像 Hyndman 这样的时间序列专家进行了有趣的区分。
https://robjhyndman.com/hyndsight/intervals/
谢谢
预测区间。谢谢 Luis!
你好,Jason。
如果我们预测价格时出现负的置信下限该怎么办?由于价格不能为负,有什么方法可以纠正这一点吗?
谢谢!
很好的问题。我暂时不知道这个问题的良好理论。在实践中,您可以强制限制区间以适应您的领域,例如:
lower = max(0, lower)
您是否有其他代码显示如何使用此模型为整个时间序列进行预测并绘制置信区间?
谢谢!
T
上面的帖子确实进行了预测并显示了置信区间。
您可以将其作为您自己数据集的模板。
当我执行网格搜索以获得最佳参数时,如何为 SARIMAX 获取置信区间,同时还要考虑是否存在外生变量(如节假日效应)?
也许在选择配置后,将表现最佳的模型作为独立练习重新拟合和分析。
我认为上面帖子中的方法也适用于 SARIMAX。
很棒的文章。感谢您的所有帖子。我从中学习了很多。
我明白时间序列预测是指当我们预测未来相同的变量时。
X1, X2, X3 -> X4, X5, X6
如果预测的性质不是相同的变量怎么办。
X1, X2, X3 -> Y1, Y2, Y3。
如果我们预测一步,我们会得到类似
X1, X2, X3, Y1 -> Y2, Y3
在这种情况下,我们无法进一步使用该模型进行预测。
您知道这种预测的技术称为什么吗?
我们应该使用 LSTM 直接映射 X->Y,还是有其他技术可用?我正在寻找此问题的定义以及已开发的技术。谢谢!
这称为序列到序列预测。
https://machinelearning.org.cn/sequence-prediction/
嗨,Jason,
非常感谢您的文章!
我有一个关于对数变换与预测区间的问题。
如果我们在改进预测能力时首先对数据进行对数变换,那么当我们回到常规空间时,我们是否也对预测区间进行了对数变换?但是,在对数空间中对对数数据应用 exp 函数,对于小的差异在常规空间中会导致巨大的差异,并且在许多情况下会使上限变得巨大。
所以我的问题是——是否存在任何常见的方法来避免这种副作用?
一切顺利,
Mateusz
预测和区间都假设一个高斯分布,该分布在指数化时会膨胀,正如您所评论的。
哎哟。好问题。
我目前不知道任何好的策略,抱歉。如果您发现任何内容,请告诉我。
Jason 先生:感谢您的文章。这是一篇很棒的文章。关于 plot_predict 调用,我有一个问题。正如我阅读“绘制置信区间”中的代码一样,测试数据实际上并未用于绘图。您认为我们应该从代码中删除测试部分吗?
当然可以。
嗨,Jason,
您是否知道如何使用 LSTM 模型计算时间序列预测的置信区间?
谢谢
Sanchit
您的意思是预测区间吗?这也许会有帮助。
https://machinelearning.org.cn/prediction-intervals-for-machine-learning/
感谢您提供的精彩文章,Jason。
我有兴趣计算 ARIMA 或 SARIMA 模型输出的多个时间步的所有预测值的总和。如果我可以使用您描述的方法估算每个预测值的标准误差,您知道如何计算这些预测值总和的标准误差吗?
您的帮助将不胜感激。
这将需要自定义代码,对您来说应该很有趣。
你到底遇到了什么问题?
我的任务是预测一个月的变量 y,持续 6 个月,并估算这 6 个月的 y 的总和以及相关的置信区间。
我不确定正确的计算方法,因为简单地将每个月的独立标准误差相加并不适用,因为估计的数据点可能相关。
也许可以为预测开发一个线性模型,例如 ARIMA,然后编写一些代码来对预测求和?
我在哪里可以找到关于如何在时间序列中预测区间的定理?
也许是一本像这本一样的教科书
https://amzn.to/2KRuymG
我认为这些是预测区间。
我同意,我已经更新了帖子。谢谢。
你好,Jason 先生。
谢谢你的博客。
它非常有帮助。
但是,我仍然有一个问题。
使用 plot_predict(),我得到了一个短时间序列的预测区间(例如,超过一个预测点)。
如果允许,我想打印预测区间并查看它们的数量。
我该怎么做?
顺便说一下,我使用了 ARMA 模型而不是 ARIMA 模型。
(我自己实现了差分和逆差分过程。
当尝试 ARIMA 模型时,总会出现一些错误。)
所以我需要对预测数据应用差分的逆过程。
期待您的回复!
您可以直接使用相同的函数来预测多个时间步并获取每个时间步的区间 - 只需指定步数即可。
然后,您可以绘制或总结每个预测和区间的結果。
为什么 MSE 不能用于获取长期预测的预测区间?
您可以汇总多个时间步的 MSE 分布,但这将是对预测方差的粗略估计。
嗨,Jason,
谢谢您的工作,它对我帮助很大!
您已经更新了这篇文章,我的一个问题是:在“绘制预测区间”一节中,您使用 statsmodels 计算并绘制了“灰色圆锥”,它返回了一个置信区间。
https://statsmodels.cn/stable/generated/statsmodels.tsa.arima_model.ARIMAResults.forecast.html#statsmodels.tsa.arima_model.ARIMAResults.forecast
在这个特定的示例中,为什么预测区间等于置信区间?
提前非常感谢!
不客气。
他们在 API 中使用“置信区间”来指代“预测区间”。
从技术上讲,它们是不同的。
预测区间
https://machinelearning.org.cn/prediction-intervals-for-machine-learning/
置信区间
https://machinelearning.org.cn/confidence-intervals-for-machine-learning/
在示例中,您有一个标准误差为 6.996,然后用于帮助创建一个时间步后的 95.0% 预测区间为 32.167 和 59.590。如果我想预测两个或更多时间步该怎么办……两个时间步的预测标准误差是多少,我该如何找到它?它是否与一个时间步预测标准误差 6.996 相关?谢谢。
您可以调用 forecast 函数指定所需的步数,并获取这些预测步的预测区间。
我正在使用“statsmodels.tsa.vector_ar.var_model.VAR”包。我想知道拟合的模型是否具有内部函数来获取预测区间(就像 OLS 回归一样)?否则,您的方法是否也适用于 VAR 模型?
也许有,您需要检查 API。
我看到这会给出模型估计的下一个样本外值的预测区间。我正试图为我的ARIMA模型获取整个时间序列的预测区间值——模型每个步骤的预测区间。模型.fit是否会输出预测区间?或者是否有更好的方法来获得它?
您可以通过对数据索引调用forecast()来获得区间,但我不知道它有多大用处。
您能举个语法示例吗?我尝试过但还没有得到任何结果。当我查看statsmodels文档时,看起来forecast只用于样本外预测。结果或结果预测似乎除了模型结果的估计之外没有其他输出。
语法与任何其他预测相同,只需指定从0到len(train)的索引。我猜是这样。
抱歉,我没有能力准备自定义示例。
您是说类似:forecast, stderr, conf = model_fit.forecast()[0:50] 吗?
这给我的结果与不使用索引相同——只有一个时间步。根据文档,forecast() 用于样本外预测,从样本末尾开始。可以指定向前预测的步数,但我想要拟合模型中每个步骤的PI。model_fit.predict() 返回每个步骤的估计值,但没有PI。
https://statsmodels.cn/stable/generated/statsmodels.tsa.arima_model.ARIMAResults.forecast.html
不太对,请参阅此教程,了解如何使用 predict() 和 forecast() 函数
https://machinelearning.org.cn/make-sample-forecasts-arima-python/
将其调整为样本内预测而不是样本外预测。
感谢您不断地对此进行迭代。我确切的问题是如何在样本内使用 forecast() 函数。您共享的示例/链接是针对样本外的。您如何将 forecast() 应用于样本内?
也许 forecast() 只支持样本外,因为参数“steps”是相对于训练样本末尾的。
也许您可以使用 predict()?也许API中还有其他函数可以使用?
如何将X轴标签更改为日期而不是天数?
您可能需要查阅matplotlib的API,我暂时不记得了。
当我使用statsmodels包及其ARIMA来拟合时间序列数据时,预测会随着多步预测而变得更加平稳,例如,如果最后一个观测值为x(t),那么预测的x(t+1)和x(t+2)看起来是合理的,但在x(t+10)之后,结果看起来相当平稳。
另一个问题是,对于样本内预测,置信区间和预测均值之间的差异与样本外预测不同。文档说置信区间是通过(期望值±1.96*(标准误差))计算的(假设alpha为0.05),并且差异应该只取决于标准误差,而标准误差应该是恒定的。
我猜这两个问题是相关的。
预测的未来越远,可能出现的错误就越多。预测未来确实很难。
嗨,Jason,
确实很有帮助!
ARIMA中计算95%区间的公式是什么?
另外,在VAR中,我们得到的预测值和上下限的尺度不同(通常是差分的阶数)。
在VAR中如何将它们转换回原始尺度?
预测值可以看作均值,然后只需进行累积求和即可得到原始尺度。上下限稍微复杂一些。您需要假设一个概率模型(例如,高斯分布)并进行卷积积分,以便将误差范围转换回来。
Jason您好,我几年前买了您的《时间序列预测》这本书,它在我的数据科学家职业生涯中帮助我学习了预测公司宏观预测的知识。
我目前正在进行一项新的预测,并被要求使用BATS和TBATS。我已成功实现,但现在还需要提供预测区间。我找不到任何提供预测区间的Python库,所以我假设我需要自己计算。您能否帮我提供Python代码或我应该使用的预测公式?
谢谢,
肯
昨天我花了好几个小时都没有找到BATS置信区间的答案。但就像我通常做的那样,在我向您Jason提问后15分钟,我就找到了答案。
如果其他人需要BATS预测区间,这里有一个GitHub链接,其中有一个很棒的示例,对我来说很有效。
https://github.com/intive-DataScience/tbats/blob/master/examples/confidence_intervals.py