使用 Python 为时间序列预测编写 SARIMA
原文:
machinelearningmastery.com/sarima-for-time-series-forecasting-in-python/
自回归综合移动平均线(ARIMA)是用于单变量时间序列数据预测的最广泛使用的预测方法之一。
尽管该方法可以处理具有趋势的数据,但它不支持具有季节性组件的时间序列。
支持对该系列季节性组成部分进行直接建模的 ARIMA 扩展称为 SARIMA。
在本教程中,您将发现季节性自回归集成移动平均线(SARIMA)时间序列预测方法,其中包含趋势和季节性的单变量数据。
完成本教程后,您将了解:
- ARIMA 在季节性数据方面的局限性。
- ARIMA 的 SARIMA 扩展,明确地模拟单变量数据中的季节性元素。
- 如何使用 Statsmodels 库在 Python 中实现 SARIMA 方法。
让我们开始吧。
- 更新 Nov / 2018 :有关使用和网格搜索 SARIMA 超参数的帮助,请参阅此帖子:
用于 Python 中时间序列预测的 SARIMA 的温和介绍
Mario Micklisch 的照片,保留一些权利。
教程概述
本教程分为四个部分;他们是:
- ARIMA 有什么不对
- 什么是 SARIMA?
- 如何配置 SARIMA
- 如何在 Python 中使用 SARIMA
ARIMA 有什么不对
自回归综合移动平均线(ARIMA)是单变量时间序列数据的预测方法。
顾名思义,它支持自回归和移动平均元素。集成元素指的是差分,允许该方法支持具有趋势的时间序列数据。
ARIMA 的一个问题是它不支持季节性数据。这是一个重复循环的时间序列。
ARIMA 预计数据不是季节性的,或者季节性成分被删除,例如通过季节性差异等方法进行季节性调整。
有关 ARIMA 的更多信息,请参阅帖子:
另一种方法是使用 SARIMA。
什么是 SARIMA?
季节性自回归整合移动平均线,SARIMA 或季节性 ARIMA,是 ARIMA 的扩展,明确支持具有季节性成分的单变量时间序列数据。
它增加了三个新的超参数来指定系列季节性成分的自回归(AR),差分(I)和移动平均(MA),以及季节性周期的附加参数。
通过在 ARIMA 中包含额外的季节性术语来形成季节性 ARIMA 模型[…]模型的季节性部分由与模型的非季节性组成非常相似的术语组成,但它们涉及季节性时段的后移。
- 第 242 页,预测:原则和实践,2013。
如何配置 SARIMA
配置 SARIMA 需要为系列的趋势和季节性元素选择超参数。
趋势元素
有三个趋势元素需要配置。
它们与 ARIMA 模型相同;特别:
- p :趋势自动回归顺序。
- d :趋势差异顺序。
- q :趋势均线。
季节性元素
有四个不属于 ARIMA 的季节性元素必须配置;他们是:
- P :季节性自回归顺序。
- D :季节性差异顺序。
- Q :季节性移动平均线。
- m :单个季节性时段的时间步数。
同时,SARIMA 模型的表示法指定为:
SARIMA(p,d,q)(P,D,Q)m
指定模型的特定选择超参数的位置;例如:
SARIMA(3,1,0)(1,1,0)12
重要的是,m
参数影响P
,D
和Q
参数。例如,月度数据的 m 为 12 表示每年的季节性周期。
P
= 1 将利用模型中的第一个季节性偏移观察,例如 t-(m * 1)或 t-12。P
= 2,将使用最后两个季节性偏移的观测值 t-(m * 1),t-(m * 2)。
类似地,1 的D
将计算一阶季节差异,并且Q
= 1 将使用模型中的一阶误差(例如,移动平均值)。
季节性 ARIMA 模型使用等于季节数的滞后差异来消除加性季节效应。与滞后 1 差分去除趋势一样,滞后差分引入移动平均项。季节性 ARIMA 模型包括滞后 s 处的自回归和移动平均项。
- 第 142 页,入门时间序列与 R ,2009 年。
可以通过仔细分析 ACF 和 PACF 图来选择趋势元素,其中查看最近时间步长(例如,1,2,3)的相关性。
类似地,可以通过查看季节性滞后时间步长的相关性来分析 ACF 和 PACF 图以指定季节模型的值。
有关解释 ACF / PACF 图的更多信息,请参阅帖子:
季节性 ARIMA 模型可能具有大量参数和术语组合。因此,在拟合数据时尝试各种模型并使用适当的标准选择最佳拟合模型是合适的…
- 第 143-144 页,介绍时间序列与 R ,2009 年。
或者,可以在趋势和季节性超参数中使用网格搜索。
有关网格搜索 ARIMA 参数的更多信息,请参阅帖子:
如何在 Python 中使用 SARIMA
通过 Statsmodels 库在 Python 中支持 SARIMA 时间序列预测方法。
要使用 SARIMA,有三个步骤,它们是:
- 定义模型。
- 适合定义的模型。
- 使用拟合模型做出预测。
让我们依次看一下每一步。
1.定义模型
可以通过提供训练数据和大量模型配置参数来创建 SARIMAX 类的实例。
# specify training data
data = ...
# define model
model = SARIMAX(data, ...)
该实现称为 SARIMAX 而不是 SARIMA,因为方法名称中的“X”意味着该实现还支持外生变量。
这些是并行时间序列变量,它们不是通过 AR,I 或 MA 过程直接建模,而是作为模型的加权输入提供。
外源变量是可选的,可以通过“exog
”参数指定。
# specify training data
data = ...
# specify additional data
other_data = ...
# define model
model = SARIMAX(data, exog=other_data, ...)
趋势和季节性超参数分别指定为“_ 顺序 _”和“seasonal_order
”参数的 3 和 4 元素元组。
必须指定这些元素。
# specify training data
data = ...
# define model configuration
my_order = (1, 1, 1)
my_seasonal_order = (1, 1, 1, 12)
# define model
model = SARIMAX(data, order=my_order, seasonal_order=my_seasonal_order, ...)
这些是主要的配置元素。
您可能需要配置其他微调参数。在完整的 API 中了解更多信息:
2.适合模型
创建模型后,它可以适合训练数据。
通过调用 fit()函数来拟合模型。
拟合模型返回SARIMAXResults
类的实例。此对象包含拟合的详细信息,例如数据和系数,以及可用于使用模型的函数。
# specify training data
data = ...
# define model
model = SARIMAX(data, order=..., seasonal_order=...)
# fit model
model_fit = model.fit()
可以配置拟合过程的许多元素,一旦您熟悉实现,就值得阅读 API 以查看这些选项。
3.做出预测
适合后,该模型可用于做出预测。
可以通过在调用 fit 返回的SARIMAXResults
对象上调用forecast()
或predict()
函数来做出预测。
forecast()函数采用单个参数指定要预测的采样时间步数,或者如果未提供参数则采用一步预测。
# specify training data
data = ...
# define model
model = SARIMAX(data, order=..., seasonal_order=...)
# fit model
model_fit = model.fit()
# one step forecast
yhat = model_fit.forecast()
predict()
函数需要指定开始和结束日期或索引。
此外,如果在定义模型时提供了外生变量,则它们也必须在predict()
函数的预测期内提供。
# specify training data
data = ...
# define model
model = SARIMAX(data, order=..., seasonal_order=...)
# fit model
model_fit = model.fit()
# one step forecast
yhat = model_fit.predict(start=len(data), end=len(data))
进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
帖子
- 如何在 Python 中搜索用于时间序列预测的 SARIMA 模型超参数
- 如何使用 Python 创建用于时间序列预测的 ARIMA 模型
- 如何使用 Python 网格搜索 ARIMA 模型超参数
- 自相关和部分自相关的温和介绍
图书
API
- Statsmodels 状态空间方法的时间序列分析
- statsmodels.tsa.statespace.sarimax.SARIMAX API
- statsmodels.tsa.statespace.sarimax.SARIMAXResults API
- Statsmodels SARIMAX 笔记本
用品
摘要
在本教程中,您发现了季节性自回归集成移动平均线(SARIMA),用于包含趋势和季节性的单变量数据进行时间序列预测。
具体来说,你学到了:
- ARIMA 在季节性数据方面的局限性。
- ARIMA 的 SARIMA 扩展,明确地模拟单变量数据中的季节性元素。
- 如何使用 Statsmodels 库在 Python 中实现 SARIMA 方法。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
如何在 Python 中保存 ARIMA 时间序列预测模型
原文:
machinelearningmastery.com/save-arima-time-series-forecasting-model-python/
自回归整合移动平均模型(ARIMA)是一种流行的时间序列分析和预测线性模型。
statsmodels 库提供了用于 Python 的 ARIMA 实现。 ARIMA 模型可以保存到文件中,以便以后用于对新数据做出预测。当前版本的 statsmodels 库中存在一个错误,该错误会阻止加载已保存的模型。
在本教程中,您将了解如何诊断和解决此问题。
让我们开始吧。
如何在 Python 中保存 ARIMA 时间序列预测模型
照片由 Les Chatfield 保留,保留一些权利。
每日女性出生数据集
首先,让我们看一下标准时间序列数据集,我们可以用它来理解 statsmodels ARIMA 实现的问题。
这个每日女性出生数据集描述了 1959 年加利福尼亚州每日女性出生的数量。
单位是计数,有 365 个观测值。数据集的来源归功于 Newton(1988)。
您可以从 DataMarket 网站了解更多信息并下载数据集。
下载数据集并将其放在当前工作目录中,文件名为“ daily-total-female-births.csv ”。
下面的代码片段将加载并绘制数据集。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-total-female-births.csv', header=0)
series.plot()
pyplot.show()
运行该示例将数据集作为 Pandas Series 加载,然后显示数据的线图。
每日总女性出生情节
Python 环境
确认您使用的是 statsmodels 库的最新版本。
你可以通过运行下面的脚本来做到这一点:
import statsmodels
print('statsmodels: %s' % statsmodels.__version__)
运行脚本应生成显示 statsmodels 0.6 或 0.6.1 的结果。
statsmodels: 0.6.1
您可以使用 Python 2 或 3。
更新:我可以确认 statsmodels 0.8 中仍然存在故障并导致错误消息:
AttributeError: 'ARIMA' object has no attribute 'dates'
ARIMA 模型保存 Bug
我们可以在 Daily Female Births 数据集上轻松训练 ARIMA 模型。
下面的代码片段在数据集上训练 ARIMA(1,1,1)。
model.fit()函数返回一个 ARIMAResults 对象,我们可以在其上调用 save()将模型保存到文件和 load() 以后加载它。
from pandas import Series
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.tsa.arima_model import ARIMAResults
# load data
series = Series.from_csv('daily-total-female-births.csv', header=0)
# prepare data
X = series.values
X = X.astype('float32')
# fit model
model = ARIMA(X, order=(1,1,1))
model_fit = model.fit()
# save model
model_fit.save('model.pkl')
# load model
loaded = ARIMAResults.load('model.pkl')
运行此示例将训练模型并将其保存到文件中没有问题。
尝试从文件加载模型时将报告错误。
Traceback (most recent call last):
File "...", line 16, in <module>
loaded = ARIMAResults.load('model.pkl')
File ".../site-packages/statsmodels/base/model.py", line 1529, in load
return load_pickle(fname)
File ".../site-packages/statsmodels/iolib/smpickle.py", line 41, in load_pickle
return cPickle.load(fin)
TypeError: __new__() takes at least 3 arguments (1 given)
具体来说,注意这一行:
TypeError: __new__() takes at least 3 arguments (1 given)
到目前为止一切顺利,我们如何解决它?
ARIMA 模型保存 Bug 解决方法
Zae Myung Kim 于 2016 年 9 月发现了这个错误,并报告了这个错误。
你可以在这里读到所有和它有关的:
发生该错误是因为 pickle (用于序列化 Python 对象的库)所需的函数尚未在 statsmodels 中定义。
必须在保存之前在 ARIMA 模型中定义函数 getnewargs ,该函数定义构造对象所需的参数。
我们可以解决这个问题。修复涉及两件事:
- 定义适合 ARIMA 对象的
__getnewargs__
函数的实现。 - 将新功能添加到 ARIMA。
值得庆幸的是,Zae Myung Kim 在他的错误报告中提供了该函数的示例,因此我们可以直接使用它:
def __getnewargs__(self):
return ((self.endog),(self.k_lags, self.k_diff, self.k_ma))
Python 允许我们猴子补丁一个对象,甚至像 statsmodels 这样的库。
我们可以使用赋值在现有对象上定义新函数。
我们可以为 ARIMA 对象上的__getnewargs__
函数执行此操作,如下所示:
ARIMA.__getnewargs__ = __getnewargs__
下面列出了使用 Monkey 补丁在 Python 中训练,保存和加载 ARIMA 模型的完整示例:
from pandas import Series
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.tsa.arima_model import ARIMAResults
# monkey patch around bug in ARIMA class
def __getnewargs__(self):
return ((self.endog),(self.k_lags, self.k_diff, self.k_ma))
ARIMA.__getnewargs__ = __getnewargs__
# load data
series = Series.from_csv('daily-total-female-births.csv', header=0)
# prepare data
X = series.values
X = X.astype('float32')
# fit model
model = ARIMA(X, order=(1,1,1))
model_fit = model.fit()
# save model
model_fit.save('model.pkl')
# load model
loaded = ARIMAResults.load('model.pkl')
现在运行该示例成功加载模型而没有错误。
摘要
在这篇文章中,您了解了如何解决 statsmodels ARIMA 实现中的一个错误,该错误阻止您在文件中保存和加载 ARIMA 模型。
你发现了如何编写一个猴子补丁来解决这个 bug,以及如何证明它确实已被修复。
您是否在项目中使用此解决方法?
请在下面的评论中告诉我。
将 Python 用于季节性持久性预测
原文:
machinelearningmastery.com/seasonal-persistence-forecasting-python/
通常使用持久性或朴素预测作为时间序列问题的首次预测。
对具有季节性成分的时间序列数据进行更好的首次预测是在上一季中同时持续观察。这称为季节性持久性。
在本教程中,您将了解如何在 Python 中实现时间序列预测的季节性持久性。
完成本教程后,您将了解:
- 如何使用前几季的点观察来进行持久性预测。
- 如何在前一季的滑动窗口中使用平均观测值来进行持久性预测。
- 如何应用和评估每月和每日时间序列数据的季节性持久性。
让我们开始吧。
季节性持久性
在转向更复杂的方法之前,对时间序列问题进行有用的首次预测至关重要,以提供较低的技能。
这是为了确保我们不会在不具有预测性的模型或数据集上浪费时间。
在时间序列预测时,通常使用持久性或朴素预测作为首次预测模型。
对于具有明显季节性成分的时间序列数据,这没有意义。对于季节性数据,更好的第一次切割模型是在前一季节周期中同时使用观察作为预测。
我们可以称之为“_ 季节性持久性 _”,它是一个简单的模型,可以产生有效的第一次切割模型。
更好的一步是在之前的季节周期中同时使用最后几个观测值的简单函数。例如,观察的平均值。这通常可以提供一些额外的好处。
在本教程中,我们将演示这种简单的季节性持久性预测方法,用于在三个不同的真实时间序列数据集上提供预测技能的下限。
滑动窗的季节性持久性
在本教程中,我们将使用滑动窗口季节性持久性模型做出预测。
在滑动窗口内,将收集前一年季节中同时的观测结果,这些观测结果的平均值可用作持续预测。
可以评估不同的窗口大小以找到最小化错误的组合。
例如,如果数据是每月且预测的月份是 2 月,那么使用大小为 1 的窗口( w = 1 ),将使用去年 2 月的观察值来做出预测。
一个大小为 2 的窗口( w = 2 )将涉及对最后两个 Februaries 进行平均观察并用作预测。
另一种解释可能寻求使用前几年的点观测值(例如每月数据的 t-12,t-24 等),而不是采用累积点观测值的平均值。也许在您的数据集上尝试两种方法,看看哪种方法最适合作为一个好的起点模型。
实验测试线束
一致地评估时间序列预测模型非常重要。
在本节中,我们将定义如何在本教程中评估预测模型。
首先,我们将保留最近两年的数据,并评估对这些数据的预测。这适用于我们将查看的每月和每日数据。
我们将使用前向验证来评估模型表现。这意味着将枚举测试数据集中的每个时间步,在历史数据上构建模型,并将预测与预期值进行比较。然后将观察结果添加到训练数据集中并重复该过程。
前瞻性验证是评估时间序列预测模型的现实方法,因为人们可以期望在新观察结果可用时更新模型。
最后,将使用均方根误差或 RMSE 来评估预测。 RMSE 的好处在于它会对大错误进行处罚,并且得分与预测值(每月汽车销售额)的单位相同。
总之,测试工具包括:
- 最近 2 年的数据用作测试集。
- 模型评估的前瞻性验证。
- 用于报告模型技能的均方根误差。
案例研究 1:每月汽车销售数据集
月度汽车销售数据集描述了 1960 年至 1968 年间加拿大魁北克省的汽车销售数量。
单位是销售数量的计数,有 108 个观察值。数据来源归功于 Abraham 和 Ledolter(1983)。
您可以从 DataMarket 下载数据集。
下载数据集并将其保存到当前工作目录中,文件名为“ car-sales.csv ”。请注意,您可能需要从文件中删除页脚信息。
下面的代码将数据集加载为 Pandas Series 对象。
# line plot of time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('car-sales.csv', header=0)
# display first few rows
print(series.head(5))
# line plot of dataset
series.plot()
pyplot.show()
运行该示例将打印前 5 行数据。
Month
1960-01-01 6550
1960-02-01 8728
1960-03-01 12026
1960-04-01 14395
1960-05-01 14587
Name: Sales, dtype: int64
还提供了数据的线图。我们可以看到年度季节性成分和增长趋势。
月度汽车销售数据集的线图
之前 24 个月的数据将作为测试数据保留。我们将用 1 至 5 年的滑动窗口调查季节性持久性。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from numpy import mean
from matplotlib import pyplot
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# evaluate mean of different number of years
years = [1, 2, 3, 4, 5]
scores = list()
for year in years:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# collect obs
obs = list()
for y in range(1, year+1):
obs.append(history[-(y*12)])
# make prediction
yhat = mean(obs)
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('Years=%d, RMSE: %.3f' % (year, rmse))
pyplot.plot(years, scores)
pyplot.show()
运行该示例从前几年同一月的观察滑动窗口打印年份数和平均观测值的 RMSE。
结果表明,采用过去三年的平均值是一个良好的起始模型,汽车销售的 RMSE 为 1803.630。
Years=1, RMSE: 1997.732
Years=2, RMSE: 1914.911
Years=3, RMSE: 1803.630
Years=4, RMSE: 2099.481
Years=5, RMSE: 2522.235
创建滑动窗口大小与模型错误的关系图。
该图很好地显示了滑动窗口大小为 3 年的改进,然后是从那一点开始的误差的快速增加。
每月汽车销售的窗口大小滑动到 RMSE
案例研究 2:每月书面纸销售数据集
每月书写纸销售数据集描述了专业书写纸销售的数量。
单位是销售数量的一种类型,有 147 个月的观察(仅超过 12 年)。计数是分数,表明数据实际上可能以数十万销售为单位。数据来源归功于 Makridakis 和 Wheelwright(1989)。
您可以从 DataMarket 下载数据集。
下载数据集并将其保存到当前工作目录中,文件名为“ writing-paper-sales.csv ”。请注意,您可能需要从文件中删除页脚信息。
日期时间戳仅包含年份编号和月份。因此,需要自定义日期时间解析功能来加载数据并将数据基于任意年份。选择 1900 年作为起点,这不应影响本案例研究。
下面的示例将每月书写纸销售数据集加载为 Pandas 系列。
# load and plot dataset
from pandas import read_csv
from pandas import datetime
from matplotlib import pyplot
# load dataset
def parser(x):
if len(x) == 4:
return datetime.strptime('190'+x, '%Y-%m')
return datetime.strptime('19'+x, '%Y-%m')
series = read_csv('writing-paper-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
# summarize first few rows
print(series.head())
# line plot
series.plot()
pyplot.show()
运行该示例将打印已加载数据集的前 5 行。
Month
1901-01-01 1359.795
1901-02-01 1278.564
1901-03-01 1508.327
1901-04-01 1419.710
1901-05-01 1440.510
然后创建加载的数据集的线图。我们可以看到年度季节性成分和增长趋势。
月刊书写纸销售数据集的线图
与前面的示例一样,我们可以将最近 24 个月的观察结果作为测试数据集。因为我们有更多的数据,我们将尝试从 1 年到 10 年的滑动窗口大小。
下面列出了完整的示例。
from pandas import read_csv
from pandas import datetime
from sklearn.metrics import mean_squared_error
from math import sqrt
from numpy import mean
from matplotlib import pyplot
# load dataset
def parser(x):
if len(x) == 4:
return datetime.strptime('190'+x, '%Y-%m')
return datetime.strptime('19'+x, '%Y-%m')
series = read_csv('writing-paper-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# evaluate mean of different number of years
years = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
scores = list()
for year in years:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# collect obs
obs = list()
for y in range(1, year+1):
obs.append(history[-(y*12)])
# make prediction
yhat = mean(obs)
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('Years=%d, RMSE: %.3f' % (year, rmse))
pyplot.plot(years, scores)
pyplot.show()
运行该示例将打印滑动窗口的大小以及由此产生的季节性持久性模型错误。
结果表明,窗户大小为 5 年是最佳的,每月写作纸的 RMSE 为 554.660。
Years=1, RMSE: 606.089
Years=2, RMSE: 557.653
Years=3, RMSE: 555.777
Years=4, RMSE: 544.251
Years=5, RMSE: 540.317
Years=6, RMSE: 554.660
Years=7, RMSE: 569.032
Years=8, RMSE: 581.405
Years=9, RMSE: 602.279
Years=10, RMSE: 624.756
窗口大小和错误之间的关系在线图上绘制,显示与前一场景相似的错误趋势。错误在再次增加之前下降到拐点(在这种情况下为 5 年)。
每月书写纸销售的窗口大小滑动到 RMSE
案例研究 3:墨尔本每日最高温度数据集
每日最高墨尔本气温数据集描述了 1981 年至 1990 年期间澳大利亚墨尔本市的日常气温。
单位是摄氏度,有 3,650 个观测值,或 10 年的数据。数据来源记入澳大利亚气象局。
您可以从 DataMarket 下载数据集。
下载数据集并将其保存到当前工作目录中,文件名为“ max-daily-temps.csv ”。请注意,您可能需要从文件中删除页脚信息。
下面的示例演示如何将数据集加载为 Pandas 系列。
# line plot of time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('max-daily-temps.csv', header=0)
# display first few rows
print(series.head(5))
# line plot of dataset
series.plot()
pyplot.show()
运行该示例将打印前 5 行数据。
Date
1981-01-01 38.1
1981-01-02 32.4
1981-01-03 34.5
1981-01-04 20.7
1981-01-05 21.5
还创建了线图。我们可以看到,我们比前两个场景有更多的观察,并且数据中存在明显的季节性趋势。
每日墨尔本最高温度数据集的线图
由于数据是每天,我们需要将测试数据中的年份指定为 365 天而不是 12 个月的函数。
这忽略了闰年,这是一个可能,甚至应该在您自己的项目中解决的复杂问题。
下面列出了季节性持久性的完整示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from numpy import mean
from matplotlib import pyplot
# load data
series = Series.from_csv('max-daily-temps.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-(2*365)], X[-(2*365):]
# evaluate mean of different number of years
years = [1, 2, 3, 4, 5, 6, 7, 8]
scores = list()
for year in years:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# collect obs
obs = list()
for y in range(1, year+1):
obs.append(history[-(y*365)])
# make prediction
yhat = mean(obs)
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('Years=%d, RMSE: %.3f' % (year, rmse))
pyplot.plot(years, scores)
pyplot.show()
运行该示例将打印滑动窗口的大小和相应的模型错误。
与前两种情况不同,我们可以看到随着窗口大小的增加技能不断提高的趋势。
最好的结果是所有 8 年历史数据的滑动窗口,RMSE 为 4.271。
Years=1, RMSE: 5.950
Years=2, RMSE: 5.083
Years=3, RMSE: 4.664
Years=4, RMSE: 4.539
Years=5, RMSE: 4.448
Years=6, RMSE: 4.358
Years=7, RMSE: 4.371
Years=8, RMSE: 4.271
滑动窗口大小与模型误差的关系图使这一趋势明显。
它表明,如果最优模型证明是前几年同一天的观测函数,那么获得更多这个问题的历史数据可能会有用。
将窗口尺寸滑动到 RMSE 以获得每日墨尔本最高温度
如果观察结果是在前几季的同一周或一个月中取平均值,我们也可以这样做,这可能是一个富有成果的实验。
摘要
在本教程中,您发现了时间序列预测的季节性持久性。
你了解到:
- 如何使用前几季的点观察来进行持久性预测。
- 如何在多个前几季使用滑动窗口的平均值来进行持久性预测。
- 如何将季节性持久性应用于每日和每月时间序列数据。
您对季节性数据的持久性有任何疑问吗?
在评论中提出您的问题,我会尽力回答。
基于 Python 和 ARIMA 的历史规模敏感性分析的预测技巧
原文:
machinelearningmastery.com/sensitivity-analysis-history-size-forecast-skill-arima-python/
时间序列预测模型需要多少历史记录?
这是一个特定问题的问题,我们可以通过设计实验进行调查。
在本教程中,您将发现历史大小对 Python 中 ARIMA 预测模型技能的影响。
具体来说,在本教程中,您将:
- 加载标准数据集并拟合 ARIMA 模型。
- 设计并执行历史数据年数的敏感性分析,以模拟技能。
- 分析灵敏度分析的结果。
这将提供一个模板,用于对您自己的时间序列预测问题执行历史数据集大小的类似灵敏度分析。
让我们开始吧。
- 2017 年 8 月更新:修正了在原始数据上构建模型的错误,而不是季节性差异版本的数据。谢谢 David Ravnsborg!
- 更新 June / 2018 :删除重复的句子。拉胡尔感谢!
用 Python 中的 ARIMA 预测技能的历史大小敏感性分析
照片由 Sean MacEntee ,保留一些权利。
最低每日温度数据集
该数据集描述了澳大利亚墨尔本市 10 年(1981-1990)的最低日常温度。
单位为摄氏度,有 3,650 个观测值。数据来源被称为澳大利亚气象局。
下载数据集并将其保存在当前工作目录中,文件名为“ daily-minimum-Temperats.sv ”。
注意:下载的文件包含一些问号(“?”)字符,在使用数据集之前必须将其删除。在文本编辑器中打开文件并删除“?”字符。此外,删除文件中的任何页脚信息。
下面的示例将数据集加载为 Pandas 系列。
# line plot of time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# display first few rows
print(series.head(20))
# line plot of dataset
series.plot()
pyplot.show()
运行该示例将打印加载文件的前 20 行。
Date
1981-01-01 20.7
1981-01-02 17.9
1981-01-03 18.8
1981-01-04 14.6
1981-01-05 15.8
1981-01-06 15.8
1981-01-07 15.8
1981-01-08 17.4
1981-01-09 21.8
1981-01-10 20.0
1981-01-11 16.2
1981-01-12 13.3
1981-01-13 16.7
1981-01-14 21.5
1981-01-15 25.0
1981-01-16 20.7
1981-01-17 20.6
1981-01-18 24.8
1981-01-19 17.7
1981-01-20 15.5
Name: Temp, dtype: float64
然后将数据绘制成显示季节性模式的线图。
最低每日温度数据集线图
ARIMA 预测模型
在本节中,我们将 ARIMA 预测模型与数据拟合。
模型的参数不会被调整,但是会很熟练。
数据包含一年的季节性组件,必须将其删除以使数据固定并适合与 ARIMA 模型一起使用。
我们可以通过从一年前(365 天)减去观察值来获取季节性差异。这很粗糙,因为它没有说明闰年。这也意味着第一年的数据将无法用于建模,因为一年前没有数据来区分数据。
# seasonal difference
differenced = series.diff(365)
# trim off the first year of empty data
differenced = differenced[365:]
我们将 ARIMA(7,0,0)模型与数据拟合并打印摘要信息。这表明该模型是稳定的。
# fit model
model = ARIMA(differenced, order=(7,0,0))
model_fit = model.fit(trend='nc', disp=0)
print(model_fit.summary())
综合这些,下面列出了完整的例子。
# fit an ARIMA model
from pandas import Series
from matplotlib import pyplot
from statsmodels.tsa.arima_model import ARIMA
# load dataset
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# seasonal difference
differenced = series.diff(365)
# trim off the first year of empty data
differenced = series[365:]
# fit model
model = ARIMA(differenced, order=(7,0,0))
model_fit = model.fit(trend='nc', disp=0)
print(model_fit.summary())
运行该示例提供了适合 ARIMA 模型的摘要。
ARMA Model Results
==============================================================================
Dep. Variable: Temp No. Observations: 3285
Model: ARMA(7, 0) Log Likelihood -8690.089
Method: css-mle S.D. of innovations 3.409
Date: Fri, 25 Aug 2017 AIC 17396.178
Time: 15:02:59 BIC 17444.955
Sample: 01-01-1982 HQIC 17413.643
- 12-31-1990
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1.Temp 0.5278 0.017 30.264 0.000 0.494 0.562
ar.L2.Temp -0.1099 0.020 -5.576 0.000 -0.149 -0.071
ar.L3.Temp 0.0286 0.020 1.441 0.150 -0.010 0.067
ar.L4.Temp 0.0307 0.020 1.549 0.122 -0.008 0.070
ar.L5.Temp 0.0090 0.020 0.456 0.648 -0.030 0.048
ar.L6.Temp 0.0164 0.020 0.830 0.407 -0.022 0.055
ar.L7.Temp 0.0272 0.017 1.557 0.120 -0.007 0.061
Roots
=============================================================================
Real Imaginary Modulus Frequency
-----------------------------------------------------------------------------
AR.1 1.3305 -0.0000j 1.3305 -0.0000
AR.2 0.9936 -1.1966j 1.5553 -0.1397
AR.3 0.9936 +1.1966j 1.5553 0.1397
AR.4 -0.2067 -1.7061j 1.7186 -0.2692
AR.5 -0.2067 +1.7061j 1.7186 0.2692
AR.6 -1.7536 -0.8938j 1.9683 -0.4250
AR.7 -1.7536 +0.8938j 1.9683 0.4250
-----------------------------------------------------------------------------
模型历史敏感性分析
在本节中,我们将探讨历史规模对拟合模型技能的影响。
原始数据有 10 年的数据。季节性差异给我们留下了 9 年的数据。我们将把最后一年的数据作为测试数据,并在最后一年进行前瞻性验证。
将收集逐日预测并计算均方根误差(RMSE)分数以指示模型的技能。
下面的代码段将经季节性调整的数据分为训练和测试数据集。
train, test = differenced[differenced.index < '1990'], differenced['1990']
选择对您自己的预测问题有意义的区间非常重要。
我们将使用前一年的数据评估模型的技能,然后是 2 年,一直追溯到 8 年的历史数据。
考虑到数据的季节性,一年是测试该数据集的良好间隔,但是可以测试其他间隔,例如每月或多年间隔。
下面的代码段显示了我们如何逐年倒退并累积选择所有可用的观察结果。
例如
- 测试 1:1989 年的所有数据
- 测试 2:1988 年至 1989 年的所有数据
等等。
# split
train, test = differenced[differenced.index < '1990'], differenced['1990']
years = ['1989', '1988', '1987', '1986', '1985', '1984', '1983', '1982']
for year in years:
# select data from 'year' cumulative to 1989
dataset = train[train.index >= year]
下一步是评估 ARIMA 模型。
我们将使用前向验证。这意味着将在选定的历史数据上构建模型并预测下一个时间步骤(1990 年 1 月 1 日)。对该时间步骤的真实观察将被添加到历史中,构建新模型,并预测下一个时间步骤。
预测将一起收集并与观察的最后一年进行比较,以给出错误分数。在这种情况下,RMSE 将用作分数,并且与观察本身的比例相同。
# walk forward over time steps in test
values = dataset.values
history = [values[i] for i in range(len(values))]
predictions = list()
test_values = test.values
for t in range(len(test_values)):
# fit model
model = ARIMA(history, order=(7,0,0))
model_fit = model.fit(trend='nc', disp=0)
# make prediction
yhat = model_fit.forecast()[0]
predictions.append(yhat)
history.append(test_values[t])
rmse = sqrt(mean_squared_error(test_values, predictions))
print('%s-%s (%d values) RMSE: %.3f' % (years[0], year, len(values), rmse))
综合这些,下面列出了完整的例子。
# fit an ARIMA model
from pandas import Series
from matplotlib import pyplot
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
from math import sqrt
# load dataset
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# seasonal difference
differenced = series.diff(365)
# trim off the first year of empty data
differenced = differenced[365:]
# split
train, test = differenced[differenced.index < '1990'], differenced['1990']
years = ['1989', '1988', '1987', '1986', '1985', '1984', '1983', '1982']
for year in years:
# select data from 'year' cumulative to 1989
dataset = train[train.index >= year]
# walk forward over time steps in test
values = dataset.values
history = [values[i] for i in range(len(values))]
predictions = list()
test_values = test.values
for t in range(len(test_values)):
# fit model
model = ARIMA(history, order=(7,0,0))
model_fit = model.fit(trend='nc', disp=0)
# make prediction
yhat = model_fit.forecast()[0]
predictions.append(yhat)
history.append(test_values[t])
rmse = sqrt(mean_squared_error(test_values, predictions))
print('%s-%s (%d values) RMSE: %.3f' % (years[0], year, len(values), rmse))
运行该示例将打印历史记录的间隔,历史记录中的观察次数以及使用该历史记录训练的模型的 RMSE 技能。
该示例确实需要一段时间才能运行,因为为历史训练数据的每个累积间隔创建了 365 个 ARIMA 模型。
1989-1989 (365 values) RMSE: 3.120
1989-1988 (730 values) RMSE: 3.109
1989-1987 (1095 values) RMSE: 3.104
1989-1986 (1460 values) RMSE: 3.108
1989-1985 (1825 values) RMSE: 3.107
1989-1984 (2190 values) RMSE: 3.103
1989-1983 (2555 values) RMSE: 3.099
1989-1982 (2920 values) RMSE: 3.096
结果表明,随着可用历史的大小增加,模型误差减小,但趋势不是纯线性的。
我们确实看到在 2 - 3 年可能会出现收益递减点。在数据可用性或长模型训练时间成为问题的域中,了解您可以使用更少的数据年份非常有用。
我们可以绘制 ARIMA 模型误差与训练观察数量之间的关系。
from matplotlib import pyplot
x = [365, 730, 1095, 1460, 1825, 2190, 2555, 2920]
y = [3.120, 3.109, 3.104, 3.108, 3.107, 3.103, 3.099, 3.096]
pyplot.plot(x, y)
pyplot.show()
运行该示例会创建一个绘图,当训练样本增加时,该绘图几乎显示出错误的线性趋势。
历史大小与 ARIMA 模型错误
这通常是预期的,因为更多的历史数据意味着系数可以被更好地优化以描述在多数情况下来自多年数据的可变性所发生的情况。
还有反直觉。可以预期模型的表现会随着历史的增加而增加,因为最近几年的数据可能更像是明年的数据。这种直觉在受到更大概念漂移的领域中可能更有效。
扩展
本节讨论灵敏度分析的限制和扩展。
- Untuned Model 。该示例中使用的 ARIMA 模型决不会针对该问题进行调整。理想情况下,将使用已调整的 ARIMA 模型或针对每种情况调整的模型对训练历史的大小进行灵敏度分析。
- 统计学意义。目前尚不清楚模型技能的差异是否具有统计学意义。成对统计显着性检验可用于梳理 RMSE 的差异是否有意义。
- 替代型号。 ARIMA 使用历史数据来拟合系数。其他模型可能以其他方式使用不断增加的历史数据。可以研究替代的非线性机器学习模型。
- 备用间隔。选择一年来联合历史数据,但可以使用其他间隔。在该数据集的历史数据的一年或两年内,良好的间隔可能是数周或数月,因为极端新近度可能以有用的方式偏差系数。
摘要
在本教程中,您了解了如何设计,执行和分析用于拟合时间序列预测模型的历史记录量的灵敏度分析。
你有任何问题吗?
在评论中提出您的问题,我会尽力回答。
用于测试简单的时间序列预测模型,以便不会欺骗自己
原文:
machinelearningmastery.com/simple-time-series-forecasting-models/
重要的是要在时间序列预测问题上建立强大的绩效基准,并且不要愚弄自己认为复杂的方法是熟练的,而事实上它们并非如此。
这需要您评估一套标准的朴素或简单的时间序列预测模型,以便了解问题的最差可接受表现,以便更复杂的模型。
应用这些简单模型还可以发现有关可能带来更好表现的更高级方法的新想法。
在本教程中,您将了解如何在现实世界数据集上实现和自动化三种标准基线时间序列预测方法。
具体来说,您将学到:
- 如何自动化持久性模型并测试一组持久化值。
- 如何自动化扩展窗口模型。
- 如何自动化滚动窗口预测模型并测试一组窗口大小。
这是一个重要的主题,强烈推荐用于任何时间序列预测项目。
让我们开始吧。
概观
本教程分为以下 5 个部分:
- 每月汽车销售数据集:我们将使用的标准时间序列数据集的概述。
- 测试设置:我们将如何评估本教程中的预测模型。
- 持久性预测:持久性预测以及如何自动化。
- 扩展窗口预测:扩展窗口预测以及如何自动化。
- 滚动窗口预测:滚动窗口预测以及如何自动化它。
使用了最新的 Python SciPy 环境,包括 Python 2 或 3,Pandas,Numpy 和 Matplotlib。
每月汽车销售数据集
在本教程中,我们将使用 Monthly Car Sales 数据集。
该数据集描述了 1960 年至 1968 年间加拿大魁北克省的汽车销售数量。
单位是销售数量的计数,有 108 个观察值。源数据归功于 Abraham 和 Ledolter(1983)。
您可以从 DataMarket 下载数据集。
下载数据集并将其保存到当前工作目录中,文件名为“ car-sales.csv ”。请注意,您可能需要从文件中删除页脚信息。
下面的代码将数据集加载为 Pandas Series 对象。
# line plot of time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('car-sales.csv', header=0)
# display first few rows
print(series.head(5))
# line plot of dataset
series.plot()
pyplot.show()
运行该示例将打印前 5 行数据。
Month
1960-01-01 6550
1960-02-01 8728
1960-03-01 12026
1960-04-01 14395
1960-05-01 14587
Name: Sales, dtype: int64
还提供了数据的线图。
每月汽车销售数据集线图
实验测试设置
一致地评估时间序列预测模型非常重要。
在本节中,我们将定义如何评估本教程中的三个预测模型。
首先,我们将保留最近两年的数据,并评估对这些数据的预测。鉴于数据是每月,这意味着最后 24 个观测值将用作测试数据。
我们将使用前进验证方法来评估模型表现。这意味着将枚举测试数据集中的每个时间步,在历史数据上构建模型,并将预测与预期值进行比较。然后将观察结果添加到训练数据集中并重复该过程。
前瞻性验证是评估时间序列预测模型的现实方法,因为人们可以期望在新观察结果可用时更新模型。
最后,将使用均方根误差或 RMSE 评估预测。 RMSE 的好处在于它会对大错误进行处罚,并且得分与预测值(每月汽车销售额)的单位相同。
总之,测试工具包括:
- 最近 2 年的数据使用了测试集。
- 模型评估的前瞻性验证。
- 用于报告模型技能的均方根误差。
优化持久性预测
持久性预测涉及使用先前的观察来预测下一个时间步。
出于这个原因,这种方法通常被称为朴素的预测。
为什么要停止使用之前的观察?在本节中,我们将研究自动化持久性预测,并评估使用任意先前时间步骤来预测下一个时间步骤。
我们将在持久性模型中探索前 24 个月的点观察中的每一个。将使用测试工具和收集的 RMSE 分数评估每个配置。然后,我们将显示分数并绘制持久时间步长与模型技能之间的关系。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from matplotlib import pyplot
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
persistence_values = range(1, 25)
scores = list()
for p in persistence_values:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = history[-p]
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('p=%d RMSE:%.3f' % (p, rmse))
# plot scores over persistence values
pyplot.plot(persistence_values, scores)
pyplot.show()
运行该示例为每个持久点观察打印 RMSE。
p=1 RMSE:3947.200
p=2 RMSE:5485.353
p=3 RMSE:6346.176
p=4 RMSE:6474.553
p=5 RMSE:5756.543
p=6 RMSE:5756.076
p=7 RMSE:5958.665
p=8 RMSE:6543.266
p=9 RMSE:6450.839
p=10 RMSE:5595.971
p=11 RMSE:3806.482
p=12 RMSE:1997.732
p=13 RMSE:3968.987
p=14 RMSE:5210.866
p=15 RMSE:6299.040
p=16 RMSE:6144.881
p=17 RMSE:5349.691
p=18 RMSE:5534.784
p=19 RMSE:5655.016
p=20 RMSE:6746.872
p=21 RMSE:6784.611
p=22 RMSE:5642.737
p=23 RMSE:3692.062
p=24 RMSE:2119.103
还创建了持久值(t-n)与模型技能(RMSE)的关系图。
从结果来看,显然从 12 个月前或 24 个月前坚持观察是这个数据集的一个很好的起点。
取得的最好成果包括坚持 t-12 的结果,车辆销售的 RMSE 为 1997.732。
这是一个明显的结果,但也非常有用。
我们期望预测模型是 t-12,t-24,t-36 等观测值的一些加权组合,这将是一个强有力的起点。
它还指出,朴素的 t-1 持久性对于这个数据集来说是一个不太理想的起点。
持续观察 RMSE 月度汽车销售数据集
我们可以使用 t-12 模型做出预测并根据测试数据绘制它。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from matplotlib import pyplot
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = history[-12]
predictions.append(yhat)
# observation
history.append(test[i])
# plot predictions vs observations
pyplot.plot(test)
pyplot.plot(predictions)
pyplot.show()
运行该示例将测试数据集(蓝色)与预测值(橙色)进行对比。
t-12 持久性模型的预测值与测试数据集的线图
您可以在帖子中了解有关时间序列预测的持久性模型的更多信息:
扩大窗口预测
展开窗口是指计算所有可用历史数据的统计量并使用该数据做出预测的模型。
这是一个不断扩大的窗口,因为它随着收集更多真实观察而增长。
要计算的两个好的起点统计量是平均值和中值历史观察值。
以下示例使用展开窗口均值作为预测。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from numpy import mean
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = mean(history)
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
print('RMSE: %.3f' % rmse)
运行该示例将打印方法的 RMSE 评估。
RMSE: 5113.067
我们也可以用历史观察的中位数重复相同的实验。下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from numpy import median
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = median(history)
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
print('RMSE: %.3f' % rmse)
再次,运行该示例打印模型的技能。
我们可以看到,在这个问题上,历史均值产生了比中位数更好的结果,但两者都比使用优化的持久性值更差。
RMSE: 5527.408
我们可以根据测试数据集绘制平均扩展窗口预测,以了解预测在上下文中的实际情况。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from matplotlib import pyplot
from numpy import mean
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = mean(history)
predictions.append(yhat)
# observation
history.append(test[i])
# plot predictions vs observations
pyplot.plot(test)
pyplot.plot(predictions)
pyplot.show()
该图显示了糟糕的预测情况以及它如何不跟随数据的变动,除了略微上升的趋势。
平均扩展窗口模型的预测值与测试数据集的线图
您可以在帖子中看到更多扩展窗口统计量的示例:
滚动窗口预测
滚动窗口模型涉及计算先前观察的固定连续块的统计量并将其用作预测。
它很像扩展窗口,但窗口大小保持固定,并从最近的观察结果倒数。
对于时间序列问题可能更有用,其中最近的滞后值比旧的滞后值更具预测性。
我们将自动检查 1 到 24 个月(2 年)的不同滚动窗口大小,并从计算平均观察开始并将其用作预测。下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from matplotlib import pyplot
from numpy import mean
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
window_sizes = range(1, 25)
scores = list()
for w in window_sizes:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = mean(history[-w:])
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('w=%d RMSE:%.3f' % (w, rmse))
# plot scores over window sizes values
pyplot.plot(window_sizes, scores)
pyplot.show()
运行该示例将为每个配置打印滚动窗口大小和 RMSE。
w=1 RMSE:3947.200
w=2 RMSE:4350.413
w=3 RMSE:4701.446
w=4 RMSE:4810.510
w=5 RMSE:4649.667
w=6 RMSE:4549.172
w=7 RMSE:4515.684
w=8 RMSE:4614.551
w=9 RMSE:4653.493
w=10 RMSE:4563.802
w=11 RMSE:4321.599
w=12 RMSE:4023.968
w=13 RMSE:3901.634
w=14 RMSE:3907.671
w=15 RMSE:4017.276
w=16 RMSE:4084.080
w=17 RMSE:4076.399
w=18 RMSE:4085.376
w=19 RMSE:4101.505
w=20 RMSE:4195.617
w=21 RMSE:4269.784
w=22 RMSE:4258.226
w=23 RMSE:4158.029
w=24 RMSE:4021.885
还会创建窗口大小与错误的折线图。
结果表明,w = 13 的滚动窗口最佳,RMSE 为每月 3,901 辆汽车销量。
滚动窗口大小到 RMSE 的线图,用于月度汽车销售数据集的平均预测
我们可以用中位数统计重复这个实验。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from math import sqrt
from matplotlib import pyplot
from numpy import median
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
window_sizes = range(1, 25)
scores = list()
for w in window_sizes:
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = median(history[-w:])
predictions.append(yhat)
# observation
history.append(test[i])
# report performance
rmse = sqrt(mean_squared_error(test, predictions))
scores.append(rmse)
print('w=%d RMSE:%.3f' % (w, rmse))
# plot scores over window sizes values
pyplot.plot(window_sizes, scores)
pyplot.show()
再次运行该示例将为每个配置打印窗口大小和 RMSE。
w=1 RMSE:3947.200
w=2 RMSE:4350.413
w=3 RMSE:4818.406
w=4 RMSE:4993.473
w=5 RMSE:5212.887
w=6 RMSE:5002.830
w=7 RMSE:4958.621
w=8 RMSE:4817.664
w=9 RMSE:4932.317
w=10 RMSE:4928.661
w=11 RMSE:4885.574
w=12 RMSE:4414.139
w=13 RMSE:4204.665
w=14 RMSE:4172.579
w=15 RMSE:4382.037
w=16 RMSE:4522.304
w=17 RMSE:4494.803
w=18 RMSE:4360.445
w=19 RMSE:4232.285
w=20 RMSE:4346.389
w=21 RMSE:4465.536
w=22 RMSE:4514.596
w=23 RMSE:4428.739
w=24 RMSE:4236.126
再次创建窗口大小和 RMSE 的图。
在这里,我们可以看到,窗口大小为 w = 1,每月汽车销售 RMSE 为 3947.200,实际上是 t-1 持久性模型,取得了最佳效果。
结果通常比优化持久性差,但优于扩展窗口模型。我们可以通过加权组合窗口观察来想象更好的结果,这个想法导致使用 AR 和 ARIMA 等线性模型。
滚动窗口大小到 RMSE 的线图,用于月度汽车销售数据集的中位数预测
同样,我们可以根据实际观察结果绘制来自更好模型(w = 13 的平均滚动窗口)的预测,以了解预测在上下文中的表现。
下面列出了完整的示例。
from pandas import Series
from sklearn.metrics import mean_squared_error
from matplotlib import pyplot
from numpy import mean
# load data
series = Series.from_csv('car-sales.csv', header=0)
# prepare data
X = series.values
train, test = X[0:-24], X[-24:]
# walk-forward validation
history = [x for x in train]
predictions = list()
for i in range(len(test)):
# make prediction
yhat = mean(history[-13:])
predictions.append(yhat)
# observation
history.append(test[i])
# plot predictions vs observations
pyplot.plot(test)
pyplot.plot(predictions)
pyplot.show()
运行代码会创建观测线图(蓝色)与预测值(橙色)的对比。
我们可以看到模型更好地遵循数据水平,但同样不遵循实际的上下运动。
预测值的线图与平均 w = 13 滚动窗口模型的测试数据集
您可以在帖子中看到滚动窗口统计量的更多示例:
摘要
在本教程中,您发现了计算时间序列预测问题和方法的最差可接受表现的重要性,您可以使用这些方法确保您不会使用更复杂的方法来欺骗自己。
具体来说,你学到了:
- 如何自动测试一组持久性配置。
- 如何评估扩展窗口模型。
- 如何自动测试一组滚动窗口配置。
您对基线预测方法或此帖有任何疑问吗?
在评论中提出您的问题,我会尽力回答。
标准多变量,多步骤和多站点时间序列预测问题
实时世界时间序列预测具有挑战性,其原因不仅限于问题特征,例如具有多个输入变量,需要预测多个时间步骤,以及需要对多个物理站点执行相同类型的预测。
在这篇文章中,您将发现具有这些属性的标准化但复杂的时间序列预测问题,但是它很小且充分理解,可用于探索和更好地理解在具有挑战性的数据集上开发预测模型的方法。
阅读这篇文章后,你会知道:
- 解决空气质量数据集的竞争和动机。
- 概述定义的预测问题及其涵盖的数据挑战。
- 可以下载并立即开始使用的免费数据文件的说明。
让我们开始吧。
标准多变量,多步骤和多站点时间序列预测问题
照某人,保留一些权利。
EMC 数据科学全球黑客马拉松
该数据集被用作 Kaggle 比赛的中心。
具体而言,由数据科学伦敦和数据科学全球主办的 24 小时黑客马拉松作为大数据周活动的一部分,两个组织现在似乎不存在,6 年后。
比赛涉及数千美元的现金奖励,数据集由伊利诺伊州库克县当地政府提供,建议数据集中提到的所有位置都在该地区。
挑战的动机是开发一个更好的预测空气质量的模型,取自竞赛描述:
EPA 的空气质量指数每天被患有哮喘和其他呼吸系统疾病的人使用,以避免可能引发攻击的危险水平的室外空气污染物。据世界卫生组织统计,目前估计有 2.35 亿人患有哮喘。在全球范围内,它现在是儿童中最常见的慢性疾病,自 1980 年以来美国的发病率翻了一番。
竞赛描述表明,获胜模型可以作为新的空气质量预测系统的基础,尽管尚不清楚是否为此目的转换了任何模型。
比赛是由一名 Kaggle 员工 Ben Hamner 赢得的,根据利益冲突,他可能没有收到奖金。 Ben 在博客文章中描述了他的获胜方法,题为“将所有东西放入随机森林:Ben Hamner 赢得空气质量预测黑客马拉松”并在 GitHub 上提供了他的代码。
在这个论坛帖子中有一个很好的讨论解决方案和相关代码,标题为“分区模型的一般方法? “。
预测性建模问题
该数据描述了跨多个站点或物理位置的多变量时间序列的多步预测问题。
随着时间的推移进行多次天气测量,预测在多个物理位置的特定未来时间间隔内的一系列空气质量测量。
这是一个具有挑战性的时间序列预测问题,具有很多现实世界预测的质量:
- 数据不完整。并非所有天气和空气质量措施都适用于所有地点。
- 缺少数据。并非所有可用的措施都有完整的历史。
- 多变量输入:每个预测的模型输入由多个天气观测组成。
- 多步输出:模型输出是一系列不连续的预测空气质量测量。
- 多站点输出:该模式必须为多个物理站点输出多步预测。
下载数据集文件
该数据集可从 Kaggle 网站免费获得。
您必须先创建一个帐户并使用 Kaggle 登录,然后才能获得下载数据集的权限。
数据集可以从这里下载:
数据集文件的说明
您必须单独下载 4 个感兴趣的文件;他们是:
文件:SiteLocations.csv
此文件包含由唯一标识符标记的站点位置列表,以及它们在地球上按经度和纬度测量的精确位置。
所有坐标在西北半球似乎相对较近,例如美国。
以下是该文件的示例。
"SITE_ID","LATITUDE","LONGITUDE"
1,41.6709918952829,-87.7324568962847
32,41.755832412403,-87.545349670582
50,41.7075695897648,-87.5685738570845
57,41.9128621248178,-87.7227234452095
64,41.7907868783739,-87.6016464917605
...
文件:SiteLocations_with_more_sites.csv
此文件具有与SiteLocations.csv
相同的格式,并且似乎列出与该文件相同的所有位置以及一些其他位置。
正如文件名所示,它只是网站列表的更新版本。
以下是该文件的示例。
"SITE_ID","LATITUDE","LONGITUDE"
1,41.6709918952829,-87.7324568962847
14,41.834243,-87.6238
22,41.6871654376343,-87.5393154841479
32,41.755832412403,-87.545349670582
50,41.7075695897648,-87.5685738570845
...
文件:TrainingData.csv
该文件包含用于建模的训练数据。
数据以非标准化的方式呈现。每行数据包含一组跨越多个位置的一小时的气象测量值以及该小时的每个位置的目标或结果。
措施包括:
- 时间信息,包括时间块,连续时间块内的索引,平均月份,星期几和一天中的小时。
- 风测量,如方向和速度。
- 温度测量,例如最小和最大环境温度。
- 压力测量,如最小和最大气压。
目标变量是不同物理位置的不同空气质量或污染测量的集合。
并非所有地点都有全天候测量,并非所有地点都与所有目标措施有关。此外,对于那些记录的变量,存在标记为 NA 的缺失值。
以下是该文件的示例。
"rowID","chunkID","position_within_chunk","month_most_common","weekday","hour","Solar.radiation_64","WindDirection..Resultant_1","WindDirection..Resultant_1018","WindSpeed..Resultant_1","WindSpeed..Resultant_1018","Ambient.Max.Temperature_14","Ambient.Max.Temperature_22","Ambient.Max.Temperature_50","Ambient.Max.Temperature_52","Ambient.Max.Temperature_57","Ambient.Max.Temperature_76","Ambient.Max.Temperature_2001","Ambient.Max.Temperature_3301","Ambient.Max.Temperature_6005","Ambient.Min.Temperature_14","Ambient.Min.Temperature_22","Ambient.Min.Temperature_50","Ambient.Min.Temperature_52","Ambient.Min.Temperature_57","Ambient.Min.Temperature_76","Ambient.Min.Temperature_2001","Ambient.Min.Temperature_3301","Ambient.Min.Temperature_6005","Sample.Baro.Pressure_14","Sample.Baro.Pressure_22","Sample.Baro.Pressure_50","Sample.Baro.Pressure_52","Sample.Baro.Pressure_57","Sample.Baro.Pressure_76","Sample.Baro.Pressure_2001","Sample.Baro.Pressure_3301","Sample.Baro.Pressure_6005","Sample.Max.Baro.Pressure_14","Sample.Max.Baro.Pressure_22","Sample.Max.Baro.Pressure_50","Sample.Max.Baro.Pressure_52","Sample.Max.Baro.Pressure_57","Sample.Max.Baro.Pressure_76","Sample.Max.Baro.Pressure_2001","Sample.Max.Baro.Pressure_3301","Sample.Max.Baro.Pressure_6005","Sample.Min.Baro.Pressure_14","Sample.Min.Baro.Pressure_22","Sample.Min.Baro.Pressure_50","Sample.Min.Baro.Pressure_52","Sample.Min.Baro.Pressure_57","Sample.Min.Baro.Pressure_76","Sample.Min.Baro.Pressure_2001","Sample.Min.Baro.Pressure_3301","Sample.Min.Baro.Pressure_6005","target_1_57","target_10_4002","target_10_8003","target_11_1","target_11_32","target_11_50","target_11_64","target_11_1003","target_11_1601","target_11_4002","target_11_8003","target_14_4002","target_14_8003","target_15_57","target_2_57","target_3_1","target_3_50","target_3_57","target_3_1601","target_3_4002","target_3_6006","target_4_1","target_4_50","target_4_57","target_4_1018","target_4_1601","target_4_2001","target_4_4002","target_4_4101","target_4_6006","target_4_8003","target_5_6006","target_7_57","target_8_57","target_8_4002","target_8_6004","target_8_8003","target_9_4002","target_9_8003"
1,1,1,10,"Saturday",21,0.01,117,187,0.3,0.3,NA,NA,NA,14.9,NA,NA,NA,NA,NA,NA,NA,NA,5.8,NA,NA,NA,NA,NA,NA,NA,NA,747,NA,NA,NA,NA,NA,NA,NA,NA,750,NA,NA,NA,NA,NA,NA,NA,NA,743,NA,NA,NA,NA,NA,2.67923294292042,6.1816228132982,NA,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,NA,2.38965627997991,NA,5.56815355612325,0.690015329704154,NA,NA,NA,NA,NA,NA,2.84349016287551,0.0920223353681394,1.69321097077376,0.368089341472558,0.184044670736279,0.368089341472558,0.276067006104418,0.892616653070952,1.74842437199465,NA,NA,5.1306307034019,1.34160578423204,2.13879182993514,3.01375212399952,NA,5.67928016629218,NA
2,1,2,10,"Saturday",22,0.01,231,202,0.5,0.6,NA,NA,NA,14.9,NA,NA,NA,NA,NA,NA,NA,NA,5.8,NA,NA,NA,NA,NA,NA,NA,NA,747,NA,NA,NA,NA,NA,NA,NA,NA,750,NA,NA,NA,NA,NA,NA,NA,NA,743,NA,NA,NA,NA,NA,2.67923294292042,8.47583334194495,NA,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,NA,1.99138023331659,NA,5.56815355612325,0.923259948195698,NA,NA,NA,NA,NA,NA,3.1011527019063,0.0920223353681394,1.94167127626774,0.368089341472558,0.184044670736279,0.368089341472558,0.368089341472558,1.73922213845783,2.14412041407765,NA,NA,5.1306307034019,1.19577906855465,2.72209869264472,3.88871241806389,NA,7.42675098668978,NA
3,1,3,10,"Saturday",23,0.01,247,227,0.5,1.5,NA,NA,NA,14.9,NA,NA,NA,NA,NA,NA,NA,NA,5.8,NA,NA,NA,NA,NA,NA,NA,NA,747,NA,NA,NA,NA,NA,NA,NA,NA,750,NA,NA,NA,NA,NA,NA,NA,NA,743,NA,NA,NA,NA,NA,2.67923294292042,8.92192983362627,NA,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,NA,1.7524146053186,NA,5.56815355612325,0.680296803933673,NA,NA,NA,NA,NA,NA,3.06434376775904,0.0920223353681394,2.52141198908702,0.460111676840697,0.184044670736279,0.368089341472558,0.368089341472558,1.7852333061419,1.93246904273093,NA,NA,5.13639545700122,1.40965825154816,3.11096993445111,3.88871241806389,NA,7.68373198968942,NA
4,1,4,10,"Sunday",0,0.01,219,218,0.2,1.2,NA,NA,NA,14,NA,NA,NA,NA,NA,NA,NA,NA,4.8,NA,NA,NA,NA,NA,NA,NA,NA,751,NA,NA,NA,NA,NA,NA,NA,NA,754,NA,NA,NA,NA,NA,NA,NA,NA,748,NA,NA,NA,NA,NA,2.67923294292042,5.09824561921501,NA,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,NA,2.38965627997991,NA,5.6776192223642,0.612267123540305,NA,NA,NA,NA,NA,NA,3.21157950434806,0.184044670736279,2.374176252498,0.460111676840697,0.184044670736279,0.368089341472558,0.276067006104418,1.86805340797323,2.08890701285676,NA,NA,5.21710200739181,1.47771071886428,2.04157401948354,3.20818774490271,NA,4.83124285639335,NA
5,1,5,10,"Sunday",1,0.01,2,216,0.2,0.3,NA,NA,NA,14,NA,NA,NA,NA,NA,NA,NA,NA,4.8,NA,NA,NA,NA,NA,NA,NA,NA,751,NA,NA,NA,NA,NA,NA,NA,NA,754,NA,NA,NA,NA,NA,NA,NA,NA,748,NA,NA,NA,NA,NA,2.67923294292042,4.87519737337435,NA,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,0.114975168664303,NA,2.31000107064725,NA,5.6776192223642,0.694874592589394,NA,NA,NA,NA,NA,NA,3.67169118118876,0.184044670736279,2.46619858786614,0.460111676840697,0.184044670736279,0.368089341472558,0.276067006104418,1.70241320431058,2.60423209091834,NA,NA,5.21710200739181,1.45826715677396,2.13879182993514,3.4998411762575,NA,4.62565805399363,NA
...
文件:SubmissionZerosExceptNAs.csv
此文件包含预测问题的提交样本。
每行指定在一段连续时间内针对给定小时的所有目标位置的每个目标度量的预测。
以下是该文件的示例。
"rowID","chunkID","position_within_chunk","hour","month_most_common","target_1_57","target_10_4002","target_10_8003","target_11_1","target_11_32","target_11_50","target_11_64","target_11_1003","target_11_1601","target_11_4002","target_11_8003","target_14_4002","target_14_8003","target_15_57","target_2_57","target_3_1","target_3_50","target_3_57","target_3_1601","target_3_4002","target_3_6006","target_4_1","target_4_50","target_4_57","target_4_1018","target_4_1601","target_4_2001","target_4_4002","target_4_4101","target_4_6006","target_4_8003","target_5_6006","target_7_57","target_8_57","target_8_4002","target_8_6004","target_8_8003","target_9_4002","target_9_8003"
193,1,193,21,10,0,0,-1e+06,0,0,0,0,0,0,0,-1e+06,0,-1e+06,0,0,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,0,0,0,0,0,0,0,0,0,-1e+06,-1e+06,0,0,0,0,-1e+06,0,-1e+06
194,1,194,22,10,0,0,-1e+06,0,0,0,0,0,0,0,-1e+06,0,-1e+06,0,0,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,0,0,0,0,0,0,0,0,0,-1e+06,-1e+06,0,0,0,0,-1e+06,0,-1e+06
195,1,195,23,10,0,0,-1e+06,0,0,0,0,0,0,0,-1e+06,0,-1e+06,0,0,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,0,0,0,0,0,0,0,0,0,-1e+06,-1e+06,0,0,0,0,-1e+06,0,-1e+06
196,1,196,0,10,0,0,-1e+06,0,0,0,0,0,0,0,-1e+06,0,-1e+06,0,0,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,0,0,0,0,0,0,0,0,0,-1e+06,-1e+06,0,0,0,0,-1e+06,0,-1e+06
197,1,197,1,10,0,0,-1e+06,0,0,0,0,0,0,0,-1e+06,0,-1e+06,0,0,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,-1e+06,0,0,0,0,0,0,0,0,0,-1e+06,-1e+06,0,0,0,0,-1e+06,0,-1e+06
...
构建预测问题
这个预测问题的很大一部分挑战是可以为建模设置问题的大量方法。
这是具有挑战性的,因为不清楚哪个框架可能是这个特定建模问题的最佳框架。
例如,下面是一些问题,可以引发关于如何构建问题的思考。
- 是否更好地归咎或忽略遗漏的观察结果?
- 以时间序列的天气观测或仅观察当前时间的观测结果是否更好?
- 是否更好地使用来自一个或多个源位置的天气观测来做出预测?
- 为每个位置设置一个模型或为所有位置设置一个模式更好吗?
- 每个预测时间有一个模型或者所有预测时间都有一个模型更好吗?
进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
- EMC 数据科学全球黑客马拉松(空气质量预测)
- 下载数据集
- 将所有东西放入随机森林:Ben Hamner 赢得空气质量预测黑客马拉松
- EMC 数据科学全球黑客马拉松(空气质量预测)的获奖代码
- 分区模型的一般方法?
摘要
在这篇文章中,您发现了 Kaggle 空气质量数据集,该数据集为复杂的时间序列预测提供了标准数据集。
具体来说,你学到了:
- 解决空气质量数据集的竞争和动机。
- 概述定义的预测问题及其涵盖的数据挑战。
- 可以下载并立即开始使用的免费数据文件的说明。
你有没有研究过这个数据集,或者你打算做什么?
在下面的评论中分享您的经历。
如何使用 Python 检查时间序列数据是否是平稳的
原文:
machinelearningmastery.com/time-series-data-stationary-python/
时间序列不同于更传统的分类和回归预测性建模问题。
时间结构为观察增加了顺序。这种强加的顺序意味着需要专门处理关于这些观察的一致性的重要假设。
例如,在建模时,假设观测的汇总统计量是一致的。在时间序列术语中,我们将此期望称为时间序列是静止的。
通过添加趋势,季节性和其他依赖于时间的结构,可以在时间序列中容易地违反这些假设。
在本教程中,您将了解如何使用 Python 检查时间序列是否固定。
完成本教程后,您将了解:
- 如何使用线图识别明显的静止和非平稳时间序列。
- 如何查看随时间变化的均值和方差等汇总统计量。
- 如何使用具有统计显着性的统计检验来检查时间序列是否静止。
让我们开始吧。
- 2017 年 2 月更新:修正了 p 值解释的拼写错误,增加了要点,使其更加清晰。
- 更新于 May / 2018 :改进了拒绝与拒绝统计测试的语言。
如何使用 Python 检查时间序列数据是否是固定的
照片由 Susanne Nilsson 保留,保留一些权利。
固定时间序列
静止时间序列中的观察结果不依赖于时间。
如果没有趋势或季节性影响,时间序列是静止。按时间序列计算的汇总统计量随时间变化是一致的,例如观察值的均值或方差。
当时间序列静止时,可以更容易建模。统计建模方法假定或要求时间序列是静止的以使其有效。
以下是静止的每日女性出生数据集的示例。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-total-female-births.csv', header=0)
series.plot()
pyplot.show()
运行该示例将创建以下图表。
每日女性出生数据集图
非定时时间序列
来自非平稳时间序列的观测显示了季节性影响,趋势和依赖于时间指数的其他结构。
像平均值和方差这样的汇总统计量会随着时间的推移而发生变化,从而使模型可能尝试捕获的概念发生偏差。
经典时间序列分析和预测方法涉及通过识别和消除趋势以及消除季节性影响来使非平稳时间序列数据静止。
下面是一个非静止的航空公司乘客数据集的示例,显示趋势和季节性组件。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('international-airline-passengers.csv', header=0)
series.plot()
pyplot.show()
运行该示例将创建以下图表。
非固定航空公司乘客数据集
固定时间序列的类型
平稳性的概念来自时间序列的理论研究,它在预测时是一个有用的抽象。
如果你深入研究这个话题,你可能会遇到一些更细微的平稳性概念。他们是:
他们是:
- 固定过程:生成一系列固定观测的过程。
- 固定模型:描述固定观测系列的模型。
- Trend Stationary :没有趋势的时间序列。
- 季节性文具:没有季节性的时间序列。
- 严格固定:静止过程的数学定义,特别是观测的联合分布对时移是不变的。
固定时间序列与预测
你应该让你的时间序列固定吗?
一般来说,是的。
如果您的时间序列中有明确的趋势和季节性,那么对这些组件进行建模,将其从观察中移除,然后在残差上训练模型。
如果我们将静态模型拟合到数据中,我们假设我们的数据是静止过程的实现。因此,我们分析的第一步应该是检查是否有任何趋势或季节性影响的证据,如果有,则删除它们。
- 第 122 页,介绍时间序列与 R 。
统计时间序列方法甚至现代机器学习方法将受益于数据中更清晰的信号。
但…
当经典方法失败时,我们转向机器学习方法。当我们想要更多或更好的结果时。我们不知道如何最好地模拟时间序列数据中的未知非线性关系,并且一些方法在处理非平稳观测或者问题的静态和非静态视图的某种混合时可以产生更好的表现。
这里的建议是将时间序列的属性视为静止或不作为另一个信息源,可以在使用机器学习方法时在时间序列问题中使用特征工程和特征选择。
检查平稳性
有许多方法可以检查时间序列(直接观察,残差,否则)是静止的还是非静止的。
- 看一下情节:您可以查看数据的时间序列图,并目视检查是否有任何明显的趋势或季节性。
- 摘要统计:您可以查看季节或随机分区数据的摘要统计量,并检查明显或显着的差异。
- 统计检验:您可以使用统计检验来检查是否满足或已经违反了平稳性的期望。
在上文中,我们已经将每日女性出生和航空旅客数据集分别定为静止和非静止,并且图表显示趋势和季节性成分明显缺乏和存在。
接下来,我们将看一个快速而肮脏的方法来计算和查看我们的时间序列数据集的摘要统计量,以检查它是否是静止的。
摘要统计
快速而肮脏的检查以确定您的时间序列是非静止的是查看摘要统计量。
您可以将时间序列拆分为两个(或更多)分区,并比较每个组的均值和方差。如果它们不同并且差异具有统计显着性,则时间序列可能是非平稳的。
接下来,让我们在 Daily Births 数据集上尝试这种方法。
每日出生数据集
因为我们正在研究均值和方差,所以我们假设数据符合高斯(也称为钟形曲线或正态)分布。
我们还可以通过观察我们观察的直方图来快速检查这一点。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-total-female-births.csv', header=0)
series.hist()
pyplot.show()
运行该示例绘制时间序列中的值的直方图。我们清楚地看到高斯分布的钟形曲线形状,也许右尾更长。
每日女性出生的直方图
接下来,我们可以将时间序列分成两个连续的序列。然后我们可以计算每组数字的均值和方差并比较这些数值。
from pandas import Series
series = Series.from_csv('daily-total-female-births.csv', header=0)
X = series.values
split = len(X) / 2
X1, X2 = X[0:split], X[split:]
mean1, mean2 = X1.mean(), X2.mean()
var1, var2 = X1.var(), X2.var()
print('mean1=%f, mean2=%f' % (mean1, mean2))
print('variance1=%f, variance2=%f' % (var1, var2))
运行此示例显示均值和方差值不同,但在同一个球场中。
mean1=39.763736, mean2=44.185792
variance1=49.213410, variance2=48.708651
接下来,让我们在 Airline Passengers 数据集上尝试相同的技巧。
航空公司乘客数据集
直接切入追逐,我们可以分割我们的数据集并计算每个组的均值和方差。
from pandas import Series
series = Series.from_csv('international-airline-passengers.csv', header=0)
X = series.values
split = len(X) / 2
X1, X2 = X[0:split], X[split:]
mean1, mean2 = X1.mean(), X2.mean()
var1, var2 = X1.var(), X2.var()
print('mean1=%f, mean2=%f' % (mean1, mean2))
print('variance1=%f, variance2=%f' % (var1, var2))
运行示例,我们可以看到均值和方差看起来非常不同。
我们有一个非平稳的时间序列。
mean1=182.902778, mean2=377.694444
variance1=2244.087770, variance2=7367.962191
也许。
让我们退一步,检查在这种情况下假设高斯分布是否有意义,将时间序列的值绘制为直方图。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('international-airline-passengers.csv', header=0)
series.hist()
pyplot.show()
运行该示例表明,值的分布确实看起来不像高斯,因此均值和方差值的意义不大。
这种观察的压扁分布可能是非平稳时间序列的另一个指标。
航空公司乘客的直方图
再次回顾时间序列的情节,我们可以看到有一个明显的季节性成分,看起来季节性成分正在增长。
这可能表明一个季节的指数增长。可以使用对数变换将指数变化平坦回到线性关系。
下面是具有时间序列的对数变换的相同直方图。
from pandas import Series
from matplotlib import pyplot
from numpy import log
series = Series.from_csv('international-airline-passengers.csv', header=0)
X = series.values
X = log(X)
pyplot.hist(X)
pyplot.show()
pyplot.plot(X)
pyplot.show()
运行该示例,我们可以看到更熟悉的高斯类或类似统一的值分布。
航空公司乘客的直方图记录
我们还创建了对数转换数据的线图,可以看到指数增长似乎减少了,但我们仍然有趋势和季节性元素。
航空公司乘客的线路图
我们现在可以计算对数变换数据集的值的均值和标准差。
from pandas import Series
from matplotlib import pyplot
from numpy import log
series = Series.from_csv('international-airline-passengers.csv', header=0)
X = series.values
X = log(X)
split = len(X) / 2
X1, X2 = X[0:split], X[split:]
mean1, mean2 = X1.mean(), X2.mean()
var1, var2 = X1.var(), X2.var()
print('mean1=%f, mean2=%f' % (mean1, mean2))
print('variance1=%f, variance2=%f' % (var1, var2))
运行示例显示了每组的平均值和标准偏差值,这些值又相似但不相同。
也许,仅从这些数字来看,我们就会说时间序列是静止的,但我们坚信在审查线图时并非如此。
mean1=5.175146, mean2=5.909206
variance1=0.068375, variance2=0.049264
这是一种快速而肮脏的方法,很容易被愚弄。
我们可以使用统计检验来检查两个高斯随机变量样本之间的差异是真实的还是统计的侥幸。我们可以探索统计显着性检验,例如 Student t 检验,但由于值之间的序列相关性,事情变得棘手。
在下一节中,我们将使用统计测试来明确评论单变量时间序列是否是静止的。
增强 Dickey-Fuller 测试
统计测试对您的数据做出了强有力的假设。它们只能用于通知零假设可被拒绝或未被拒绝的程度。必须解释结果才能使给定问题有意义。
然而,他们可以提供快速检查和确认证据,证明您的时间序列是静止的或非静止的。
增强 Dickey-Fuller 检验是一种称为单位根检验的统计检验。
单位根检验背后的直觉是它确定趋势定义时间序列的强度。
有许多单位根测试,Augmented Dickey-Fuller 可能是更广泛使用的之一。它使用自回归模型并优化跨多个不同滞后值的信息标准。
测试的零假设是时间序列可以由单位根表示,它不是静止的(具有一些时间相关的结构)。替代假设(拒绝零假设)是时间序列是静止的。
- 空假设(H0):如果未能被拒绝,则表明时间序列具有单位根,这意味着它是非平稳的。它有一些时间依赖的结构。
- 替代假设(H1):零假设被拒绝;它表明时间序列没有单位根,这意味着它是静止的。它没有时间依赖的结构。
我们使用测试中的 p 值来解释这个结果。低于阈值的 p 值(例如 5%或 1%)表明我们拒绝零假设(静止),否则高于阈值的 p 值表明我们未能拒绝零假设(非静止)。
- p 值&gt; 0.05 :未能拒绝原假设(H0),数据具有单位根并且是非平稳的。
- p 值&lt; = 0.05 :拒绝原假设(H0),数据没有单位根并且是静止的。
下面是在 Daily Female Births 数据集上计算 Augmented Dickey-Fuller 测试的示例。 statsmodels 库提供实现测试的 adfuller()函数。
from pandas import Series
from statsmodels.tsa.stattools import adfuller
series = Series.from_csv('daily-total-female-births.csv', header=0)
X = series.values
result = adfuller(X)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical Values:')
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value))
运行该示例将打印测试统计值-4。这个统计量越负,我们就越有可能拒绝零假设(我们有一个固定的数据集)。
作为输出的一部分,我们得到一个查找表,以帮助确定 ADF 统计量。我们可以看到,我们的统计值-4 小于-3.449 的值,1%。
这表明我们可以拒绝具有小于 1%的显着性水平的零假设(即,结果是统计侥幸的低概率)。
拒绝原假设意味着该过程没有单位根,反过来,时间序列是静止的或没有时间依赖的结构。
ADF Statistic: -4.808291
p-value: 0.000052
Critical Values:
5%: -2.870
1%: -3.449
10%: -2.571
我们可以在 Airline Passenger 数据集上执行相同的测试。
from pandas import Series
from statsmodels.tsa.stattools import adfuller
series = Series.from_csv('international-airline-passengers.csv', header=0)
X = series.values
result = adfuller(X)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical Values:')
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value))
运行该示例给出了与上面不同的图片。检验统计量是正的,这意味着我们不太可能拒绝零假设(它看起来是非平稳的)。
将测试统计量与临界值进行比较,看起来我们不得不拒绝零假设,即时间序列是非平稳的并且具有时间依赖性结构。
ADF Statistic: 0.815369
p-value: 0.991880
Critical Values:
5%: -2.884
1%: -3.482
10%: -2.579
让我们再次对数据集进行日志转换,使值的分布更加线性,更好地满足此统计检验的预期。
from pandas import Series
from statsmodels.tsa.stattools import adfuller
from numpy import log
series = Series.from_csv('international-airline-passengers.csv', header=0)
X = series.values
X = log(X)
result = adfuller(X)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value))
运行该示例显示测试统计量的负值。
我们可以看到该值大于临界值,这意味着我们不能拒绝零假设,反过来说时间序列是非平稳的。
ADF Statistic: -1.717017
p-value: 0.422367
5%: -2.884
1%: -3.482
10%: -2.579
摘要
在本教程中,您了解了如何使用 Python 检查时间序列是否固定。
具体来说,你学到了:
- 时间序列数据静止用于统计建模方法甚至一些现代机器学习方法的重要性。
- 如何使用线图和基本摘要统计来检查时间序列是否静止。
- 如何计算和解释统计显着性检验以检查时间序列是否静止。
您对固定和非固定时间序列或此帖有任何疑问吗?
在下面的评论中提出您的问题,我会尽力回答。
将 Python 用于时间序列数据可视化
原文:
machinelearningmastery.com/time-series-data-visualization-with-python/
使用 Python 绘制时间序列数据的 6 种方法
时间序列自然适用于可视化。
随着时间的推移观察的线图很受欢迎,但是您可以使用一套其他图来了解有关您的问题的更多信息。
您对数据的了解越多,就越有可能开发出更好的预测模型。
在本教程中,您将发现可用于使用 Python 可视化时间序列数据的 6 种不同类型的图。
具体来说,完成本教程后,您将了解:
- 如何用线图,滞后图和自相关图来探索时间序列的时间结构。
- 如何使用直方图和密度图来理解观测的分布。
- 如何使用箱形和须状图以及热图绘制来区分间隔内的分布变化。
你最喜欢的时间序列图是否缺失?
请在评论中告诉我。
让我们开始吧。
时间序列可视化
可视化在时间序列分析和预测中起着重要作用。
原始样本数据的图可以提供有价值的诊断,以识别可影响模型选择的时间结构,如趋势,周期和季节性。
问题在于时间序列预测领域的许多新手都以线图停止。
在本教程中,我们将介绍可以在您自己的时间序列数据上使用的 6 种不同类型的可视化。他们是:
- 线图。
- 直方图和密度图。
- 盒子和晶须图。
- 热图。
- 滞后图或散点图。
- 自相关图。
重点是单变量时间序列,但是当您在每个时间步进行多次观察时,这些技术同样适用于多变量时间序列。
接下来,让我们看一下我们将在本教程中用于演示时间序列可视化的数据集。
最低每日温度数据集
该数据集描述了澳大利亚墨尔本市 10 年(1981-1990)的最低日常温度。
单位为摄氏度,有 3,650 个观测值。数据来源被称为澳大利亚气象局。
下载数据集并将其放在当前工作目录中,文件名为“ daily-minimum-Temperats.sv ”。
注意:下载的文件包含一些问号(“?”)字符,必须先将其删除才能使用数据集。在文本编辑器中打开文件并删除“?”字符。同时删除文件中的任何页脚信息。
下面是将数据集加载为 Panda 系列的示例。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
print(series.head())
运行该示例将加载数据集并打印前 5 行。
Date
1981-01-01 20.7
1981-01-02 17.9
1981-01-03 18.8
1981-01-04 14.6
1981-01-05 15.8
Name: Temp, dtype: float64
1.时间序列线图
时间序列的第一个,也许是最流行的可视化是线图。
在该图中,时间在 x 轴上显示,沿 y 轴具有观察值。
下面是将最小每日温度数据集的 Pandas 系列直接可视化为线图的示例。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
series.plot()
pyplot.show()
运行该示例会创建一个线图。
最低每日温度线图
线图非常密集。
有时它可以帮助改变线条图的风格;例如,使用虚线或点。
下面是将线条样式更改为黑点而不是连接线的示例( style =‘k。’ 参数)。
我们可以通过将样式设置为’ k- '来更改此示例以使用虚线。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
series.plot(style='k.')
pyplot.show()
运行该示例使用点而不是连接线重新创建相同的线图。
最低每日温度点图
比较相同区间的线图可能会有所帮助,例如每天,每月,每年和每年。
最低每日温度数据集跨越 10 年。我们可以按年度对数据进行分组,并创建每年的线图以进行直接比较。
以下示例显示了如何执行此操作。首先,观察按年分组( series.groupby(TimeGrouper(‘A’)))。
然后枚举这些组,并将每年的观察结果存储为新 DataFrame 中的列。
最后,创建了这个设计的 DataFrame 的图,每个列都可视化为子图,其中移除了图例以减少杂乱。
from pandas import Series
from pandas import DataFrame
from pandas import TimeGrouper
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
groups = series.groupby(TimeGrouper('A'))
years = DataFrame()
for name, group in groups:
years[name.year] = group.values
years.plot(subplots=True, legend=False)
pyplot.show()
运行该示例创建 10 个线图,从 1981 年的顶部开始每年一个,在底部的 1990 年,每个线图的长度为 365 天。
最低每日温度年线图
2.时间序列直方图和密度图
另一个重要的可视化是观察本身的分布。
这意味着没有时间排序的值的图。
一些线性时间序列预测方法假设观察结果表现良好(即钟形曲线或正态分布)。可以使用统计假设检验等工具明确检查。但是,绘图可以在原始观察和任何类型的数据变换执行后提供有用的第一次观察。
下面的示例创建最小每日温度数据集中观测值的直方图。直方图将值分组到箱中,并且每个箱中的观测频率或计数可以提供对观测的基础分布的洞察。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
series.hist()
pyplot.show()
运行该示例显示看起来强烈高斯的分布。绘图功能根据数据中值的扩展自动选择分档的大小。
最低每日温度直方图
通过使用密度图,我们可以更好地了解观测分布的形状。
这就像直方图,除了一个函数用于拟合观察的分布,一个漂亮,平滑的线用于总结这个分布。
以下是最低每日温度数据集的密度图示例。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
series.plot(kind='kde')
pyplot.show()
运行该示例将创建一个图表,该图表提供了更清晰的观察分布摘要。我们可以看到,分布可能有点不对称,也许有点像高斯。
看到像这样的分布可能会建议以后探索统计假设检验,以正式检查分布是否是高斯分布,以及可能重新分配分布的数据准备技术,如 Box-Cox 变换。
最低每日温度密度图
3.按时间间隔划分的时间序列框和晶须图
直方图和密度图提供了对所有观测值分布的深入了解,但我们可能对按时间间隔的值分布感兴趣。
另一种有助于总结观察分布的图是盒子和须状图。该图绘制了一个围绕数据的第 25 和第 75 百分位的框,其捕获了中间 50%的观察结果。在第 50 百分位(中位数)绘制一条线,并在方框的上方和下方绘制晶须,以总结观察的一般范围。对于数据的胡须或范围之外的异常值绘制点。
可以为时间序列中的每个间隔创建框和晶须图,例如年,月或天。
下面是按年度对最低每日温度数据集进行分组的示例,如上图中的示例所示。然后每年创建一个盒子和胡须图,并排列并排以进行直接比较。
from pandas import Series
from pandas import DataFrame
from pandas import TimeGrouper
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
groups = series.groupby(TimeGrouper('A'))
years = DataFrame()
for name, group in groups:
years[name.year] = group.values
years.boxplot()
pyplot.show()
以一致的间隔比较盒子和须状图是一种有用的工具。在一个区间内,它可以帮助发现异常值(胡须上方或下方的点)。
在这几年的间隔期间,我们可以查找可以建模的多年趋势,季节性和其他结构信息。
每年最低温度箱和晶须图
我们也可能对一年内数月的价值分布感兴趣。
下面的示例创建了 12 个盒子和须状图,一个用于 1990 年的每个月,即数据集中的最后一年。
在该示例中,首先,仅提取 1990 年的观测值。
然后,观察按月分组,每个月作为列添加到新的 DataFrame 中。
最后,为新构造的 DataFrame 中的每个月 - 列创建一个框和胡须图。
from pandas import Series
from pandas import DataFrame
from pandas import TimeGrouper
from matplotlib import pyplot
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
one_year = series['1990']
groups = one_year.groupby(TimeGrouper('M'))
months = concat([DataFrame(x[1].values) for x in groups], axis=1)
months = DataFrame(months)
months.columns = range(1,13)
months.boxplot()
pyplot.show()
运行这个例子创建了 12 个盒子和胡须图,显示了从 1 月份的南半球夏季到年中的南半球冬季,以及再次回到夏季,一年中最低温度分布的显着变化。
最低每日温度每月盒子和晶须图
4.时间序列热图
可以将数字矩阵绘制为表面,其中矩阵的每个单元格中的值被赋予唯一的颜色。
这被称为热图,因为较大的值可以用较暖的颜色(黄色和红色)绘制,较小的值可以用较冷的颜色(蓝色和绿色)绘制。
像盒子和胡须图一样,我们可以使用热图比较间隔之间的观察结果。
在最低每日温度的情况下,观测值可以排列成年 - 列和日 - 行的矩阵,每天的单元格温度最低。然后可以绘制该矩阵的热图。
以下是创建最低每日温度数据的热图的示例。使用 matplotlib 库中的 matshow()函数,因为没有直接在 Pandas 中提供热图支持。
为方便起见,矩阵是旋转(转置),因此每行代表一年,每列代表一天。这提供了更直观,从左到右的数据布局。
from pandas import Series
from pandas import DataFrame
from pandas import TimeGrouper
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
groups = series.groupby(TimeGrouper('A'))
years = DataFrame()
for name, group in groups:
years[name.year] = group.values
years = years.T
pyplot.matshow(years, interpolation=None, aspect='auto')
pyplot.show()
该图显示了这些年中的较冷的最低温度以及这些年的开始和结束时较温暖的最低温度,以及它们之间的所有衰落和复杂性。
每日最低温度年热图
与上面的方框和胡须图示例一样,我们也可以比较一年内的月份。
下面是单热图的示例,比较 1990 年的一年中的几个月。每列代表一个月,行代表从 1 到 31 的月份日期。
from pandas import Series
from pandas import DataFrame
from pandas import TimeGrouper
from matplotlib import pyplot
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
one_year = series['1990']
groups = one_year.groupby(TimeGrouper('M'))
months = concat([DataFrame(x[1].values) for x in groups], axis=1)
months = DataFrame(months)
months.columns = range(1,13)
pyplot.matshow(months, interpolation=None, aspect='auto')
pyplot.show()
运行该示例显示了每月在缩放的月度级别上看到的相同宏观趋势。
我们还可以在图的底部看到一些白色斑块。对于那些少于 31 天的月份而言,这是缺失的数据,而二月份在 1990 年的 28 天内相当异常。
每日最低温度月热图
5.时间序列滞后散点图
时间序列建模假定观察与先前观察之间的关系。
先前在时间序列中的观察被称为滞后,在前一时间步骤的观察被称为 lag1,在两个时间步骤之前的观察被称为 lag2,依此类推。
探索每个观测与该观测滞后之间关系的有用类型的图称为散点图。
Pandas 有一个内置函数,正好称为滞后图。它绘制了在 x 轴上的时间 t 处的观察和在 y 轴上的 lag1 观察(t-1)。
- 如果点沿着从图的左下角到右上角的对角线聚集,则表明正相关关系。
- 如果点沿着从左上角到右下角的对角线聚集,则表明负相关关系。
- 两种关系都很好,因为它们可以建模。
对角线更紧密的点表明关系更强,而且线上更多的分布表明关系更弱。
中间的一个球或横跨该地块的一个球表明弱关系或无关系。
下面是最低每日温度数据集的滞后图的示例。
from pandas import Series
from matplotlib import pyplot
from pandas.tools.plotting import lag_plot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
lag_plot(series)
pyplot.show()
通过运行该示例创建的图显示了观察值与其 lag1 值之间的相对强的正相关性。
最低每日温度滞后图
我们可以重复这个过程进行观察和任何滞后值。也许在上周,上个月或去年的同一时间观察,或者我们可能希望探索的任何其他领域特定知识。
例如,我们可以使用前七天中的每个值为观察创建散点图。以下是最低每日温度数据集的示例。
首先,创建一个新的 DataFrame,并将滞后值作为新列。列名称相应。然后创建一个新的子图,用不同的滞后值绘制每个观察。
from pandas import Series
from pandas import DataFrame
from pandas import concat
from matplotlib import pyplot
from pandas.plotting import scatter_matrix
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
values = DataFrame(series.values)
lags = 7
columns = [values]
for i in range(1,(lags + 1)):
columns.append(values.shift(i))
dataframe = concat(columns, axis=1)
columns = ['t+1']
for i in range(1,(lags + 1)):
columns.append('t-' + str(i))
dataframe.columns = columns
pyplot.figure(1)
for i in range(1,(lags + 1)):
ax = pyplot.subplot(240 + i)
ax.set_title('t+1 vs t-' + str(i))
pyplot.scatter(x=dataframe['t+1'].values, y=dataframe['t-'+str(i)].values)
pyplot.show()
运行该示例表明观察与其 lag1 值之间的最强关系,但通常与上周的每个值具有良好的正相关性。
最低每日温度散点图
6.时间序列自相关图
我们可以量化观察与其滞后之间关系的强度和类型。
在统计中,这称为相关,当根据时间序列中的滞后值计算时,称为自相关(自相关)。
在两组数字之间计算的相关值,例如观察值和它们的 lag1 值,得到-1 和 1 之间的数字。该数字的符号分别表示负相关或正相关。接近零的值表示弱相关,而接近-1 或 1 的值表示强相关。
可以针对每个观察和不同的滞后值计算称为相关系数的相关值。一旦计算出来,就可以创建一个图,以帮助更好地理解这种关系如何随着滞后而变化。
这种类型的图称为自相关图,Pandas 提供内置的此功能,称为 autocorrelation_plot()函数。
以下示例为最低每日温度数据集创建自相关图:
from pandas import Series
from matplotlib import pyplot
from pandas.tools.plotting import autocorrelation_plot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
autocorrelation_plot(series)
pyplot.show()
得到的图显示沿 x 轴的滞后和 y 轴的相关性。提供虚线表示这些线上方的任何相关值具有统计显着性(有意义)。
我们可以看到,对于最低每日温度数据集,我们看到强烈的负相关和正相关的周期。这捕获了观察与过去观察在相同和相反季节或一年中的时间的关系。像本例中所见的正弦波是数据集中季节性的强烈信号。
最低每日温度自相关图
进一步阅读
本节提供了一些资源,可用于进一步阅读绘图时间序列以及本教程中使用的 Pandas 和 Matplotlib 函数。
摘要
在本教程中,您了解了如何在 Python 中探索和更好地理解时间序列数据集。
具体来说,你学到了:
- 如何探索与线,散点和自相关图的时间关系。
- 如何用直方图和密度图探索观测分布。
- 如何用箱形和晶须和热图绘制来探索观测分布的变化。
您对绘制时间序列数据或本教程有任何疑问吗?
在评论中提出您的问题,我会尽力回答。