如何将时间序列数据分解为趋势和季节性
原文:
machinelearningmastery.com/decompose-time-series-data-trend-seasonality/
时间序列分解涉及将一系列视为水平,趋势,季节性和噪声分量的组合。
分解提供了一个有用的抽象模型,用于一般地考虑时间序列,以及更好地理解时间序列分析和预测中的问题。
在本教程中,您将发现时间序列分解以及如何使用 Python 自动将时间序列拆分为其组件。
完成本教程后,您将了解:
- 时间序列分析分析方法及其如何帮助预测。
- 如何在 Python 中自动分解时间序列数据。
- 如何分解加法和乘法时间序列问题并绘制结果。
让我们开始吧。
如何将时间序列数据分解为趋势和季节性
摄影: Terry Robinson ,保留一些权利。
时间序列组件
选择预测方法的有用抽象是将时间序列分解为系统和非系统组件。
- Systematic :具有一致性或重复性的时间序列的组成部分,可以进行描述和建模。
- Non-Systematic :无法直接建模的时间序列的组成部分。
给定的时间序列被认为包括三个系统组件,包括水平,趋势,季节性和一个称为噪声的非系统组件。
这些组件定义如下:
- 等级:系列中的平均值。
- 趋势:系列中的增加或减少值。
- 季节性:系列中重复的短期周期。
- Noise :系列中的随机变化。
结合时间序列组件
一系列被认为是这四个组成部分的集合或组合。
所有系列都有水平和噪音。趋势和季节性组件是可选的。
将组件视为加法或乘法组合是有帮助的。
添加模型
添加剂模型表明组分如下加在一起:
y(t) = Level + Trend + Seasonality + Noise
添加剂模型是线性的,其中随时间的变化始终以相同的量进行。
线性趋势是直线。
线性季节性具有相同的频率(周期宽度)和幅度(周期的高度)。
乘法模型
乘法模型表明组件乘以如下:
y(t) = Level * Trend * Seasonality * Noise
乘法模型是非线性的,例如二次或指数。变化随时间增加或减少。
非线性趋势是曲线。
非线性季节性随时间具有增加或减少的频率和/或幅度。
分解为工具
这是一个有用的抽象。
分解主要用于时间序列分析,作为分析工具,它可用于为您的问题提供预测模型。
它提供了一种思考时间序列预测问题的结构化方法,通常在建模复杂性方面,特别是在如何最佳地捕获给定模型中的每个组件方面。
在数据准备,模型选择和模型调整期间,您可能需要考虑和解决这些组件中的每一个。您可以在对趋势进行建模并从数据中减去趋势时明确地解决它,或者通过为算法提供足够的历史记录来隐式地解决趋势(如果趋势可能存在)。
您可能会或可能无法将您的特定时间序列干净或完美地分解为添加剂或乘法模型。
现实世界的问题是混乱和嘈杂。可能存在加法和乘法组件。可能会出现增长趋势,随后呈下降趋势。可能存在与重复季节性成分混合的非重复循环。
然而,这些抽象模型提供了一个简单的框架,您可以使用它来分析数据并探索思考和预测问题的方法。
自动时间序列分解
有一些方法可以自动分解的时间序列。
statsmodels 库在名为 seasonal_decompose()的函数中提供了朴素或经典分解方法的实现。它要求您指定模型是加法还是乘法。
两者都会产生结果,在解释结果时必须小心谨慎。对时间序列图和一些汇总统计量的回顾通常可以是一个很好的开始,可以了解您的时间序列问题是否具有加性或乘法性。
seasonal_decompose()
函数返回结果对象。结果对象包含用于从分解中访问四个数据的数组。
例如,下面的代码段显示了假设添加模型如何将一系列分解为趋势,季节和残差分量。
结果对象提供对趋势和季节性系列的访问作为数组。它还提供对残差的访问,残差是趋势之后的时间序列,并且删除了季节性组件。最后,还存储原始数据或观察数据。
from statsmodels.tsa.seasonal import seasonal_decompose
series = ...
result = seasonal_decompose(series, model='additive')
print(result.trend)
print(result.seasonal)
print(result.resid)
print(result.observed)
通过调用plot()
函数,可以直接从结果对象绘制这四个时间序列。例如:
from statsmodels.tsa.seasonal import seasonal_decompose
from matplotlib import pyplot
series = ...
result = seasonal_decompose(series, model='additive')
result.plot()
pyplot.show()
我们来看一些例子。
添加剂分解
我们可以创建一个时间序列,包括从 1 到 99 的线性增长趋势和一些随机噪声,并将其分解为一个加法模型。
因为时间序列是设计的并且是作为一组数字提供的,所以我们必须指定观察的频率( freq = 1 参数)。如果提供了 Pandas Series 对象,则不需要此参数。
from random import randrange
from pandas import Series
from matplotlib import pyplot
from statsmodels.tsa.seasonal import seasonal_decompose
series = [i+randrange(10) for i in range(1,100)]
result = seasonal_decompose(series, model='additive', freq=1)
result.plot()
pyplot.show()
运行该示例将创建系列,执行分解,并绘制 4 个结果系列。
我们可以看到整个系列被视为趋势组件而且没有季节性。
加性模型分解图
我们还可以看到残差图显示为零。这是一个很好的例子,其中朴素或经典的分解无法将我们从线性趋势中添加的噪声分开。
朴素分解方法很简单,并且有更高级的分解,例如使用 Loess 或 STL 分解进行季节性和趋势分解。
使用自动分解方法时需要谨慎和健康的怀疑态度。
乘法分解
我们可以将二次时间序列设计为从 1 到 99 的时间步长的平方,然后假设乘法模型将其分解。
from pandas import Series
from matplotlib import pyplot
from statsmodels.tsa.seasonal import seasonal_decompose
series = [i**2.0 for i in range(1,100)]
result = seasonal_decompose(series, model='multiplicative', freq=1)
result.plot()
pyplot.show()
运行这个例子,我们可以看到,就像在附加情况下一样,趋势很容易被提取并且完全表征时间序列。
乘法模型分解图
指数变化可以通过数据变换线性变化。在这种情况下,通过取平方根可以使二次趋势成为线性。通过采用自然对数,可以使季节性的指数增长成线性。
同样,将分解视为一种潜在有用的分析工具非常重要,但要考虑探索可以应用于您的问题的许多不同方式,例如转换后的数据或残差模型错误。
让我们看一下真实世界的数据集。
航空公司乘客数据集
航空公司乘客数据集描述了一段时间内航空公司乘客的总数。
这些单位是数千名航空公司乘客的数量。从 1949 年到 1960 年,每月有 144 次观察。
了解更多信息并从数据市场下载数据集。
使用文件名“ airline-passengers.csv ”将数据集下载到当前工作目录。
首先,让我们绘制原始观察图。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
series.plot()
pyplot.show()
回顾线图,它表明可能存在线性趋势,但很难确定是否会引人注目。还有季节性,但周期的幅度(高度)似乎在增加,这表明它是乘法的。
航空公司乘客数据集的情节
我们将假设一个乘法模型。
以下示例将航空公司乘客数据集分解为乘法模型。
from pandas import Series
from matplotlib import pyplot
from statsmodels.tsa.seasonal import seasonal_decompose
series = Series.from_csv('airline-passengers.csv', header=0)
result = seasonal_decompose(series, model='multiplicative')
result.plot()
pyplot.show()
运行该示例绘制观察,趋势,季节和剩余时间序列。
我们可以看到从该系列中提取的趋势和季节性信息似乎是合理的。残差也很有趣,显示了该系列早期和晚期的高度可变性。
航空旅客数据集的乘法分解
进一步阅读
本节列出了一些用于进一步阅读时间序列分解的资源。
- 第 2.2 节时间序列组件, R 实用时间序列预测:动手指南。
- 第 6.3 节,经典分解,预测:原则和实践
摘要
在本教程中,您发现了时间序列分解以及如何使用 Python 分解时间序列数据。
具体来说,你学到了:
- 将时间序列分解为水平,趋势,季节性和噪声的结构。
- 如何使用 Python 自动分解时间序列数据集。
- 如何分解加法或乘法模型并绘制结果。
您对时间序列分解或本教程有任何疑问吗?
在下面的评论中提出您的问题,我会尽力回答。
如何用 ARCH 和 GARCH 为时间序列预测建模波动率
原文:
machinelearningmastery.com/develop-arch-and-garch-models-for-time-series-forecasting-in-python/
当使用 ARIMA 等经典方法对时间序列建模时,方差或波动率随时间的变化可能会导致问题。
ARCH 或自回归条件异方差性方法提供了一种模拟时间序列变化的方法,该时间序列是时间相关的,例如增加或减少波动率。这种方法的扩展名为 GARCH 或广义自回归条件异方差,允许该方法支持时间相关波动率的变化,例如增加和减少同一系列中的波动率。
在本教程中,您将发现 ARCH 和 GARCH 模型,用于预测时间序列的方差。
完成本教程后,您将了解:
- 时间序列中的方差问题以及 ARCH 和 GARCH 模型的需求。
- 如何配置 ARCH 和 GARCH 模型。
- 如何在 Python 中实现 ARCH 和 GARCH 模型。
让我们开始吧。
如何开发用于 Python 时间序列预测的 ARCH 和 GARCH 模型
照片由 Murray Foubister ,保留一些权利。
教程概述
本教程分为五个部分;他们是:
- 方差问题
- 什么是 ARCH 模型?
- 什么是 GARCH 模型?
- 如何配置 ARCH 和 GARCH 模型
- Python 中的 ARCH 和 GARCH 模型
方差问题
可以针对单变量时间序列数据开发自回归模型,该数据是静止的(AR),具有趋势(ARIMA),并且具有季节性成分(SARIMA)。
这些自回归模型不建模的单变量时间序列的一个方面是方差随时间的变化。
经典地,方差的适度变化的时间序列有时可以使用功率变换来调整,例如通过采用 Log 或使用 Box-Cox 变换。
有一些时间序列,方差随时间变化一致。在金融领域的时间序列的背景下,这将被称为增加和减少波动率。
在方差以系统方式增加的时间序列中,例如增加趋势,该系列的这种性质称为异方差性。这是统计量中的一个奇特的词汇,意味着整个系列的变化或不等方差。
如果方差的变化可以随时间相关,则可以使用自回归过程(例如 ARCH)对其进行建模。
什么是 ARCH 模型?
自回归条件异方差性或 ARCH,是一种明确模拟时间序列中随时间变化的方法。
具体地,ARCH 方法将时间步长的方差建模为来自平均过程(例如,零均值)的残差的函数。
Engle(1982)引入的 ARCH 过程明确地认识到无条件和条件方差之间的差异,允许后者随着时间的推移而变化,作为过去错误的函数。
- 广义自回归条件异方差,1986。
必须指定滞后参数以定义要包括在模型中的先前残留错误的数量。使用 GARCH 模型的符号(稍后讨论),我们可以将此参数称为“q
”。最初,这个参数被称为“p
”,在本教程后面使用的 arch Python 包中也被称为“p
”。
- q :包含在 ARCH 模型中的滞后平方残差的数量。
一个普遍接受的 ARCH 模型的表示法是用 q 参数 ARCH(q)指定 ARCH()函数;例如,ARCH(1)将是一阶 ARCH 模型。
该方法期望该系列是固定的,而不是方差的变化,这意味着它没有趋势或季节性成分。 ARCH 模型用于预测未来时间步的方差。
[ARCH]是平均零,连续不相关的过程,具有以过去为条件的非常数方差,但是具有恒定的无条件方差。对于此类流程,最近的过去提供了有关一期预测差异的信息。
- 具有英国通货膨胀方差估计的自回归条件异方差,1982。
在实践中,这可以用于在使用另一个自回归模型(例如 ARMA 或类似物)之后对残差的预期方差进行建模。
该模型应仅适用于不相关且不包含趋势或季节变化的预白化残差序列{e_t},例如可在拟合满意的 SARIMA 模型后获得。
- 第 148 页,入门时间序列与 R ,2009。
什么是 GARCH 模型?
广义自回归条件异方差性(GARCH)是 ARCH 模型的扩展,它将移动平均分量与自回归分量结合在一起。
具体地,该模型包括滞后方差项(例如,如果对另一个过程的白噪声残余误差进行建模,则观察)以及来自平均过程的滞后残差。
移动平均分量的引入允许模型既模拟随时间变化的条件变化以及随时间变化的变化。例子包括条件增加和方差减少。
因此,该模型引入了一个新参数“p”,它描述了滞后方差项的数量:
- p :GARCH 模型中包含的滞后变化数。
- q :要包含在 GARCH 模型中的滞后残差的数量。
GARCH 模型的普遍接受的符号是用p
和q
参数 GARCH(p,q)指定 GARCH()函数;例如,GARCH(1,1)将是一阶 GARCH 模型。
GARCH 模型包含 ARCH 模型,其中 GARCH(0,q)等效于 ARCH(q)模型。
对于 p = 0,该过程简化为 ARCH(q)过程,并且对于 p = q = 0,E(t)仅为白噪声。在 ARCH(q)过程中,条件方差仅被指定为过去样本方差的线性函数,而 GARCH(p,q)过程也允许滞后条件方差进入。这对应于某种自适应学习机制。
- 广义自回归条件异方差,1986。
与 ARCH 一样,GARCH 预测未来的方差并期望该系列是固定的,而不是方差的变化,这意味着它没有趋势或季节性成分。
如何配置 ARCH 和 GARCH 模型
ARCH 模型的配置最好在 ACF 和 PACF 时间序列方差图的背景下理解。
这可以通过从系列中的每个观察值中减去平均值并对结果求平方来实现,或者如果您已经在处理来自另一个模型的白噪声残差,则可以通过平方观察来实现。
如果相关图看起来是白噪声[…],那么可以通过查看平方值的相关图来检测波动率,因为平方值等于方差(假设系列被调整为具有零均值)。
- 第 146-147 页, R 的入门时间序列,2009 年。
然后可以解释 ACF 和 PACF 图以估计 p 和 q 的值,其方式与对 ARMA 模型所做的类似。
有关如何执行此操作的详细信息,请参阅帖子:
Python 中的 ARCH 和 GARCH 模型
在本节中,我们将了解如何使用 arch 库在 Python 中开发 ARCH 和 GARCH 模型。
首先,让我们准备一个可用于这些示例的数据集。
测试数据集
我们可以使用受控的方差模型创建数据集。
最简单的情况是一系列随机噪声,其中均值为零,方差从 0.0 开始并稳步增加。
我们可以使用 gauss()函数在 Python 中实现这一点,该函数生成具有指定均值和标准差的高斯随机数。
# create dataset
data = [gauss(0, i*0.01) for i in range(1,100+1)]
我们可以绘制数据集,以了解方差线性变化的外观。下面列出了完整的示例。
# create a simple white noise with increasing variance
from random import gauss
from random import seed
from matplotlib import pyplot
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# plot
pyplot.plot(data)
pyplot.show()
运行该示例将创建并绘制数据集。我们可以看到系列过程中方差的明显变化。
具有增大的方差的数据集线图
自相关
我们知道人为数据集的方差存在自相关。
不过,我们可以看一下自相关图来证实这种期望。下面列出了完整的示例。
# check correlations of squared observations
from random import gauss
from random import seed
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_acf
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# square the dataset
squared_data = [x**2 for x in data]
# create acf plot
plot_acf(squared_data)
pyplot.show()
运行该示例会创建平方观测值的自相关图。我们看到方差与大约 15 个滞后时间步长之间存在显着的正相关。
这可能会为 ARCH 模型中的参数提供合理的值。
具有增大方差的数据的自相关图
ARCH 模型
开发 ARCH 模型包括三个步骤:
- 定义模型
- 适合模型
- 做一个预测。
在拟合和预测之前,我们可以将数据集拆分为训练和测试集,以便我们可以将模型拟合到训练上并评估其在测试集上的表现。
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
可以通过调用 arch_model()函数来定义模型。我们可以为该系列的平均值指定一个模型:在这种情况下, mean =‘Zero’ 是一个合适的模型。然后我们可以指定方差的模型:在这种情况下 vol =‘ARCH’。我们还可以为 ARCH 模型指定滞后参数:在这种情况下 p = 15 。
注意,在 arch 库中,ARCH / GARCH 的p
和q
参数的名称已被颠倒。
# define model
model = arch_model(train, mean='Zero', vol='ARCH', p=15)
通过调用 fit()函数,可以使模型适合数据。此功能有很多选项,但默认设置足以让您入门。这将返回一个拟合模型。
# fit model
model_fit = model.fit()
最后,我们可以通过在拟合模型上调用 forecast()函数来做出预测。我们可以指定预测的范围。
在这种情况下,我们将预测数据集的最后 10 个时间步的方差,并从模型的训练中扣除它们。
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
我们可以将所有这些结合在一起;下面列出了完整的示例。
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='ARCH', p=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
运行该示例定义并拟合模型,然后预测数据集的最后 10 个时间步的方差。
创建线图,将预期方差系列与预测方差进行比较。虽然模型没有调整,但预测的方差看起来合理。
用 ARCH 预测方差的线性图到预测方差
GARCH 模型
我们可以使用 arch 库轻松地拟合 GARCH 模型。
arch_model()
函数可以指定 GARCH 而不是 ARCH 模型 vol ='GARCH’以及两者的滞后参数。
# define model
model = arch_model(train, mean='Zero', vol='GARCH', p=15, q=15)
鉴于线性增加的方差,数据集可能不适合 GARCH 模型,但是,下面列出了完整的示例。
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='GARCH', p=15, q=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
下面列出了预期和预测方差的图。
使用 GARCH 预测方差与预测方差的线图
进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
论文和书籍
- 具有英国通货膨胀方差估计的自回归条件异方差,1982。
- 广义自回归条件异方差,1986。
- 第七章,非平稳模型, R 的入门时间序列,2009。
API
用品
摘要
在本教程中,您发现了 ARCH 和 GARCH 模型,用于预测时间序列的方差。
具体来说,你学到了:
- 时间序列中的方差问题以及 ARCH 和 GARCH 模型的需求。
- 如何配置 ARCH 和 GARCH 模型。
- 如何在 Python 中实现 ARCH 和 GARCH 模型。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
如何使用 Python 差分时间序列数据集
原文:
machinelearningmastery.com/difference-time-series-dataset-python/
差分是时间序列中流行且广泛使用的数据变换。
在本教程中,您将了解如何使用 Python 将差异操作应用于时间序列数据。
完成本教程后,您将了解:
- 关于差分运算,包括滞后差和差分顺序的配置。
- 如何开发差分操作的手动实现。
- 如何使用内置的 Pandas 差分功能。
让我们开始吧。
如何区分时间序列数据集与 Python
照片由 Marcus ,保留一些权利。
为什么差异时间序列数据?
差分是一种转换时间序列数据集的方法。
它可用于消除序列对时间的依赖性,即所谓的时间依赖性。这包括趋势和季节性等结构。
差异可以通过消除时间序列水平的变化来帮助稳定时间序列的均值,从而消除(或减少)趋势和季节性。
- 第 215 页,预测:原则与实践
通过从当前观察中减去先前的观察来执行差分。
difference(t) = observation(t) - observation(t-1)
以这种方式,可以计算一系列差异。
滞后差异
将连续观察之间的差异称为滞后-1 差异。
可以调整滞后差异以适应特定的时间结构。
对于具有季节性成分的时间序列,滞后可以预期为季节性的周期(宽度)。
差异订单
在执行差分运算之后,例如在非线性趋势的情况下,时间结构可能仍然存在。
这样,差分过程可以重复多次,直到所有时间依赖性都被消除。
执行差分的次数称为差分顺序。
洗发水销售数据集
该数据集描述了 3 年期间每月洗发水的销售数量。
单位是销售计数,有 36 个观察。原始数据集归功于 Makridakis,Wheelwright 和 Hyndman(1998)。
下面的示例加载并创建已加载数据集的图。
from pandas import read_csv
from pandas import datetime
from matplotlib import pyplot
def parser(x):
return datetime.strptime('190'+x, '%Y-%m')
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
series.plot()
pyplot.show()
运行该示例将创建在数据中显示清晰线性趋势的图。
洗发水销售数据集图
手动差分
我们可以手动区分数据集。
这涉及开发一个创建差异数据集的新功能。该函数将遍历提供的序列并以指定的间隔或滞后计算差异值。
以下名为difference()
的函数实现了此过程。
# create a differenced series
def difference(dataset, interval=1):
diff = list()
for i in range(interval, len(dataset)):
value = dataset[i] - dataset[i - interval]
diff.append(value)
return Series(diff)
我们可以看到该函数在指定的时间间隔后小心地开始差异数据集,以确保实际上可以计算差值。定义默认间隔或滞后值 1。这是一个合理的默认值。
进一步的改进是还能够指定执行差分操作的次序或次数。
以下示例将手动 _ 差异()_ 功能应用于 Shampoo Sales 数据集。
from pandas import read_csv
from pandas import datetime
from pandas import Series
from matplotlib import pyplot
def parser(x):
return datetime.strptime('190'+x, '%Y-%m')
# create a differenced series
def difference(dataset, interval=1):
diff = list()
for i in range(interval, len(dataset)):
value = dataset[i] - dataset[i - interval]
diff.append(value)
return Series(diff)
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
X = series.values
diff = difference(X)
pyplot.plot(diff)
pyplot.show()
运行该示例将创建差异数据集并绘制结果。
手动差异的洗发水销售数据集
自动差分
Pandas 库提供了自动计算数据集差异的功能。
在系列和 DataFrame 对象上都提供了diff()
功能。
与上一节中手动定义的差异函数一样,它需要一个参数来指定间隔或滞后,在本例中称为 _ 周期 _。
下面的示例演示了如何在 Pandas Series 对象上使用内置差异函数。
from pandas import read_csv
from pandas import datetime
from matplotlib import pyplot
def parser(x):
return datetime.strptime('190'+x, '%Y-%m')
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
diff = series.diff()
pyplot.plot(diff)
pyplot.show()
与上一节一样,运行该示例会绘制差异数据集。
除了需要更少的代码之外,使用 Pandas 功能的好处是它可以维护差异系列的日期时间信息。
自动差异洗发水销售数据集
摘要
在本教程中,您了解了如何使用 Python 将差异操作应用于时间序列数据。
具体来说,你学到了:
- 关于差异操作,包括滞后和顺序的配置。
- 如何手动实现差分变换。
- 如何使用内置的 Pandas 实现差分变换。
您对差异或此帖有任何疑问吗?
在下面的评论中提出您的问题。
Python 中用于时间序列预测的指数平滑的温和介绍
原文:
machinelearningmastery.com/exponential-smoothing-for-time-series-forecasting-in-python/
指数平滑是单变量数据的时间序列预测方法,可以扩展为支持具有系统趋势或季节性成分的数据。
它是一种强大的预测方法,可用作流行的 Box-Jenkins ARIMA 系列方法的替代方法。
在本教程中,您将发现单变量时间序列预测的指数平滑方法。
完成本教程后,您将了解:
- 什么是指数平滑以及它与其他预测方法的不同之处。
- 指数平滑的三种主要类型以及如何配置它们。
- 如何在 Python 中实现指数平滑。
让我们开始吧。
Python 中时间序列预测的指数平滑的温和介绍
照片由 Wolfgang Staudt ,保留一些权利。
教程概述
本教程分为 4 个部分;他们是:
- 什么是指数平滑?
- 指数平滑的类型
- 如何配置指数平滑
- Python 中的指数平滑
什么是指数平滑?
指数平滑是单变量数据的时间序列预测方法。
像 Box-Jenkins ARIMA 系列方法这样的时间序列方法开发了一种模型,其中预测是近期过去观察或滞后的加权线性和。
指数平滑预测方法的类似之处在于预测是过去观察的加权和,但模型明确地使用指数减小的权重用于过去的观察。
具体而言,过去的观察以几何减小的比率加权。
使用指数平滑方法产生的预测是过去观测的加权平均值,随着观测结果的变化,权重呈指数衰减。换句话说,观察越近,相关重量越高。
- 第 171 页,预测:原则和实践,2013。
指数平滑方法可以被视为对等,并且是流行的 Box-Jenkins ARIMA 类时间序列预测方法的替代方法。
总的来说,这些方法有时被称为 ETS 模型,指的是错误,趋势和季节性的显式建模。
指数平滑的类型
指数平滑时间序列预测方法有三种主要类型。
一种假设没有系统结构的简单方法,明确处理趋势的扩展,以及增加季节性支持的最先进方法。
单指数平滑
单指数平滑,简称 SES,也称为简单指数平滑,是一种没有趋势或季节性的单变量数据的时间序列预测方法。
它需要一个名为alpha
(a
)的参数,也称为平滑因子或平滑系数。
该参数控制在先前时间步骤的观察结果的影响以指数方式衰减的速率。 Alpha 通常设置为介于 0 和 1 之间的值。大值意味着模型主要关注最近的过去观察,而较小的值意味着在做出预测时会考虑更多的历史记录。
接近 1 的值表示快速学习(即,只有最近的值影响预测),而接近 0 的值表示学习缓慢(过去的观察对预测有很大影响)。
- 第 89 页,实用时间序列预测与 R ,2016 年。
超参数:
- Alpha :级别的平滑因子。
双指数平滑
双指数平滑是指数平滑的扩展,明确增加了对单变量时间序列趋势的支持。
除了用于控制水平平滑因子的alpha
参数外,还增加了一个额外的平滑因子来控制称为beta
(_ 的趋势变化影响的衰减。 b_ )。
该方法支持以不同方式变化的趋势:加法和乘法,取决于趋势分别是线性还是指数。
具有附加趋势的双指数平滑通常被称为 Holt 的线性趋势模型,以 Charles Holt 方法的开发者命名。
- 附加趋势:具有线性趋势的双指数平滑。
- 乘法趋势:具有指数趋势的双指数平滑。
对于更长距离(多步骤)的预测,这种趋势可能会持续不切实际。因此,随着时间的推移抑制趋势可能是有用的。
阻尼意味着将未来时间步长趋势的大小减小到一条直线(没有趋势)。
Holt 线性方法产生的预测显示出未来的不变趋势(增加或减少)。更为极端的是指数趋势法产生的预测[…]受此观察的推动[…]引入了一个参数,在未来的某个时间“抑制”趋势为平线。
- 第 183 页,预测:原则和实践,2013。
与对趋势本身进行建模一样,我们可以使用相同的原理来抑制趋势,特别是对于线性或指数阻尼效应,可以相加或相乘。阻尼系数Phi
(p
)用于控制阻尼率。
- 添加剂阻尼:线性地抑制趋势。
- 乘法阻尼:以指数方式抑制趋势。
超参数:
- Alpha :级别的平滑因子。
- Beta :趋势的平滑因子。
- 趋势类型:加法或乘法。
- Dampen Type :加法或乘法。
- Phi :阻尼系数。
三次指数平滑
三次指数平滑是指数平滑的扩展,明确地增加了对单变量时间序列的季节性支持。
这种方法有时被称为 Holt-Winters Exponential Smoothing,以该方法的两个贡献者命名:Charles Holt 和 Peter Winters。
除了α和β平滑因子之外,还添加了一个新参数,称为gamma
(g
),它控制对季节性成分的影响。
与趋势一样,季节性可以被建模为季节性线性或指数变化的加法或乘法过程。
- 添加季节性:具有线性季节性的三重指数平滑。
- 乘法季节性:具有指数季节性的三次指数平滑。
三指数平滑是指数平滑的最高级变化,通过配置,它还可以开发双指数和单指数平滑模型。
作为一种自适应方法,Holt-Winter 的指数平滑允许水平,趋势和季节性模式随时间变化。
- 第 95 页,实用时间序列预测与 R ,2016 年。
此外,为确保正确建模季节性,必须指定季节性时间段(_ 期间 _)中的时间步数。例如,如果系列是每月数据并且每年重复季节性时段,则期间= 12。
超参数:
- Alpha :级别的平滑因子。
- Beta :趋势的平滑因子。
- Gamma :季节性的平滑因子。
- 趋势类型:加法或乘法。
- Dampen Type :加法或乘法。
- Phi :阻尼系数。
- 季节性类型:加法或乘法。
- 期间:季节性时间段的时间步长。
如何配置指数平滑
可以明确指定所有模型超参数。
对于专家和初学者来说,这可能具有挑战性。
相反,通常使用数值优化来搜索和资助平滑系数(alpha
,beta
,gamma
和phi
)对于导致最低错误的模型。
[…]更加稳健和客观的方法来获得任何指数平滑方法中包含的未知参数的值是从观测数据中估计它们。 […]未知参数和任何指数平滑方法的初始值可以通过最小化 SSE [平方误差之和]来估算。
- 第 177 页,预测:原则和实践,2013。
必须明确指定指定趋势和季节性变化类型的参数,例如它们是加性或乘法的天气以及它们是否应该被抑制。
Python 中的指数平滑
本节介绍如何在 Python 中实现指数平滑。
Statsmodels Python 库中提供了 Python 中的指数平滑的实现。
这些实现基于 Rob Hyndman 和 George Athanasopoulos 的优秀书籍预测:原理与实践,2013 及其在“预测”包中的 R 实现方法的描述) 。
单指数平滑
可以通过 SimpleExpSmoothing Statsmodels 类在 Python 中实现单指数平滑或简单平滑。
首先,必须实例化SimpleExpSmoothing
类的实例并传递训练数据。然后调用fit()
函数提供拟合配置,特别是称为smoothing_level
的alpha
值。如果没有提供或设置为 _ 无 _,模型将自动优化该值。
此fit()
函数返回包含学习系数的HoltWintersResults
类的实例。可以调用结果对象上的forecast()
或predict()
函数做出预测。
例如:
# single exponential smoothing
...
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
# prepare data
data = ...
# create class
model = SimpleExpSmoothing(data)
# fit model
model_fit = model.fit(...)
# make prediction
yhat = model_fit.predict(...)
双指数和三指数平滑
可以使用 ExponentialSmoothing Statsmodels 类在 Python 中实现单指数,双指数和三指数平滑。
首先,必须实例化 ExponentialSmoothing 类的实例,同时指定训练数据和模型的某些配置。
具体而言,您必须指定以下配置参数:
- 趋势:趋势分量的类型,作为加法的“_ 加 _”或乘法的“
mul
”。可以通过将趋势设置为“无”来禁用对趋势建模。 - 阻尼:是否应该抑制趋势分量,
True
或False
。 - 季节性:季节性成分的类型,为“_ 添加 _”为添加剂或“
mul
”为乘法。可以通过将季节性组件设置为“无”来禁用它。 - seasonal_periods :季节性时间段内的时间步数,例如每年季节性结构 12 个月 12 个月(更多)。
然后通过调用fit()
函数将模型拟合到训练数据上。
此功能允许您指定指数平滑模型的平滑系数或对其进行优化。默认情况下,它们已经过优化(例如 _ 优化= True_ )。这些系数包括:
- smoothing_level (
alpha
):该级别的平滑系数。 - smoothing_slope (
beta
):趋势的平滑系数。 - smoothing_seasonal (
gamma
):季节性成分的平滑系数。 - damping_slope (
phi
):阻尼趋势的系数。
另外,拟合函数可以在建模之前执行基本数据准备;特别:
- use_boxcox :是否执行系列的幂变换(True / False)或指定变换的 lambda。
fit()
函数将返回包含学习系数的HoltWintersResults
类的实例。可以调用结果对象上的forecast()
或predict()
函数做出预测。
# double or triple exponential smoothing
...
from statsmodels.tsa.holtwinters import ExponentialSmoothing
# prepare data
data = ...
# create class
model = ExponentialSmoothing(data, ...)
# fit model
model_fit = model.fit(...)
# make prediction
yhat = model_fit.predict(...)
进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
图书
- 第七章指数平滑,预测:原则和实践,2013。
- 第 6.4 节。时间序列分析简介,工程统计手册,2012。
- 实际时间序列预测与 R ,2016 年。
API
- Statsmodels 时间序列分析
- statsmodels.tsa.holtwinters.SimpleExpSmoothing API
- statsmodels.tsa.holtwinters.ExponentialSmoothing API
- statsmodels.tsa.holtwinters.HoltWintersResults API
- 预测:时间序列和线性模型 R 包的预测函数
用品
摘要
在本教程中,您发现了单变量时间序列预测的指数平滑方法。
具体来说,你学到了:
- 什么是指数平滑以及它与其他预测方法的不同之处。
- 指数平滑的三种主要类型以及如何配置它们。
- 如何在 Python 中实现指数平滑。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
Python 中用于时间序列预测的特征选择
原文:
machinelearningmastery.com/feature-selection-time-series-forecasting-python/
在时间序列数据上使用机器学习方法需要特征工程。
单变量时间序列数据集仅由一系列观察组成。这些必须转换为输入和输出功能,以便使用监督学习算法。
问题在于,您可以为时间序列问题设计的功能类型和数量几乎没有限制。像 correlogram 这样的经典时间序列分析工具可以帮助评估滞后变量,但在选择其他类型的特征时不会直接帮助,例如从时间戳(年,月或日)和移动统计量(如移动平均值)得出的特征。
在本教程中,您将了解在处理时间序列数据时如何使用功能重要性和功能选择的机器学习工具。
完成本教程后,您将了解:
- 如何创建和解释滞后观察的相关图。
- 如何计算和解释时间序列要素的要素重要性分数。
- 如何在时间序列输入变量上执行特征选择。
让我们开始吧。
教程概述
本教程分为以下 5 个步骤:
- 每月汽车销售数据集:描述我们将要使用的数据集。
- Make Stationary :描述如何使数据集静止以进行分析和预测。
- 自相关图:描述如何创建时间序列数据的相关图。
- 滞后变量的特征重要性:描述如何计算和查看时间序列数据的特征重要性分数。
- 滞后变量的特征选择:描述如何计算和查看时间序列数据的特征选择结果。
让我们从查看标准时间序列数据集开始。
每月汽车销售数据集
在本教程中,我们将使用 Monthly Car Sales 数据集。
该数据集描述了 1960 年至 1968 年间加拿大魁北克省的汽车销售数量。
单位是销售数量的计数,有 108 个观察值。源数据归功于 Abraham 和 Ledolter(1983)。
您可以从 DataMarket 下载数据集。
下载数据集并将其保存到当前工作目录中,文件名为“ car-sales.csv ”。请注意,您可能需要从文件中删除页脚信息。
下面的代码将数据集加载为 Pandas _ 系列 _ 对象。
# 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
还提供了数据的线图。
每月汽车销售数据集线图
制作文具
我们可以看到明确的季节性和数据的增长趋势。
趋势和季节性是固定的组成部分,可以添加到我们做出的任何预测中。它们很有用,但需要删除才能探索任何其他有助于预测的系统信号。
季节性和趋势被移除的时间序列称为静止。
为了消除季节性,我们可以采取季节性差异,从而产生所谓的季节性调整时间序列。
季节性的时期似乎是一年(12 个月)。下面的代码计算经季节性调整的时间序列并将其保存到文件“ seasonally-adjusted.csv ”。
# seasonally adjust the time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('car-sales.csv', header=0)
# seasonal difference
differenced = series.diff(12)
# trim off the first year of empty data
differenced = differenced[12:]
# save differenced dataset to file
differenced.to_csv('seasonally_adjusted.csv')
# plot differenced dataset
differenced.plot()
pyplot.show()
由于前 12 个月的数据没有先前的数据差异,因此必须将其丢弃。
固定数据存储在“ seasonally-adjusted.csv ”中。创建差异数据的线图。
季节性差异月度汽车销售数据集线图
该图表明通过差分消除了季节性和趋势信息。
自相关图
传统上,时间序列特征是基于它们与输出变量的相关性来选择的。
这称为自相关,涉及绘制自相关图,也称为相关图。这些显示了每个滞后观察的相关性以及相关性是否具有统计学意义。
例如,下面的代码绘制了月度汽车销售数据集中所有滞后变量的相关图。
from pandas import Series
from statsmodels.graphics.tsaplots import plot_acf
from matplotlib import pyplot
series = Series.from_csv('seasonally_adjusted.csv', header=None)
plot_acf(series)
pyplot.show()
运行该示例将创建数据的相关图或自相关函数(ACF)图。
该图显示了沿 x 轴的滞后值和 y 轴上的相关性,在-1 和 1 之间分别为负相关和正相关滞后。
蓝色区域上方的点表示统计显着性。滞后值为 0 的相关性为 1 表示观察与其自身的 100%正相关。
该图显示在 1,2,12 和 17 个月时的显着滞后值。
每月汽车销售数据集的相关图
该分析为比较提供了良好的基线。
监督学习的时间序列
我们可以通过将滞后观察(例如 t-1)作为输入并使用当前观察(t)作为输出变量,将单变量月度汽车销售数据集转换为监督学习问题。
我们可以在 Pandas 中使用 shift 函数创建移动观测的新列。
下面的示例创建一个新的时间序列,其中包含 12 个月的滞后值,以预测当前的观察结果。
12 个月的转变意味着前 12 行数据不可用,因为它们包含NaN
值。
from pandas import Series
from pandas import DataFrame
# load dataset
series = Series.from_csv('seasonally_adjusted.csv', header=None)
# reframe as supervised learning
dataframe = DataFrame()
for i in range(12,0,-1):
dataframe['t-'+str(i)] = series.shift(i)
dataframe['t'] = series.values
print(dataframe.head(13))
dataframe = dataframe[13:]
# save to new file
dataframe.to_csv('lags_12months_features.csv', index=False)
运行该示例将打印显示前 12 行和可用第 13 行的前 13 行数据。
t-12 t-11 t-10 t-9 t-8 t-7 t-6 t-5 \
1961-01-01 NaN NaN NaN NaN NaN NaN NaN NaN
1961-02-01 NaN NaN NaN NaN NaN NaN NaN NaN
1961-03-01 NaN NaN NaN NaN NaN NaN NaN NaN
1961-04-01 NaN NaN NaN NaN NaN NaN NaN NaN
1961-05-01 NaN NaN NaN NaN NaN NaN NaN NaN
1961-06-01 NaN NaN NaN NaN NaN NaN NaN 687.0
1961-07-01 NaN NaN NaN NaN NaN NaN 687.0 646.0
1961-08-01 NaN NaN NaN NaN NaN 687.0 646.0 -189.0
1961-09-01 NaN NaN NaN NaN 687.0 646.0 -189.0 -611.0
1961-10-01 NaN NaN NaN 687.0 646.0 -189.0 -611.0 1339.0
1961-11-01 NaN NaN 687.0 646.0 -189.0 -611.0 1339.0 30.0
1961-12-01 NaN 687.0 646.0 -189.0 -611.0 1339.0 30.0 1645.0
1962-01-01 687.0 646.0 -189.0 -611.0 1339.0 30.0 1645.0 -276.0
t-4 t-3 t-2 t-1 t
1961-01-01 NaN NaN NaN NaN 687.0
1961-02-01 NaN NaN NaN 687.0 646.0
1961-03-01 NaN NaN 687.0 646.0 -189.0
1961-04-01 NaN 687.0 646.0 -189.0 -611.0
1961-05-01 687.0 646.0 -189.0 -611.0 1339.0
1961-06-01 646.0 -189.0 -611.0 1339.0 30.0
1961-07-01 -189.0 -611.0 1339.0 30.0 1645.0
1961-08-01 -611.0 1339.0 30.0 1645.0 -276.0
1961-09-01 1339.0 30.0 1645.0 -276.0 561.0
1961-10-01 30.0 1645.0 -276.0 561.0 470.0
1961-11-01 1645.0 -276.0 561.0 470.0 3395.0
1961-12-01 -276.0 561.0 470.0 3395.0 360.0
1962-01-01 561.0 470.0 3395.0 360.0 3440.0
从新数据集中删除前 12 行,结果保存在文件“lags_12months_features.csv
”中。
这个过程可以以任意数量的时间步长重复,例如 6 个月或 24 个月,我建议进行实验。
滞后变量的特征重要性
决策树的集合,如袋装树,随机森林和额外树木,可用于计算特征重要性分数。
这在机器学习中很常见,用于在开发预测模型时估计输入特征的相对有用性。
我们可以使用特征重要性来帮助估计人为输入特征对时间序列预测的相对重要性。
这很重要,因为我们不仅可以设计上面的滞后观察特征,还可以设计基于观测时间戳,滚动统计等的特征。特征重要性是一种帮助理清建模时可能更有用的方法。
下面的示例加载上一节中创建的数据集的监督学习视图,拟合随机森林模型( RandomForestRegressor ),并总结 12 个滞后观察中每一个的相对特征重要性分数。
使用大量树木来确保分数有些稳定。此外,初始化随机数种子以确保每次运行代码时都获得相同的结果。
from pandas import read_csv
from sklearn.ensemble import RandomForestRegressor
from matplotlib import pyplot
# load data
dataframe = read_csv('lags_12months_features.csv', header=0)
array = dataframe.values
# split into input and output
X = array[:,0:-1]
y = array[:,-1]
# fit random forest model
model = RandomForestRegressor(n_estimators=500, random_state=1)
model.fit(X, y)
# show importance scores
print(model.feature_importances_)
# plot importance scores
names = dataframe.columns.values[0:-1]
ticks = [i for i in range(len(names))]
pyplot.bar(ticks, model.feature_importances_)
pyplot.xticks(ticks, names)
pyplot.show()
首先运行该示例打印滞后观察的重要性分数。
[ 0.21642244 0.06271259 0.05662302 0.05543768 0.07155573 0.08478599
0.07699371 0.05366735 0.1033234 0.04897883 0.1066669 0.06283236]
然后将分数绘制为条形图。
该图显示了 t-12 观测的高度相对重要性,以及在较小程度上观察到 t-2 和 t-4 观测的重要性。
值得注意的是,与上述相关图的结果存在差异。
月度汽车销售数据集中特征重要性得分的条形图
可以使用可以计算重要性分数的不同方法重复该过程,例如梯度增强,额外树和袋装决策树。
滞后变量的特征选择
我们还可以使用特征选择来自动识别和选择最具预测性的输入特征。
用于特征选择的流行方法称为递归特征选择(RFE)。
RFE 通过创建预测模型,加权特征和修剪具有最小权重的特征来工作,然后重复该过程直到剩下所需数量的特征。
下面的示例使用 RFE 和随机森林预测模型,并将所需的输入要素数设置为 4。
from pandas import read_csv
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestRegressor
from matplotlib import pyplot
# load dataset
dataframe = read_csv('lags_12months_features.csv', header=0)
# separate into input and output variables
array = dataframe.values
X = array[:,0:-1]
y = array[:,-1]
# perform feature selection
rfe = RFE(RandomForestRegressor(n_estimators=500, random_state=1), 4)
fit = rfe.fit(X, y)
# report selected features
print('Selected Features:')
names = dataframe.columns.values[0:-1]
for i in range(len(fit.support_)):
if fit.support_[i]:
print(names[i])
# plot feature rank
names = dataframe.columns.values[0:-1]
ticks = [i for i in range(len(names))]
pyplot.bar(ticks, fit.ranking_)
pyplot.xticks(ticks, names)
pyplot.show()
运行该示例将打印 4 个所选要素的名称。
不出所料,结果与上一节中显示出高度重要性的特征相匹配。
Selected Features:
t-12
t-6
t-4
t-2
还会创建一个条形图,显示每个输入要素的要素选择等级(越小越好)。
月度汽车销售数据集中特征选择等级的条形图
可以使用不同数量的特征重复此过程以选择 4 个以上以及除随机森林之外的不同模型。
摘要
在本教程中,您了解了如何使用应用机器学习工具来帮助在预测时从时间序列数据中选择要素。
具体来说,你学到了:
- 如何解释高度相关滞后观察的相关图。
- 如何计算和查看时间序列数据中的要素重要性分数。
- 如何使用特征选择来识别时间序列数据中最相关的输入变量。
对时间序列数据的特征选择有任何疑问吗?
在评论中提出您的问题,我会尽力回答。
浅谈自相关和部分自相关
原文:
machinelearningmastery.com/gentle-introduction-autocorrelation-partial-autocorrelation/
自相关和部分自相关图在时间序列分析和预测中被大量使用。
这些图以图形方式总结了与时间序列中观察的关系强度与先前时间步骤的观察结果。对于初学者来说,自相关和部分自相关之间的差异可能很困难,而且时间序列预测也很困惑。
在本教程中,您将了解如何使用 Python 计算和绘制自相关和部分相关图。
完成本教程后,您将了解:
- 如何绘制和查看时间序列的自相关函数。
- 如何绘制和查看时间序列的部分自相关函数。
- 用于时间序列分析的自相关和部分自相关函数之间的差异。
让我们开始吧。
最低每日温度数据集
该数据集描述了澳大利亚墨尔本市 10 年(1981-1990)的最低日常温度。
单位为摄氏度,有 3,650 个观测值。数据来源被称为澳大利亚气象局。
了解更多信息并从 Dara Market 下载数据集。
下载数据集并将其放在当前工作目录中,文件名为“ daily-minimum-Temperats.sv '”。
注意:下载的文件包含一些问号(“?”)字符,必须先将其删除才能使用数据集。在文本编辑器中打开文件并删除“?”字符。同时删除文件中的任何页脚信息。
下面的示例将加载最低每日温度并绘制时间序列图。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
series.plot()
pyplot.show()
运行该示例将数据集作为 Pandas Series 加载,并创建时间序列的线图。
最低每日温度数据集图
相关和自相关
统计相关性总结了两个变量之间关系的强度。
我们可以假设每个变量的分布符合高斯(钟形曲线)分布。如果是这种情况,我们可以使用 Pearson 相关系数来总结变量之间的相关性。
Pearson 相关系数是介于-1 和 1 之间的数字,分别描述了负相关或正相关。值为零表示没有相关性。
我们可以计算时间序列观测值与之前时间步长的观测值之间的相关性,称为滞后。因为时间序列观测值的相关性是使用先前时间的相同序列的值计算的,所以这称为序列相关或自相关。
通过滞后的时间序列的自相关的图被称为 A uto C 或相关 F 或者首字母缩写词 ACF。该图有时称为相关图或自相关图。
下面是使用 statsmodels 库中的 plot_acf()函数计算和绘制最低每日温度的自相关图的示例。
from pandas import Series
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_acf
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
plot_acf(series)
pyplot.show()
运行该示例将创建一个 2D 绘图,显示沿 x 轴的滞后值和 y 轴与-1 和 1 之间的相关性。
置信区间绘制为锥形。默认情况下,此值设置为 95%置信区间,表明此代码之外的相关值很可能是相关性而非统计吸引力。
最低每日温度数据集的自相关图
默认情况下,会打印所有滞后值,这会使绘图产生噪音。
我们可以将 x 轴上的滞后数限制为 50,以使绘图更容易阅读。
自相关图与最低每日温度数据集的较少滞后
部分自相关函数
部分自相关是时间序列中的观察与先前时间步骤的观察与中间观察的关系被移除之间的关系的总结。
滞后 k 处的部分自相关是在消除由于较短滞后的项引起的任何相关性的影响之后产生的相关性。
- 第 81 页,第 4.5.6 节部分自相关, R 的时间序列介绍。
观察的自相关和先前时间步的观察包括直接相关和间接相关。这些间接相关性是观察相关性的线性函数,以及在中间时间步骤的观察。
部分自相关函数试图消除这些间接相关性。没有进入数学,这是部分自相关的直觉。
下面的示例使用 statsmodels 库中的 plot_pacf()计算并绘制最小每日温度数据集中前 50 个滞后的部分自相关函数。
from pandas import Series
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_pacf
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
plot_pacf(series, lags=50)
pyplot.show()
运行该示例将创建前 50 个滞后的部分自相关的 2D 图。
最低日温度数据集的部分自相关图
ACF 和 PACF 图的直觉
自相关函数的图和时间序列的部分自相关函数说明了一个非常不同的故事。
我们可以使用上面的 ACF 和 PACF 的直觉来探索一些思想实验。
自回归直觉
考虑由自回归(AR)过程生成的时间序列,滞后为k
。
我们知道 ACF 描述了观察与之前时间步骤的另一个观察之间的自相关,包括直接和间接依赖信息。
这意味着我们期望 AR(k)时间序列的 ACF 强到 k 的滞后,并且该关系的惯性将继续到随后的滞后值,随着效果减弱而在某个点落后。
我们知道 PACF 只描述观察与其滞后之间的直接关系。这表明滞后值与k
之外没有相关性。
这正是 AR(k)过程的 ACF 和 PACF 图的期望。
移动平均直觉
考虑由移动平均(MA)过程生成的时间序列,滞后为k
。
请记住,移动平均过程是先前预测的残差的时间序列的自回归模型。考虑移动平均模型的另一种方法是根据最近预测的误差来纠正未来的预测。
我们预计 MA(k)过程的 ACF 与最近的 k 值滞后显示强相关性,然后急剧下降到低或无相关性。根据定义,这就是生成流程的方式。
对于 PACF,我们预计该图将显示与滞后的强烈关系以及从滞后开始的相关性的尾随。
同样,这正是 MA(k)过程的 ACF 和 PACF 图的期望。
进一步阅读
本节提供了一些资源,可用于进一步阅读时间序列的自相关和部分自相关。
- 维基百科上的相关和依赖
- 维基百科上的 Autocorrelation
- 维基百科上的 Correlogram
- 维基百科上的部分自相关函数。
- 第 3.2.5 节“部分自相关函数”,第 64 页,时间序列分析:预测和控制。
摘要
在本教程中,您了解了如何使用 Python 计算时间序列数据的自相关和部分自相关图。
具体来说,你学到了:
- 如何计算和创建时间序列数据的自相关图。
- 如何计算和创建时间序列数据的部分自相关图。
- 解释 ACF 和 PACF 图的差异和直觉。
您对本教程有任何疑问吗?
在下面的评论中提出您的问题,我会尽力回答。
用于时间序列预测的 Box-Jenkins 方法简介
原文:
machinelearningmastery.com/gentle-introduction-box-jenkins-method-time-series-forecasting/
自回归整合移动平均模型(简称 ARIMA)是时间序列预测和分析的标准统计模型。
随着它的发展,作者 Box 和 Jenkins 还建议了一个识别,估计和检查特定时间序列数据集模型的过程。此过程现在称为 Box-Jenkins 方法。
在这篇文章中,您将发现 Box-Jenkins 方法以及在时间序列预测问题中使用它的提示。
具体来说,您将学到:
- 关于 ARIMA 流程以及 Box-Jenkins 方法的 3 个步骤。
- 用于选择 ARIMA 模型的 q,d 和 p 模型配置的最佳实践启发式算法。
- 通过寻找过拟合和残余误差作为诊断过程来评估模型。
让我们开始吧。
时间序列预测 Box-Jenkins 方法的温和介绍
Erich Ferdinand 的照片,保留一些权利。
自回归整合移动平均模型
ARIMA 模型是一类用于分析和预测时间序列数据的统计模型。
ARIMA 是 A uto R egressive I 整合 M oving A verage 的首字母缩写词。它是更简单的 AutoRegressive 移动平均线的推广,并添加了集成的概念。
这个首字母缩略词是描述性的,捕捉模型本身的关键方面。简而言之,它们是:
- AR :_ 自回归 _。使用观察与一些滞后观察之间的依赖关系的模型。
- I :_ 综合 _。使用差异原始观察(即,从前一时间步骤的观察中减去观察值)以使时间序列静止。
- MA :_ 移动平均值 _。使用应用于滞后观察的移动平均模型的观测和残差之间的依赖关系的模型。
这些组件中的每一个都在模型中明确指定为参数。
标准符号用于 ARIMA(p,d,q),其中参数用整数值代替,以快速指示正在使用的特定 ARIMA 模型。
ARIMA 模型的参数定义如下:
- p :模型中包含的滞后观察数,也称为滞后顺序。
- d :原始观察值差异的次数,也称为差分程度。
- q :移动平均窗口的大小,也称为移动平均的顺序。
Box-Jenkins 方法
Box-Jenkins 方法由 George Box 和 Gwilym Jenkins 在其开创性的 1970 年教科书时间序列分析:预测和控制中提出。
该方法首先假设生成时间序列的过程可以使用 ARMA 模型(如果它是静止的)或 ARIMA 模型(如果它是非静态的)来近似。
2016 年第 5 版教科书(第二部分,第 177 页)将该过程称为随机模型构建,它是一种迭代方法,包括以下 3 个步骤:
- 鉴定。使用数据和所有相关信息来帮助选择可以最好地汇总数据的模型子类。
- 估算。使用数据训练模型的参数(即系数)。
- 诊断检查。在可用数据的上下文中评估拟合模型,并检查可以改进模型的区域。
这是一个迭代过程,因此在诊断过程中获取新信息时,您可以回到步骤 1 并将其合并到新的模型类中。
让我们更详细地看一下这些步骤。
1.识别
识别步骤进一步细分为:
- 评估时间序列是否静止,如果不是,需要多少差异才能使其静止。
- 确定数据的 ARMA 模型的参数。
1.1 差异
以下是识别过程中的一些提示。
- 单位根测试。对时间序列使用单位根统计检验以确定它是否静止。每轮差分后重复。
- 避免过度分化。使时间序列差异超过所需时间会导致额外的串行相关性和额外的复杂性。
1.2 配置 AR 和 MA
两个诊断图可用于帮助选择 ARMA 或 ARIMA 的p
和q
参数。他们是:
- 自相关函数(ACF)。该图总结了观察与滞后值的相关性。 x 轴表示滞后,y 轴表示-1 和 1 之间的相关系数,表示负相关和正相关。
- 部分自相关函数(PACF)。该图总结了具有滞后值的观测值的相关性,该滞后值未被先前滞后观察所解释。
两个图都绘制为条形图,显示 95%和 99%置信区间为水平线。因此,跨越这些置信区间的条形图更为重要且值得注意。
您可以在这些图中观察到的一些有用模式是:
- 如果 ACF 在滞后之后落后并且在滞后之后在 PACF 中具有硬切断,则该模型是 AR。该滞后被视为
p
的值。 - 如果 PACF 滞后后退出并且在滞后后 ACF 中有一个硬切断,则该模型为 MA。该滞后值被视为
q
的值。 - 如果 ACF 和 PACF 都落后,该模型是 AR 和 MA 的混合。
2.估计
估算涉及使用数值方法来最小化损失或误差项。
我们不会详细介绍估算模型参数,因为这些细节由所选库或工具处理。
我建议参考一本教科书,以便更深入地理解 ARMA 和 ARIMA 模型以及用于解决它的有限记忆 BFGS 等优化方法所要解决的优化问题。
3.诊断检查
诊断检查的想法是寻找模型不适合数据的证据。
调查诊断的两个有用领域是:
- 过拟合
- 剩余错误。
3.1 过拟合
第一项检查是检查模型是否过拟合数据。通常,这意味着模型比它需要的更复杂并且捕获训练数据中的随机噪声。
这是时间序列预测的一个问题,因为它会对模型推广的能力产生负面影响,导致样本数据的预测表现不佳。
必须仔细注意样品内和样品外的表现,这需要仔细设计一个强大的测试工具来评估模型。
3.2 残留错误
预测残差为诊断提供了很好的机会。
对错误分布的回顾可以帮助梳理出模型中的偏差。来自理想模型的误差将类似于白噪声,即具有零均值和对称方差的高斯分布。
为此,您可以使用密度图,直方图和 Q-Q 图来比较错误分布与预期分布。非高斯分布可以提示数据预处理的机会。分布的偏差或非零均值可能表明预测偏差可能是正确的。
此外,理想模型在预测残差的时间序列中不会留下时间结构。可以通过创建剩余错误时间序列的 ACF 和 PACF 图来检查这些。
残差中存在序列相关性表明在模型中使用该信息的进一步机会。
进一步阅读
关于该主题的权威资源是时间序列分析:预测和控制。我会推荐 2016 年第 5 版,特别是第二部分和第 6-10 章。
以下是一些额外的阅读材料,如果您希望深入了解,可能有助于充实您的理解:
- Box-Jenkins 建模作者:Rob J Hyndman,2002 [PDF]。
- 维基百科上的 Box-Jenkins 方法。
- 第 6.4.4.5 节。 Box-Jenkins 模型,NIST 统计方法手册。
摘要
在这篇文章中,您发现了用于时间序列分析和预测的 Box-Jenkins 方法。
具体来说,你学到了:
- 关于 ARIMA 模型和一般 Box-Jenkins 方法的 3 个步骤。
- 如何使用 ACF 和 PACF 图来为 ARIMA 模型选择
p
和q
参数。 - 如何使用过拟合和残差来诊断拟合的 ARIMA 模型。
您对 Box-Jenkins 方法或此帖有任何疑问吗?
在下面的评论中提出您的问题,我会尽力回答。
Python 中时间序列预测的温和简介
原文:
machinelearningmastery.com/gentle-introduction-random-walk-times-series-forecasting-python/
你怎么知道你的时间序列问题是否可以预测?
这是一个时间序列预测的难题。有一种称为随机游走的工具可以帮助您了解时间序列预测问题的可预测性。
在本教程中,您将在 Python 中发现随机游走及其属性。
完成本教程后,您将了解:
- 随机游走是什么以及如何在 Python 中从零开始创建一个。
- 如何分析随机游走的属性并识别时间序列是否是随机游走。
- 如何对随机游走做出预测。
让我们开始吧。
使用 Python
照片由 Sam valadi 进行随机游走时间序列预测,保留一些权利。
随机系列
Python 标准库包含随机模块,可以访问一组用于生成随机数的函数。
randrange()函数可用于生成 0 和上限之间的随机整数。
我们可以使用randrange()
函数生成 0 到 10 之间的 1,000 个随机整数的列表。下面列出了这个例子。
from random import seed
from random import randrange
from matplotlib import pyplot
seed(1)
series = [randrange(10) for i in range(1000)]
pyplot.plot(series)
pyplot.show()
运行该示例绘制了随机数序列。
这真是一团糟。它看起来不像时间序列。
随机系列
这不是随机游走。它只是一系列随机数。
初学者犯的一个常见错误就是认为随机游走是一个随机数列表,而事实并非如此。
随机漫步
随机游走与随机数列表不同,因为序列中的下一个值是序列中先前值的修改。
用于生成序列的过程强制从一次性步骤到下一步骤的依赖性。这种依赖性提供了一步到位的一致性,而不是一系列独立的随机数提供的大跳跃。
正是这种依赖性使得该过程的名称为“随机游走”或“醉汉行走”。
随机游走的简单模型如下:
- 以随机数-1 或 1 开头。
- 随机选择-1 或 1 并将其添加到上一时间步的观察中。
- 只要您愿意,重复步骤 2。
更简洁地说,我们可以将此过程描述为:
y(t) = B0 + B1*X(t-1) + e(t)
其中 y(t) 是系列中的下一个值。B0
是一个系数,如果设置为零以外的值,则向随机游走添加恒定漂移。B1
是对前一时间步进行加权的系数,设定为 1.0。 X(t-1) 是前一时间步的观察结果。 e(t) 是此时的白噪声或随机波动。
我们可以通过循环遍历此过程并为随机漫步构建 1,000 个时间步骤列表来在 Python 中实现此功能。下面列出了完整的示例。
from random import seed
from random import random
from matplotlib import pyplot
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
pyplot.plot(random_walk)
pyplot.show()
运行该示例将创建随机游走的线图。
我们可以看到它与我们上面的随机数序列看起来非常不同。事实上,形状和运动看起来像是股票市场上证券价格的现实时间序列。
随机行走线图
在接下来的部分中,我们将仔细研究随机游走的属性。这很有用,因为它会为您提供上下文,以帮助确定您将来分析的时间序列是否可能是随机游走。
让我们从查看自相关结构开始。
随机游走和自相关
我们可以计算每个观测值与之前时间步骤的观测值之间的相关性。这些相关性的图称为自相关图或相关图。
考虑到构建随机游走的方式,我们期望与先前的观察结果具有强烈的自相关性,并且具有先前滞后值的线性下降。
我们可以使用 Pandas 中的autocorrelation_plot()
函数来绘制随机游走的相关图。
下面列出了完整的示例。
请注意,在我们生成随机游走的每个示例中,我们对随机数生成器使用相同的种子,以确保我们获得相同的随机数序列,并依次进行相同的随机游走。
from random import seed
from random import random
from matplotlib import pyplot
from pandas.tools.plotting import autocorrelation_plot
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
autocorrelation_plot(random_walk)
pyplot.show()
运行这个例子,我们通常会看到预期的趋势,在这种情况下,在前几百个滞后观察中。
随机走路 Correlogram Plot
随机游走和平稳性
静止时间序列是值不是时间函数的时间序列。
考虑到构建随机游走的方式和审查自相关的结果,我们知道随机游走中的观察结果取决于时间。
目前的观察是从先前的观察中随机的一步。
因此,我们可以预期随机游走是非平稳的。实际上,所有随机游走过程都是非平稳的。请注意,并非所有非平稳时间序列都是随机游走。
另外,非平稳时间序列随时间不具有一致的均值和/或方差。对随机走线图的回顾可能表明情况就是如此。
我们可以使用统计显着性检验来确认这一点,特别是 Augmented Dickey-Fuller 检验。
我们可以使用 statsmodels 库中的 adfuller()函数执行此测试。下面列出了完整的示例。
from random import seed
from random import random
from statsmodels.tsa.stattools import adfuller
# generate random walk
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
# statistical test
result = adfuller(random_walk)
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))
测试的零假设是时间序列是非平稳的。
运行该示例,我们可以看到测试统计值为 0.341605。这大于 1%,5%和 10%置信水平下的所有临界值。因此,我们可以说时间序列确实看起来是非平稳的,结果是统计侥幸的可能性很小。
ADF Statistic: 0.341605
p-value: 0.979175
Critical Values:
5%: -2.864
1%: -3.437
10%: -2.568
我们可以通过采取第一个差异使随机游走静止。
这就是将每个观察结果替换为它与之前的值之间的差异。
考虑到这种随机游走的构建方式,我们希望这会产生-1 和 1 值的时间序列。这正是我们所看到的。
下面列出了完整的示例。
from random import seed
from random import random
from matplotlib import pyplot
# create random walk
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
# take difference
diff = list()
for i in range(1, len(random_walk)):
value = random_walk[i] - random_walk[i - 1]
diff.append(value)
# line plot
pyplot.plot(diff)
pyplot.show()
运行该示例会生成一个线图,显示-1 和 1 的 1,000 次移动,这是一个真正的混乱。
随机游走差异线图
这个差异图也清楚地表明,除了一系列随机移动之外,我们确实没有任何信息可以使用。
没有结构可供学习。
现在时间序列是静止的,我们可以重新计算差异序列的相关图。下面列出了完整的示例。
from random import seed
from random import random
from matplotlib import pyplot
from pandas.tools.plotting import autocorrelation_plot
# create random walk
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
# take difference
diff = list()
for i in range(1, len(random_walk)):
value = random_walk[i] - random_walk[i - 1]
diff.append(value)
# line plot
autocorrelation_plot(diff)
pyplot.show()
运行这个例子,我们可以看到滞后观察之间没有显着的关系,正如我们对随机游走的生成方式所期望的那样。
所有相关性都很小,接近于零且低于 95%和 99%的置信水平(超过一些统计吸虫)。
随机游走差分曲线图
预测随机游走
随机游走是不可预测的;它无法合理预测。
考虑到随机游走的构建方式,我们可以预期,我们可以做出的最佳预测是使用前一时间步的观察,就像下一个时间步中将发生的那样。
仅仅因为我们知道下一个时间步骤将是前一个时间步的函数。
这通常被称为朴素预测或持久性模型。
我们可以在 Python 中实现这一点,首先将数据集拆分为训练集和测试集,然后使用持久性模型使用滚动预测方法预测结果。一旦为测试集收集了所有预测,就计算出均方误差。
from random import seed
from random import random
from sklearn.metrics import mean_squared_error
# generate the random walk
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
# prepare dataset
train_size = int(len(random_walk) * 0.66)
train, test = random_walk[0:train_size], random_walk[train_size:]
# persistence
predictions = list()
history = train[-1]
for i in range(len(test)):
yhat = history
predictions.append(yhat)
history = test[i]
error = mean_squared_error(test, predictions)
print('Persistence MSE: %.3f' % error)
运行该示例估计模型的均方误差为 1。
这也是预期的,因为我们知道从一个时间步到下一个的变化总是在正方向或负方向上为 1,并且该预期误差的平方为 1(1 ^ 2 = 1) 。
Persistence MSE: 1.000
随机游走的初学者犯的另一个错误是假设如果已知误差范围(方差),那么我们可以使用随机游走生成类型过程做出预测。
也就是说,如果我们知道错误是-1 或 1,那么为什么不通过向先前的值添加随机选择的-1 或 1 来做出预测。
我们可以在下面的 Python 中演示这种随机预测方法。
from random import seed
from random import random
from sklearn.metrics import mean_squared_error
# generate the random walk
seed(1)
random_walk = list()
random_walk.append(-1 if random() < 0.5 else 1)
for i in range(1, 1000):
movement = -1 if random() < 0.5 else 1
value = random_walk[i-1] + movement
random_walk.append(value)
# prepare dataset
train_size = int(len(random_walk) * 0.66)
train, test = random_walk[0:train_size], random_walk[train_size:]
# random prediction
predictions = list()
history = train[-1]
for i in range(len(test)):
yhat = history + (-1 if random() < 0.5 else 1)
predictions.append(yhat)
history = test[i]
error = mean_squared_error(test, predictions)
print('Random MSE: %.3f' % error)
运行该示例,我们可以看到算法确实导致比持久性方法更差的表现,均方误差为 1.765。
Random MSE: 1.765
持久性或朴素的预测是我们可以为随机游走时间序列做出的最佳预测。
你的时间序列是随机游走吗?
您的时间序列可能是随机游走。
检查您的时间序列是否是随机游走的一些方法如下:
- 时间序列显示出强烈的时间依赖性,其线性衰减或以类似模式衰减。
- 时间序列是非平稳的并且使其静止,在数据中没有明显可学习的结构。
- 持久性模型提供了可靠预测的最佳来源。
最后一点是时间序列预测的关键。使用持久性模型的基线预测可以快速充实您是否可以做得更好。如果你做不到,你可能会随机散步。
许多时间序列都是随机游走,尤其是随着时间推移的安全价格。
随机游走假设是股票市场价格是随机游走且无法预测的理论。
随机游走是指根据过去的历史无法预测未来步骤或方向的步行。当该术语适用于股票市场时,这意味着股票价格的短期变化是不可预测的。
- 第 26 页,随机漫步华尔街:经过时间考验的成功投资策略
人类的思想到处都是模式,我们必须保持警惕,我们不是在欺骗自己,而是通过为随机游走过程开发精心设计的模型来浪费时间。
进一步阅读
如果您想深入了解 Random Walks,下面是一些进一步的资源。
- 随机漫步华尔街:经过时间考验的成功投资策略
- 醉汉的行走:随机性如何规范我们的生活
- 第 7.3 节评估可预测性, R 实用时间序列预测:动手指南。
- 第 4.3 节随机游走, R 的时间序列介绍。
- 维基百科上的 Random Walk
- Robert F. Nau 的随机游走模型
摘要
在本教程中,您了解了如何使用 Python 探索随机漫游。
具体来说,你学到了:
- 如何在 Python 中创建随机游走过程。
- 如何探索随机游走的自相关和非平稳结构。
- 如何对随机游走时间序列做出预测。
您对随机散步或本教程有任何疑问吗?
在下面的评论中提出您的问题。
如何使用 Python 网格搜索 ARIMA 模型超参数
原文:
machinelearningmastery.com/grid-search-arima-hyperparameters-with-python/
用于时间序列分析和预测的 ARIMA 模型可能很难配置。
有 3 个参数需要通过迭代试验和错误来评估诊断图和使用 40 年的启发式规则。
我们可以使用网格搜索程序自动化为 ARIMA 模型评估大量超参数的过程。
在本教程中,您将了解如何使用 Python 中的超参数网格搜索来调整 ARIMA 模型。
完成本教程后,您将了解:
- 可用于调整 ARIMA 超参数以进行滚动一步预测的一般过程。
- 如何在标准单变量时间序列数据集上应用 ARIMA 超参数优化。
- 扩展程序的想法,以更精细和强大的模型。
让我们开始吧。
如何使用 Python 网格搜索 ARIMA 模型超参数
照片由 Alpha ,保留一些权利。
网格搜索方法
时间序列的诊断图可以与启发式规则一起使用,以确定 ARIMA 模型的超参数。
这些在大多数情况下都很好,但也许并非所有情况都很好。
我们可以在模型超参数的不同组合上自动化训练和评估 ARIMA 模型的过程。在机器学习中,这称为网格搜索或模型调整。
在本教程中,我们将开发一种网格搜索 ARIMA 超参数的方法,用于一步滚动预测。
该方法分为两部分:
- 评估 ARIMA 模型。
- 评估 ARIMA 参数集。
本教程中的代码使用了 scikit-learn,Pandas 和 statsmodels Python 库。
1.评估 ARIMA 模型
我们可以通过在训练数据集上准备 ARIMA 模型并评估测试数据集的预测来评估 ARIMA 模型。
此方法包括以下步骤:
- 将数据集拆分为训练和测试集。
- 遍历测试数据集中的时间步长。
- 训练 ARIMA 模型。
- 进行一步预测。
- 商店预测;获取并存储实际观察结果。
- 计算预测的误差分数与预期值的比较。
我们可以在 Python 中实现这个作为一个名为evaluate_arima_model()
的新独立函数,它将时间序列数据集作为输入,以及p
,d
的元组]和q
参数用于评估模型。
数据集分为两部分:初始训练数据集为 66%,测试数据集为剩余的 34%。
迭代测试集的每个时间步。只需一次迭代就可以提供一个模型,您可以使用该模型对新数据做出预测。迭代方法允许每个步骤训练新的 ARIMA 模型。
每次迭代都做出预测并存储在列表中。这样,在测试集的末尾,可以将所有预测与预期值列表进行比较,并计算出错误分数。在这种情况下,计算并返回均方误差分数。
完整的功能如下所列。
# evaluate an ARIMA model for a given order (p,d,q)
def evaluate_arima_model(X, arima_order):
# prepare training dataset
train_size = int(len(X) * 0.66)
train, test = X[0:train_size], X[train_size:]
history = [x for x in train]
# make predictions
predictions = list()
for t in range(len(test)):
model = ARIMA(history, order=arima_order)
model_fit = model.fit(disp=0)
yhat = model_fit.forecast()[0]
predictions.append(yhat)
history.append(test[t])
# calculate out of sample error
error = mean_squared_error(test, predictions)
return error
现在我们知道如何评估一组 ARIMA 超参数,让我们看看我们如何重复调用此函数以获得要评估的参数网格。
2.迭代 ARIMA 参数
评估一组参数相对简单。
用户必须指定p
,d
和q
ARIMA 参数的网格进行迭代。通过调用上一节中描述的evaluate_arima_model()
函数,为每个参数创建模型并评估其表现。
该函数必须跟踪观察到的最低错误分数和导致它的配置。这可以在函数的末尾进行总结,并打印出标准输出。
我们可以将这个名为evaluate_models()
的函数实现为一系列的四个循环。
还有两个注意事项。第一个是确保输入数据是浮点值(而不是整数或字符串),因为这可能导致 ARIMA 过程失败。
其次,statsmodels ARIMA 程序在内部使用数值优化程序来为模型找到一组系数。这些过程可能会失败,从而可能会引发异常。我们必须捕获这些异常并跳过导致问题的配置。这种情况经常发生,你会想到。
此外,建议忽略此代码的警告,以避免运行该过程产生大量噪音。这可以按如下方式完成:
import warnings
warnings.filterwarnings("ignore")
最后,即使有了所有这些保护,底层的 C 和 Fortran 库仍然可以向标准输出报告警告,例如:
** On entry to DLASCL, parameter number 4 had an illegal value
为简洁起见,这些内容已从本教程中报告的结果中删除。
下面列出了评估 ARIMA 超参数网格的完整过程。
# evaluate combinations of p, d and q values for an ARIMA model
def evaluate_models(dataset, p_values, d_values, q_values):
dataset = dataset.astype('float32')
best_score, best_cfg = float("inf"), None
for p in p_values:
for d in d_values:
for q in q_values:
order = (p,d,q)
try:
mse = evaluate_arima_model(dataset, order)
if mse < best_score:
best_score, best_cfg = mse, order
print('ARIMA%s MSE=%.3f' % (order,mse))
except:
continue
print('Best ARIMA%s MSE=%.3f' % (best_cfg, best_score))
现在我们有一个网格搜索 ARIMA 超参数的过程,让我们测试两个单变量时间序列问题的过程。
我们将从 Shampoo Sales 数据集开始。
洗发水销售案例研究
Shampoo Sales 数据集描述了 3 年期间每月洗发水的销售数量。
单位是销售计数,有 36 个观察。原始数据集归功于 Makridakis,Wheelwright 和 Hyndman(1998)。
下载数据集并将其放入当前工作目录,文件名为“ shampoo-sales.csv ”。
时间系列中的时间戳不包含绝对年份组件。从 1900 年开始加载数据和基线时,我们可以使用自定义日期解析功能,如下所示:
# load dataset
def parser(x):
return datetime.strptime('190'+x, '%Y-%m')
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
加载后,我们可以指定p
,d
和q
值的位点进行搜索并将它们传递给evaluate_models()
功能。
我们将尝试一组滞后值(p
)和一些差异迭代(d
)和残余误差滞后值(q
)。
# evaluate parameters
p_values = [0, 1, 2, 4, 6, 8, 10]
d_values = range(0, 3)
q_values = range(0, 3)
warnings.filterwarnings("ignore")
evaluate_models(series.values, p_values, d_values, q_values)
将这一切与上一节中定义的通用程序结合起来,我们可以在 Shampoo Sales 数据集中搜索 ARIMA 超参数。
完整的代码示例如下所示。
import warnings
from pandas import read_csv
from pandas import datetime
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
# evaluate an ARIMA model for a given order (p,d,q)
def evaluate_arima_model(X, arima_order):
# prepare training dataset
train_size = int(len(X) * 0.66)
train, test = X[0:train_size], X[train_size:]
history = [x for x in train]
# make predictions
predictions = list()
for t in range(len(test)):
model = ARIMA(history, order=arima_order)
model_fit = model.fit(disp=0)
yhat = model_fit.forecast()[0]
predictions.append(yhat)
history.append(test[t])
# calculate out of sample error
error = mean_squared_error(test, predictions)
return error
# evaluate combinations of p, d and q values for an ARIMA model
def evaluate_models(dataset, p_values, d_values, q_values):
dataset = dataset.astype('float32')
best_score, best_cfg = float("inf"), None
for p in p_values:
for d in d_values:
for q in q_values:
order = (p,d,q)
try:
mse = evaluate_arima_model(dataset, order)
if mse < best_score:
best_score, best_cfg = mse, order
print('ARIMA%s MSE=%.3f' % (order,mse))
except:
continue
print('Best ARIMA%s MSE=%.3f' % (best_cfg, best_score))
# load dataset
def parser(x):
return datetime.strptime('190'+x, '%Y-%m')
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
# evaluate parameters
p_values = [0, 1, 2, 4, 6, 8, 10]
d_values = range(0, 3)
q_values = range(0, 3)
warnings.filterwarnings("ignore")
evaluate_models(series.values, p_values, d_values, q_values)
运行该示例将为每个成功完成的评估打印 ARIMA 参数和 MSE。
ARIMA(4,2,1)的最佳参数在运行结束时报告,均方误差为 4,694.873。
ARIMA(0, 0, 0) MSE=52425.268
ARIMA(0, 0, 1) MSE=38145.167
ARIMA(0, 0, 2) MSE=23989.567
ARIMA(0, 1, 0) MSE=18003.173
ARIMA(0, 1, 1) MSE=9558.410
ARIMA(0, 2, 0) MSE=67339.808
ARIMA(0, 2, 1) MSE=18323.163
ARIMA(1, 0, 0) MSE=23112.958
ARIMA(1, 1, 0) MSE=7121.373
ARIMA(1, 1, 1) MSE=7003.683
ARIMA(1, 2, 0) MSE=18607.980
ARIMA(2, 1, 0) MSE=5689.932
ARIMA(2, 1, 1) MSE=7759.707
ARIMA(2, 2, 0) MSE=9860.948
ARIMA(4, 1, 0) MSE=6649.594
ARIMA(4, 1, 1) MSE=6796.279
ARIMA(4, 2, 0) MSE=7596.332
ARIMA(4, 2, 1) MSE=4694.873
ARIMA(6, 1, 0) MSE=6810.080
ARIMA(6, 2, 0) MSE=6261.107
ARIMA(8, 0, 0) MSE=7256.028
ARIMA(8, 1, 0) MSE=6579.403
Best ARIMA(4, 2, 1) MSE=4694.873
每日女性出生案例研究
每日女性出生数据集描述了 1959 年加利福尼亚州每日女性出生人数。
单位是计数,有 365 个观测值。数据集的来源归功于 Newton(1988)。
下载数据集并将其放在当前工作目录中,文件名为“ daily-total-female-births.csv ”。
此数据集可以直接作为 Pandas 系列轻松加载。
# load dataset
series = Series.from_csv('daily-total-female-births.csv', header=0)
为了简单起见,我们将探索与上一节中相同的 ARIMA 超参数网格。
# evaluate parameters
p_values = [0, 1, 2, 4, 6, 8, 10]
d_values = range(0, 3)
q_values = range(0, 3)
warnings.filterwarnings("ignore")
evaluate_models(series.values, p_values, d_values, q_values)
综上所述,我们可以在 Daily Female Births 数据集上搜索 ARIMA 参数。完整的代码清单如下。
import warnings
from pandas import Series
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
# evaluate an ARIMA model for a given order (p,d,q)
def evaluate_arima_model(X, arima_order):
# prepare training dataset
train_size = int(len(X) * 0.66)
train, test = X[0:train_size], X[train_size:]
history = [x for x in train]
# make predictions
predictions = list()
for t in range(len(test)):
model = ARIMA(history, order=arima_order)
model_fit = model.fit(disp=0)
yhat = model_fit.forecast()[0]
predictions.append(yhat)
history.append(test[t])
# calculate out of sample error
error = mean_squared_error(test, predictions)
return error
# evaluate combinations of p, d and q values for an ARIMA model
def evaluate_models(dataset, p_values, d_values, q_values):
dataset = dataset.astype('float32')
best_score, best_cfg = float("inf"), None
for p in p_values:
for d in d_values:
for q in q_values:
order = (p,d,q)
try:
mse = evaluate_arima_model(dataset, order)
if mse < best_score:
best_score, best_cfg = mse, order
print('ARIMA%s MSE=%.3f' % (order,mse))
except:
continue
print('Best ARIMA%s MSE=%.3f' % (best_cfg, best_score))
# load dataset
series = Series.from_csv('daily-total-female-births.csv', header=0)
# evaluate parameters
p_values = [0, 1, 2, 4, 6, 8, 10]
d_values = range(0, 3)
q_values = range(0, 3)
warnings.filterwarnings("ignore")
evaluate_models(series.values, p_values, d_values, q_values)
运行该示例将为成功评估的每个配置打印 ARIMA 参数和均方误差。
最佳平均参数报告为 ARIMA(6,1,0),均方误差为 53.187。
ARIMA(0, 0, 0) MSE=67.063
ARIMA(0, 0, 1) MSE=62.165
ARIMA(0, 0, 2) MSE=60.386
ARIMA(0, 1, 0) MSE=84.038
ARIMA(0, 1, 1) MSE=56.653
ARIMA(0, 1, 2) MSE=55.272
ARIMA(0, 2, 0) MSE=246.414
ARIMA(0, 2, 1) MSE=84.659
ARIMA(1, 0, 0) MSE=60.876
ARIMA(1, 1, 0) MSE=65.928
ARIMA(1, 1, 1) MSE=55.129
ARIMA(1, 1, 2) MSE=55.197
ARIMA(1, 2, 0) MSE=143.755
ARIMA(2, 0, 0) MSE=59.251
ARIMA(2, 1, 0) MSE=59.487
ARIMA(2, 1, 1) MSE=55.013
ARIMA(2, 2, 0) MSE=107.600
ARIMA(4, 0, 0) MSE=59.189
ARIMA(4, 1, 0) MSE=57.428
ARIMA(4, 1, 1) MSE=55.862
ARIMA(4, 2, 0) MSE=80.207
ARIMA(6, 0, 0) MSE=58.773
ARIMA(6, 1, 0) MSE=53.187
ARIMA(6, 1, 1) MSE=57.055
ARIMA(6, 2, 0) MSE=69.753
ARIMA(8, 0, 0) MSE=56.984
ARIMA(8, 1, 0) MSE=57.290
ARIMA(8, 2, 0) MSE=66.034
ARIMA(8, 2, 1) MSE=57.884
ARIMA(10, 0, 0) MSE=57.470
ARIMA(10, 1, 0) MSE=57.359
ARIMA(10, 2, 0) MSE=65.503
ARIMA(10, 2, 1) MSE=57.878
ARIMA(10, 2, 2) MSE=58.309
Best ARIMA(6, 1, 0) MSE=53.187
扩展
本教程中使用的网格搜索方法很简单,可以轻松扩展。
本节列出了一些扩展您可能希望探索的方法的想法。
- 种子网格。 ACF 和 PACF 图的经典诊断工具仍然可以与用于搜索 ARIMA 参数网格的结果一起使用。
- 替代措施。搜索旨在优化样本外均方误差。这可以更改为另一个样本外统计量,样本内统计量,如 AIC 或 BIC,或两者的某种组合。您可以选择对项目最有意义的指标。
- 剩余诊断。可以自动计算残差预测误差的统计量,以提供拟合质量的附加指示。例子包括残差分布是否为高斯分布以及残差中是否存在自相关的统计检验。
- 更新模型。 ARIMA 模型是从零开始为每个一步预测创建的。通过仔细检查 API,可以使用新的观察更新模型的内部数据,而不是从零开始重新创建。
- 前提条件。 ARIMA 模型可以对时间序列数据集做出假设,例如正态性和平稳性。可以检查这些,并在训练给定模型之前针对给定的数据集引发警告。
摘要
在本教程中,您了解了如何在 Python 中搜索 ARIMA 模型的超参数。
具体来说,你学到了:
- 可用于网格搜索 ARIMA 超参数以进行一步滚动预测的过程。
- 如何应用 ARIMA 超参数调整标准单变量时间序列数据集。
- 关于如何进一步改进 ARIMA 超参数网格搜索的思路。
现在轮到你了。
在您喜欢的时间序列数据集上尝试此过程。你得到了什么结果?
在下面的评论中报告您的结果。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。