Machine Learning Mastery 时间序列入门教程(四)
多步时间序列预测的 4 种策略
原文:
machinelearningmastery.com/multi-step-time-series-forecasting/
通常讨论时间序列预测,其中仅需要一步预测。
当你需要预测未来的多个时间步骤时呢?
预测未来的多个时间步骤称为多步时间序列预测。您可以使用四种主要策略进行多步预测。
在这篇文章中,您将发现多步骤时间序列预测的四种主要策略。
阅读这篇文章后,你会知道:
- 一步和多步时间序列预测之间的差异。
- 多步预测的传统直接和递归策略。
- 用于多步预测的较新的直接递归混合和多输出策略。
让我们开始吧。
- 更新 May / 2018 :修正了直接策略示例中的拼写错误。
多步时间序列预测的策略 照片由 debs-eye 拍摄,保留一些权利。
多步预测
通常,时间序列预测描述了在下一个时间步骤预测观测值。
这称为一步预测,因为只预测一个时间步长。
存在一些时间序列问题,其中必须预测多个时间步长。与一步预测相比,这些被称为多步或多步时间序列预测问题。
例如,鉴于过去 7 天观察到的温度:
Time, Temperature
1, 56
2, 50
3, 59
4, 63
5, 52
6, 60
7, 55
单步预测仅需要在时间步骤 8 做出预测。
多步骤可能需要对接下来的两天做出预测,如下所示:
Time, Temperature
8, ?
9, ?
至少有四种常用的策略可用于制定多步骤预测。
他们是:
- 直接多步预测策略。
- 递归多步预测策略。
- 直接递归混合多步预测策略。
- 多输出预测策略。
让我们依次仔细研究每种方法。
1.直接多步预测策略
直接方法涉及为每个预测时间步骤开发单独的模型。
在预测接下来两天的温度的情况下,我们将开发一个用于预测第 1 天温度的模型和用于预测第 2 天温度的单独模型。
例如:
prediction(t+1) = model1(obs(t-1), obs(t-2), ..., obs(t-n))
prediction(t+2) = model2(obs(t-2), obs(t-3), ..., obs(t-n))
每个时间步长具有一个模型是增加的计算和维护负担,尤其是当预测的时间步数增加超过平凡时。
因为使用了单独的模型,这意味着没有机会对预测之间的依赖关系建模,例如第 2 天的预测依赖于第 1 天的预测,这通常是时间序列中的情况。
2.递归多步预测
递归策略涉及多次使用一步模型,其中先前时间步长的预测被用作用于对随后的时间步长做出预测的输入。
在预测未来两天的温度的情况下,我们将开发一步预测模型。然后该模型将用于预测第 1 天,然后该预测将用作观察输入以便预测第 2 天。
例如:
prediction(t+1) = model(obs(t-1), obs(t-2), ..., obs(t-n))
prediction(t+2) = model(prediction(t+1), obs(t-1), ..., obs(t-n))
因为预测被用于代替观察,所以递归策略允许预测误差累积,使得表现可以随着预测时间范围的增加而迅速降低。
3.直接递归混合策略
直接和递归策略可以结合起来,提供两种方法的好处。
例如,可以为要预测的每个时间步骤构建单独的模型,但是每个模型可以使用由先前时间步长的模型做出的预测作为输入值。
我们可以看到这可能如何用于预测接下来两天的温度,其中使用了两个模型,但第一个模型的输出用作第二个模型的输入。
例如:
prediction(t+1) = model1(obs(t-1), obs(t-2), ..., obs(t-n))
prediction(t+2) = model2(prediction(t+1), obs(t-1), ..., obs(t-n))
结合递归和直接策略可以帮助克服每个策略的局限性。
4.多输出策略
多输出策略涉及开发一个能够以一次性方式预测整个预测序列的模型。
在预测接下来两天的温度的情况下,我们将开发一个模型并用它来预测接下来的两天作为一个操作。
例如:
prediction(t+1), prediction(t+2) = model(obs(t-1), obs(t-2), ..., obs(t-n))
多输出模型更复杂,因为它们可以学习输入和输出之间以及输出之间的依赖结构。
更复杂可能意味着他们训练较慢并需要更多数据以避免过拟合问题。
进一步阅读
请参阅以下资源,以进一步阅读多步骤预测。
- 时间序列预测的机器学习策略,2013
- 递归和直接多步预测:两全其美,2012 [PDF]
摘要
在这篇文章中,您发现了可用于进行多步时间序列预测的策略。
具体来说,你学到了:
- 如何在直接策略中训练多个并行模型或在递归策略中重用一步模型。
- 如何在混合策略中结合直接和递归策略的最佳部分。
- 如何使用多输出策略以一次性方式预测整个预测序列。
您对多步骤时间序列预测或此帖子有任何疑问吗?在下面的评论中提出您的问题,我会尽力回答。
如何在 Python 中规范化和标准化时间序列数据
原文:
machinelearningmastery.com/normalize-standardize-time-series-data-python/
如果您的时间序列数据具有一致的比例或分布,则某些机器学习算法将获得更好的表现。
可用于一致地重新缩放时间序列数据的两种技术是规范化和标准化。
在本教程中,您将了解如何将规范化和标准化重新缩放应用于 Python 中的时间序列数据。
完成本教程后,您将了解:
- 使用标准化的数据的规范化和期望的局限性。
- 需要什么参数以及如何手动计算标准化和标准化值。
- 如何使用 Python 中的 scikit-learn 来标准化和标准化您的时间序列数据。
让我们开始吧。
如何在 Python 中标准化和标准化时间序列数据 照片由 Sage Ross 拍摄,保留一些权利。
最低每日温度数据集
该数据集描述了澳大利亚墨尔本市 10 年(1981-1990)的最低日常温度。
单位为摄氏度,有 3,650 个观测值。数据来源被称为澳大利亚气象局。
下面是前 5 行数据的示例,包括标题行。
"Date","Temperatures"
"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
下面是从数据市场获取的整个数据集的图表。
最低每日温度
该数据集显示了一个强大的季节性组件,并具有良好,细粒度的细节。
本教程假定数据集位于当前工作目录中,文件名为“ daily-minimum-temperature-in-me.csv ”。
注意:下载的文件包含一些问号(“?”)字符,必须先将其删除才能使用数据集。在文本编辑器中打开文件并删除“?”字符。同时删除文件中的任何页脚信息。
标准化时间序列数据
归一化是对原始范围内的数据进行重新缩放,以使所有值都在 0 和 1 的范围内。
当你的时间序列数据具有不同尺度的输入值时,归一化可能是有用的,甚至在某些机器学习算法中也是必需的。对于算法,例如 k-最近邻,它使用距离计算和线性回归和人工神经网络可能需要归一化。重量输入值。
标准化要求您知道或能够准确估计最小和最大可观察值。您可以从可用数据中估算这些值。如果您的时间序列趋势向上或向下,估计这些预期值可能会很困难,并且规范化可能不是用于解决问题的最佳方法。
值按如下标准化:
y = (x - min) / (max - min)
其中最小值和最大值与值 x 归一化有关。
例如,对于温度数据,我们可以将最小和最大可观察值猜测为 30 和-10,这些值大大超过和低估。然后我们可以将 18.8 之类的任何值标准化,如下所示:
y = (x - min) / (max - min)
y = (18.8 - -10) / (30 - -10)
y = 28.8 / 40
y = 0.72
您可以看到,如果提供的 x 值超出最小值和最大值的范围,则结果值将不在 0 和 1 的范围内。您可以先检查这些观察结果做出预测并从数据集中删除它们或将它们限制为预定义的最大值或最小值。
您可以使用 scikit-learn 对象 MinMaxScaler 来规范化数据集。
MinMaxScaler和其他重新缩放技术的良好实践用法如下:
- 使用可用的训练数据调整定标器。对于归一化,这意味着训练数据将用于估计最小和最大可观察值。这是通过调用
fit()函数来完成的, - 将比例应用于训练数据。这意味着您可以使用标准化数据来训练模型。这是通过调用
transform()函数来完成的 - 将比例应用于前进的数据。这意味着您可以在将来准备要预测的新数据。
如果需要,可以反转变换。这对于将预测转换回其原始比例以进行报告或绘图非常有用。这可以通过调用inverse_transform()函数来完成。
以下是标准化每日最低温度数据集的示例。
缩放器要求将数据作为行和列的矩阵提供。加载的时间序列数据作为 Pandas _ 系列 _ 加载。然后必须将其重新整形为具有 3,650 行的一列矩阵。
然后使用重新整形的数据集来拟合缩放器,对数据集进行归一化,然后反转归一化变换以再次显示原始值。
# Normalize time series data
from pandas import Series
from sklearn.preprocessing import MinMaxScaler
# load the dataset and print the first 5 rows
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
print(series.head())
# prepare data for normalization
values = series.values
values = values.reshape((len(values), 1))
# train the normalization
scaler = MinMaxScaler(feature_range=(0, 1))
scaler = scaler.fit(values)
print('Min: %f, Max: %f' % (scaler.data_min_, scaler.data_max_))
# normalize the dataset and print the first 5 rows
normalized = scaler.transform(values)
for i in range(5):
print(normalized[i])
# inverse transform and print the first 5 rows
inversed = scaler.inverse_transform(normalized)
for i in range(5):
print(inversed[i])
运行该示例将从已加载的数据集中打印前 5 行,以其标准化形式显示相同的 5 个值,然后使用逆变换将值返回其原始比例。
我们还可以看到数据集的最小值和最大值分别为 0 和 26.3。
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
Min: 0.000000, Max: 26.300000
[ 0.78707224]
[ 0.68060837]
[ 0.7148289]
[ 0.55513308]
[ 0.60076046]
[ 20.7]
[ 17.9]
[ 18.8]
[ 14.6]
[ 15.8]
还有另一种类型的重新缩放对于超出预期值范围的新值更加稳健;这称为标准化。我们接下来会看一下。
标准化时间序列数据
标准化数据集涉及重缩放值的分布,以便观察值的平均值为 0,标准差为 1。
这可以被认为是减去平均值或使数据居中。
与标准化一样,当您的时间序列数据具有不同比例的输入值时,标准化可能是有用的,甚至在某些机器学习算法中也是必需的。
标准化假定您的观察结果符合高斯分布(钟形曲线),具有良好的平均值和标准偏差。如果不满足此期望,您仍然可以标准化时间序列数据,但可能无法获得可靠的结果。
这包括支持向量机,线性和逻辑回归等算法,以及其他假设或使用高斯数据提高表现的算法。
标准化要求您知道或能够准确估计可观察值的均值和标准差。您可以从训练数据中估算这些值。
值标准化如下:
y = (x - mean) / standard_deviation
_ 表示 _ 的计算方法如下:
mean = sum(x) / count(x)
standard_deviation计算如下:
standard_deviation = sqrt( sum( (x - mean)² ) / count(x))
例如,我们可以绘制最低每日温度数据集的直方图,如下所示:
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
series.hist()
pyplot.show()
运行代码会给出以下图表,该图表显示数据集的高斯分布,如标准化所假设的那样。
最低每日温度直方图
我们可以估计平均温度为 10,标准偏差约为 5.使用这些值,我们可以将数据集中的第一个值标准化为 20.7,如下所示:
y = (x - mean) / standard_deviation
y = (20.7 - 10) / 5
y = (10.7) / 5
y = 2.14
数据集的均值和标准差估计值对于新数据可能比最小值和最大值更稳健。
您可以使用 scikit-learn 对象 StandardScaler 标准化数据集。
以下是标准化每日最低温度数据集的示例。
# Standardize time series data
from pandas import Series
from sklearn.preprocessing import StandardScaler
from math import sqrt
# load the dataset and print the first 5 rows
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
print(series.head())
# prepare data for standardization
values = series.values
values = values.reshape((len(values), 1))
# train the standardization
scaler = StandardScaler()
scaler = scaler.fit(values)
print('Mean: %f, StandardDeviation: %f' % (scaler.mean_, sqrt(scaler.var_)))
# standardization the dataset and print the first 5 rows
normalized = scaler.transform(values)
for i in range(5):
print(normalized[i])
# inverse transform and print the first 5 rows
inversed = scaler.inverse_transform(normalized)
for i in range(5):
print(inversed[i])
运行该示例将打印数据集的前 5 行,打印标准化的相同值,然后以原始比例打印值。
我们可以看到估计的平均值和标准偏差分别为 11.1 和 4.0。
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
Mean: 11.177753, StandardDeviation: 4.071279
[ 2.33888328]
[ 1.65113873]
[ 1.87219948]
[ 0.84058266]
[ 1.13533032]
[ 20.7]
[ 17.9]
[ 18.8]
[ 14.6]
[ 15.8]
摘要
在本教程中,您了解了如何在 Python 中规范化和标准化时间序列数据。
具体来说,你学到了:
- 一些机器学习算法在建模时表现更好甚至需要重缩放数据。
- 如何手动计算规范化和标准化所需的参数。
- 如何使用 Python 中的 scikit-learn 对时间序列数据进行标准化和标准化。
您对重新缩短时间序列数据或此帖子有任何疑问吗? 在评论中提出您的问题,我会尽力回答。
如何利用 Python 为时间序列预测做出基线预测
原文:
machinelearningmastery.com/persistence-time-series-forecasting-with-python/
在任何时间序列预测问题上建立基线都是必不可少的。
表现基线可让您了解所有其他模型对您的问题的实际执行情况。
在本教程中,您将了解如何开发持久性预测,您可以使用它来计算使用 Python 的时间序列数据集的基准表现级别。
完成本教程后,您将了解:
- 计算时间序列预测问题的绩效基线的重要性。
- 如何在 Python 中从头开发持久性模型。
- 如何从持久性模型评估预测并使用它来建立表现基线。
让我们开始吧。
如何使用 Python 进行时间序列预测的基线预测 照片由 Bernard Spragg 撰写。 NZ ,保留一些权利。
预测绩效基准
预测表现的基线提供了一个比较点。
它是您问题的所有其他建模技术的参考点。如果模型达到或低于基线的表现,则应该修复或放弃该技术。
用于生成预测以计算基准表现的技术必须易于实现,并且不需要特定于问题的细节。
在为预测问题建立表现基线之前,必须开发测试工具。这包括:
- 您打算用于训练和评估模型的数据集。
- 您打算使用重采样技术来估算技术的表现(例如,训练/测试拆分)。
- 您打算用于评估预测的表现指标(例如均方误差)。
准备好之后,您需要选择一种朴素的技术,您可以使用该技术做出预测并计算基准表现。
目标是尽快获得时间序列预测问题的基线表现,以便您可以更好地理解数据集并开发更高级的模型。
用于进行基线预测的良好技术的三个属性是:
- 简单:一种几乎不需要训练或智力的方法。
- Fast :一种快速实现并且计算上很容易做出预测的方法。
- 可重复:一种确定性的方法,意味着它在给定相同输入的情况下产生预期输出。
用于建立基线表现的常用算法是持久性算法。
持久性算法(“朴素”预测)
监督机器学习的最常见基线方法是零规则算法。
该算法在分类的情况下预测多数类,或在回归的情况下预测平均结果。这可用于时间序列,但不考虑时间序列数据集中的序列相关结构。
与时间序列数据集一起使用的等效技术是持久性算法。
持久性算法使用前一时间步(t-1)的值来预测下一时间步(t + 1)的预期结果。
这满足了基线预测的上述三个条件。
为了具体化,我们将研究如何开发持久性模型并使用它来为简单的单变量时间序列问题建立基线表现。首先,让我们回顾一下 Shampoo Sales 数据集。
洗发水销售数据集
该数据集描述了 3 年期间每月的洗发水销售数量。
单位是销售计数,有 36 个观察。原始数据集归功于 Makridakis,Wheelwright 和 Hyndman(1998)。
下面是前 5 行数据的示例,包括标题行。
"Month","Sales"
"1-01",266.0
"1-02",145.9
"1-03",183.1
"1-04",119.3
"1-05",180.3
下面是从数据市场中获取的整个数据集的图表,您可以在其中下载数据集并了解有关它的更多信息。
洗发水销售数据集
数据集显示出增长趋势,可能还有一些季节性因素。
下载数据集并将其放在当前工作目录中,文件名为“ shampoo-sales.csv ”。
以下代码片段将加载 Shampoo Sales 数据集并绘制时间序列。
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()
运行该示例绘制时间序列,如下所示:
洗发水销售数据集图
持久性算法
可以在 Python 中轻松实现持久性模型。
我们将这一部分分为 4 个步骤:
- 将单变量数据集转换为监督学习问题。
- 为测试工具建立训练和测试数据集。
- 定义持久性模型。
- 做出预测并建立基准表现。
- 查看完整示例并绘制输出。
让我们潜入。
第 1 步:定义监督学习问题
第一步是加载数据集并创建滞后表示。也就是说,鉴于在 t-1 处的观察,预测在 t + 1 处的观察。
# Create lagged dataset
values = DataFrame(series.values)
dataframe = concat([values.shift(1), values], axis=1)
dataframe.columns = ['t-1', 't+1']
print(dataframe.head(5))
此代码段创建数据集并打印新数据集的前 5 行。
我们可以看到第一行(索引 0)将不得不被丢弃,因为在第一次观察之前没有观察用于做出预测。
从监督学习的角度来看,t-1 列是输入变量或 X,而 t + 1 列是输出变量或 y。
t-1 t+1
0 NaN 266.0
1 266.0 145.9
2 145.9 183.1
3 183.1 119.3
4 119.3 180.3
第 2 步:训练和测试集
下一步是将数据集分成训练集和测试集。
我们将保留前 66%的“训练”观察结果,其余 34%用于评估。在拆分期间,我们小心地排除具有 NaN 值的第一行数据。
在这种情况下不需要训练;这只是习惯。然后将每个训练和测试集分成输入和输出变量。
# split into train and test sets
X = dataframe.values
train_size = int(len(X) * 0.66)
train, test = X[1:train_size], X[train_size:]
train_X, train_y = train[:,0], train[:,1]
test_X, test_y = test[:,0], test[:,1]
第 3 步:持久性算法
我们可以将持久性模型定义为一个返回作为输入提供的值的函数。
例如,如果提供了 t6 值为 266.0,那么这将作为预测返回,而实际的实际值或期望值恰好是 145.9(取自滞后数据集中的第一个可用行)。
# persistence model
def model_persistence(x):
return x
第 4 步:制作并评估预测
现在我们可以在测试数据集上评估此模型。
我们使用前向验证方法执行此操作。
不需要模型训练或再训练,因此实质上,我们逐步逐步测试数据集时间并获得预测。
一旦对训练数据集中的每个时间步做出预测,就将它们与预期值进行比较,并计算均方误差(MSE)分数。
# walk-forward validation
predictions = list()
for x in test_X:
yhat = model_persistence(x)
predictions.append(yhat)
test_score = mean_squared_error(test_y, predictions)
print('Test MSE: %.3f' % test_score)
在这种情况下,测试数据集的误差超过 17,730。
Test MSE: 17730.518
第 5 步:完成示例
最后,绘制一个图来显示训练数据集和来自测试数据集的预期值的偏差预测。
从持久性模型预测的情节来看,很明显该模型落后于现实一步。销售数据中出现了上升趋势和月度噪音,凸显了持久性技术的局限性。
洗发水销售持久性模型
下面列出了完整的示例。
from pandas import read_csv
from pandas import datetime
from pandas import DataFrame
from pandas import concat
from matplotlib import pyplot
from sklearn.metrics import mean_squared_error
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)
# Create lagged dataset
values = DataFrame(series.values)
dataframe = concat([values.shift(1), values], axis=1)
dataframe.columns = ['t-1', 't+1']
print(dataframe.head(5))
# split into train and test sets
X = dataframe.values
train_size = int(len(X) * 0.66)
train, test = X[1:train_size], X[train_size:]
train_X, train_y = train[:,0], train[:,1]
test_X, test_y = test[:,0], test[:,1]
# persistence model
def model_persistence(x):
return x
# walk-forward validation
predictions = list()
for x in test_X:
yhat = model_persistence(x)
predictions.append(yhat)
test_score = mean_squared_error(test_y, predictions)
print('Test MSE: %.3f' % test_score)
# plot predictions and expected results
pyplot.plot(train_y)
pyplot.plot([None for i in train_y] + [x for x in test_y])
pyplot.plot([None for i in train_y] + [x for x in predictions])
pyplot.show()
我们已经看到了从零开始为 Shampoo Sales 问题开发的持久性模型的示例。
持久性算法很幼稚。它通常被称为 _ 朴素的预测 _。
它没有假设应用它的时间序列问题的具体细节。这使得它易于理解,如此快速地实现和评估。
作为机器学习从业者,它也可以激发大量的改进。
记下来。
这很有用,因为这些想法可以成为特征工程工作中的输入要素,或者可以在以后的集合工作中组合的简单模型。
摘要
在本教程中,您了解了如何使用 Python 建立时间序列预测问题的基线表现。
具体来说,你学到了:
- 建立基线和可以使用的持久性算法的重要性。
- 如何从零开始在 Python 中实现持久性算法。
- 如何评估持久性算法的预测并将其用作基线。
您对基线表现或本教程有任何疑问吗? 在下面的评论中提出您的问题,我会尽力回答。
如何使用 Python 对时间序列预测数据执行幂变换
原文:
machinelearningmastery.com/power-transform-time-series-forecast-data-python/
数据转换旨在消除噪声并改善时间序列预测中的信号。
对于给定的预测问题,选择良好甚至最佳的变换可能非常困难。有许多变换可供选择,每个变换都有不同的数学直觉。
在本教程中,您将了解如何使用 Python 探索不同的基于功能的变换以进行时间序列预测。
完成本教程后,您将了解:
- 如何识别何时使用以及如何探索平方根变换。
- 如何识别何时使用和探索日志转换以及对原始数据的期望。
- 如何使用 Box-Cox 变换执行平方根,记录并自动发现数据集的最佳幂变换。
让我们开始吧。
航空公司乘客数据集
航空公司乘客数据集描述了一段时间内航空公司乘客的总数。
这些单位是数千名航空公司乘客的数量。从 1949 年到 1960 年,每月有 144 次观察。
了解更多信息并从数据市场下载数据集。
使用文件名“ airline-passengers.csv ”将数据集下载到当前工作目录。
下面的示例加载数据集并绘制数据。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(series)
# histogram
pyplot.subplot(212)
pyplot.hist(series)
pyplot.show()
运行该示例将创建两个图,第一个图显示时间序列作为线图,第二个图显示观察结果作为直方图。
航空公司乘客数据集图
数据集是非平稳的,意味着观测值的均值和方差随时间而变化。这使得难以通过 ARIMA 等经典统计方法和更复杂的机器学习方法(如神经网络)进行建模。
这是由似乎既是增长趋势又是季节性因素引起的。
此外,变化量或方差随时间增加。当您查看季节性组件的大小时,这很明显,并注意到从一个周期到下一个周期,振幅(从周期的底部到顶部)正在增加。
在本教程中,我们将研究可以在展示此属性的时间序列数据集上使用的变换。
平方根变换
具有二次增长趋势的时间序列可以通过取平方根而成为线性的。
让我们用一个快速设计的例子来证明这一点。
考虑一系列数字 1 到 99 的平方。该系列的线图将显示二次增长趋势,值的直方图将显示具有长轨迹的指数分布。
下面的代码片段创建并绘制了这个系列的图表。
from matplotlib import pyplot
series = [i**2 for i in range(1,100)]
# line plot
pyplot.plot(series)
pyplot.show()
# histogram
pyplot.hist(series)
pyplot.show()
运行该示例将该系列绘制为随时间变化的线图和观察的直方图。
二次时间序列
如果您在自己的时间序列中看到这样的结构,则可能会出现二次增长趋势。通过采用平方过程的平方根的逆运算,可以将其去除或变为线性。
因为该示例是完全二次的,我们期望变换数据的线图显示直线。因为平方序列的源是线性的,我们期望直方图显示均匀分布。
下面的示例对时间序列执行sqrt()变换并绘制结果。
from matplotlib import pyplot
from numpy import sqrt
series = [i**2 for i in range(1,100)]
# sqrt transform
transform = series = sqrt(series)
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(transform)
# histogram
pyplot.subplot(212)
pyplot.hist(transform)
pyplot.show()
我们可以看到,正如预期的那样,二次趋势是线性的。
二次时间序列的平方根变换
航空公司乘客数据集可能显示二次增长。如果是这种情况,那么我们可以期望平方根变换将增长趋势减小为线性并且将观测的分布改变为可能接近高斯。
下面的示例执行数据集的平方根并绘制结果。
from pandas import Series
from pandas import DataFrame
from numpy import sqrt
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
dataframe = DataFrame(series.values)
dataframe.columns = ['passengers']
dataframe['passengers'] = sqrt(dataframe['passengers'])
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(dataframe['passengers'])
# histogram
pyplot.subplot(212)
pyplot.hist(dataframe['passengers'])
pyplot.show()
我们可以看到趋势减少了,但没有被删除。
线图仍显示从周期到周期的变化增加。直方图仍显示分布右侧的长尾,表明指数或长尾分布。
航空旅客数据集地块的平方根变换
日志转换
一类更极端的趋势是指数级的,通常作为曲棍球棒。
通过取值的对数,可以使具有指数分布的时间序列成为线性。这称为日志转换。
与上面的方形和平方根情况一样,我们可以通过一个简单的例子来证明这一点。
下面的代码通过将数字从 1 提高到 99 来创建指数分布e,这是自然对数或欧拉数的基数( 2.718 ...)。
from matplotlib import pyplot
from math import exp
series = [exp(i) for i in range(1,100)]
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(series)
# histogram
pyplot.subplot(212)
pyplot.hist(series)
pyplot.show()
运行该示例将创建序列的线图和观察分布的直方图。
我们看到线图上的极端增加以及直方图上同样极端的长尾分布。
指数时间序列
同样,我们可以通过获取值的自然对数将此系列转换回线性。
这将使串联线性和分布均匀。以下示例说明了这一点的完整性。
from matplotlib import pyplot
from math import exp
from numpy import log
series = [exp(i) for i in range(1,100)]
transform = log(series)
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(transform)
# histogram
pyplot.subplot(212)
pyplot.hist(transform)
pyplot.show()
运行该示例会创建绘图,显示预期的线性结果。
对数变换的指数时间序列
我们的航空公司乘客数据集有这种形式的分布,但也许不是这种极端。
以下示例演示了 Airline Passengers 数据集的日志转换。
from pandas import Series
from pandas import DataFrame
from numpy import log
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
dataframe = DataFrame(series.values)
dataframe.columns = ['passengers']
dataframe['passengers'] = log(dataframe['passengers'])
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(dataframe['passengers'])
# histogram
pyplot.subplot(212)
pyplot.hist(dataframe['passengers'])
pyplot.show()
运行该示例会导致趋势看起来比上面的平方根变换更加线性。线图显示看似线性的增长和方差。
直方图还显示更均匀或压扁的类高斯分布的观测值。
航空旅客数据集的日志变换
日志变换在时间序列数据中很受欢迎,因为它们在消除指数方差方面很有效。
重要的是要注意,此操作假定值为正且非零。通常通过添加固定常数来转换观察值以确保所有输入值满足此要求。例如:
transform = log(constant + x)
当 _ 变换 _ 是变换序列时,_ 常数 _ 是一个固定值,它将所有观测值提升到零以上,x是时间序列。
Box-Cox 变换
平方根变换和对数变换属于称为功率变换的一类变换。
Box-Cox 变换是一种可配置的数据变换方法,支持平方根和对数变换,以及一套相关的变换。
更重要的是,它可以配置为自动评估一组变换并选择最佳拟合。它可以被认为是一种电动工具,可以消除时间序列中基于功率的变化。得到的序列可能更线性,得到的分布更高斯或均匀,这取决于生成它的基础过程。
scipy.stats 库提供了 Box-Cox 变换的实现。 boxcox()函数接受一个名为lambda的参数,它控制要执行的变换类型。
以下是 lambda 的一些常见值
lambda= -1。是一个互惠的变换。lambda= -0.5 是倒数平方根变换。lambda= 0.0 是对数变换。lambda= 0.5 是平方根变换。lambda= 1.0 是无变换。
例如,我们可以使用boxcox()函数执行日志转换,如下所示:
from pandas import Series
from pandas import DataFrame
from scipy.stats import boxcox
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
dataframe = DataFrame(series.values)
dataframe.columns = ['passengers']
dataframe['passengers'] = boxcox(dataframe['passengers'], lmbda=0.0)
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(dataframe['passengers'])
# histogram
pyplot.subplot(212)
pyplot.hist(dataframe['passengers'])
pyplot.show()
运行该示例将重现上一节中的日志转换。
BoxCox 日志变换的航空公司乘客数据集图
我们可以将 lambda 参数设置为 None(默认值),并让函数找到统计调整的值。
以下示例演示了此用法,返回已转换的数据集和所选的lambda值。
from pandas import Series
from pandas import DataFrame
from scipy.stats import boxcox
from matplotlib import pyplot
series = Series.from_csv('airline-passengers.csv', header=0)
dataframe = DataFrame(series.values)
dataframe.columns = ['passengers']
dataframe['passengers'], lam = boxcox(dataframe['passengers'])
print('Lambda: %f' % lam)
pyplot.figure(1)
# line plot
pyplot.subplot(211)
pyplot.plot(dataframe['passengers'])
# histogram
pyplot.subplot(212)
pyplot.hist(dataframe['passengers'])
pyplot.show()
运行该示例发现lambda值为 0.148023。
我们可以看到这非常接近λ值为 0.0,导致对数变换并且对于平方根变换更强(小于)0.5。
Lambda: 0.148023
线和直方图也与对数变换非常相似。
BoxCox 自动转换航空公司乘客数据集图
摘要
在本教程中,您了解了如何使用 Python 识别何时使用以及如何对时间序列数据使用不同的电源变换。
具体来说,你学到了:
- 如何识别二次变化并使用平方根变换。
- 如何识别指数变化以及如何使用日志变换。
- 如何使用 Box-Cox 变换执行平方根和对数变换,并自动优化数据集的变换。
您对电源变换或本教程有任何疑问吗? 在下面的评论中提出您的问题,我会尽力回答。
用于时间序列预测的 Python 环境
原文:
machinelearningmastery.com/python-environment-time-series-forecasting/
Python 生态系统正在发展,可能成为应用机器学习的主要平台。
采用 Python 进行时间序列预测的主要原因是因为它是一种通用编程语言,可以用于 R& D 和生产。
在这篇文章中,您将发现用于时间序列预测的 Python 生态系统。
阅读这篇文章后,你会知道:
- 三个标准 Python 库,对时间序列预测至关重要。
- 如何安装和设置 Python 和 SciPy 环境以进行开发。
- 如何确认您的环境正常工作并准备好进行时间序列预测。
让我们开始吧。
用于时间序列预测的 Python 环境 照片由 Joao Trindade 拍摄,保留一些权利。
为何选择 Python?
Python 是一种通用的解释型编程语言(与 R 或 Matlab 不同)。
它易于学习和使用,主要是因为语言侧重于可读性。
它是一种流行语言,在 StackOverflow 调查中始终出现在前 10 种编程语言中(例如, 2015 年调查结果)。
Python 是一种动态语言,非常适合交互式开发和快速原型设计,具有支持大型应用程序开发的能力。
由于具有出色的库支持,Python 还广泛用于机器学习和数据科学。它已经迅速成为机器学习和数据科学从业者的主导平台之一,并且比雇主对 R 平台的需求更大(见下图)。
Python 机器学习工作与 R 机器学习工作
这是一个简单而非常重要的考虑因素。
这意味着您可以使用您在操作中使用的相同编程语言执行研究和开发(确定要使用的模型),从而大大简化从开发到操作的过渡。
时间序列的 Python 库
SciPy 是一个用于数学,科学和工程的 Python 库生态系统。它是 Python 的附加组件,您需要进行时间序列预测。
两个 SciPy 库为大多数其他库提供了基础;它们是用于提供高效数组操作的 NumPy 和用于绘制数据的 Matplotlib 。有三个更高级别的 SciPy 库为 Python 中的时间序列预测提供关键功能。
它们分别是数据处理,时间序列建模和机器学习的熊猫,statsmodel 和 scikit-learn。
让我们依次仔细研究一下。
库:熊猫
pandas 库提供了用于在 Python 中加载和处理数据的高表现工具。
它建立在 SciPy 生态系统的基础上,主要使用 NumPy 数组,但提供方便易用的数据结构,如DataFrame和 _ 系列 _,用于表示数据。
Pandas 提供特别关注对时间序列数据的支持。
与大熊猫时间序列预测相关的主要功能包括:
- 用于表示单变量时间序列的 _ 系列 _ 对象。
- 显式处理数据和日期时间范围中的日期时间索引。
- 变换,如移位,滞后和填充。
- 重采样方法,如上采样,下采样和聚合。
库:statsmodels
statsmodels 库提供统计建模工具。
它建立在 SciPy 生态系统的基础上,并支持 NumPy 数组和 Pandas _ 系列 _ 对象形式的数据。
它提供了一套统计测试和建模方法,以及专用于时间序列分析的工具,它们也可用于预测。
与时间序列预测相关的 statsmodels 的主要功能包括:
- 平稳性的统计测试,例如 Augmented Dickey-Fuller 单位根检验。
- 时间序列分析图,如自相关函数(ACF)和部分自相关函数(PACF)。
- 线性时间序列模型,如自回归(AR),移动平均线(MA),自回归移动平均线(ARMA)和自回归综合移动平均线(ARIMA)。
库:scikit-learn
scikit-learn 库是如何在 Python 中开发和练习机器学习的。
它建立在 SciPy 生态系统的基础之上。名称“sckit”表明它是一个 SciPy 插件或工具包。您可以查看可用的 SciKits 的完整列表。
该库的重点是用于分类,回归,聚类等的机器学习算法。它还为相关任务提供工具,例如评估模型,调整参数和预处理数据。
与 scikit-learn 中的时间序列预测相关的主要功能包括:
- 数据准备工具套件,例如缩放和输入数据。
- 机器学习算法套件,可用于建模数据和做出预测。
- 用于估计模型在看不见的数据上的表现的重采样方法,特别是 TimeSeriesSplit 。
Python 生态系统安装
本节将为您提供有关为时间序列预测设置 Python 环境的一般建议。
我们将涵盖:
- 使用 Anaconda 自动安装。
- 使用平台的包管理手动安装。
- 确认已安装的环境。
如果您已经有一个正常运行的 Python 环境,请跳至确认步骤以检查您的软件库是否是最新的。
让我们潜入。
1.自动安装
如果您对在计算机上安装软件或在 Microsoft Windows 上安装软件没有信心,那么您可以轻松选择。
有一个名为 Anaconda Python 的发行版,您可以免费下载和安装。
它支持 Microsoft Windows,Mac OS X 和 Linux 三个主要平台。
它包括 Python,SciPy 和 scikit-learn:学习,练习和使用 Python 环境进行时间序列预测所需的一切。
你可以在这里开始使用 Anaconda Python:
2.手动安装
有多种方法可以安装特定于您的平台的 Python 生态系统。
在本节中,我们将介绍如何安装 Python 生态系统以进行时间序列预测。
如何安装 Python
第一步是安装 Python。我更喜欢使用和推荐 Python 2.7 或 Python 3.5。
Python 的安装将特定于您的平台。有关说明请参阅:
- 在 Python 初学者指南中下载 Python
在 Mac OS X 上使用 macports,我会输入:
sudo port install python35
sudo port select --set python python35
sudo port select --set python3 python35
如何安装 SciPy
安装 SciPy 的方法有很多种。
例如,两种流行的方法是在您的平台上使用包管理(例如 RedHat 上的dnf或 OS X 上的macports)或使用 Python 包管理工具,如pip。
SciPy 文档非常出色,涵盖了页面上许多不同平台的操作说明安装 SciPy Stack 。
安装 SciPy 时,请确保至少安装以下软件包:
- SciPy 的
- numpy 的
- matplotlib
- 大熊猫
- statsmodels
在带有macports的 Mac OS X 上,我会输入:
sudo port install py35-numpy py35-scipy py35-matplotlib py35-pandas py35-statsmodels py35-pip
sudo port select --set pip pip35
在 Fedora Linux 上使用dnf,我会输入:
sudo dnf install python3-numpy python3-scipy python3-pandas python3-matplotlib python3-statsmodels
如何安装 scikit-learn
scikit-learn 库必须单独安装。
我建议您使用相同的方法安装 scikit-learn,就像您以前安装 SciPy 一样。
有指令用于安装 scikit-learn ,但它们仅限于使用 Pythonpip包管理器。
在 Linux 和 Mac OS X 上,我输入了 scikit-learn:
sudo pip install -U scikit-learn
3.确认您的环境
设置完环境后,必须确认它是否按预期工作。
我们首先检查 Python 是否已成功安装。打开命令行并键入:
python -V
您应该看到如下响应:
Python 2.7.12
要么
Python 3.5.3
现在,确认已成功安装库。
创建一个名为 versions.py 的新文件,并将以下代码段复制并粘贴到其中,并将文件另存为versions.py。
# scipy
import scipy
print('scipy: %s' % scipy.__version__)
# numpy
import numpy
print('numpy: %s' % numpy.__version__)
# matplotlib
import matplotlib
print('matplotlib: %s' % matplotlib.__version__)
# pandas
import pandas
print('pandas: %s' % pandas.__version__)
# statsmodels
import statsmodels
print('statsmodels: %s' % statsmodels.__version__)
# scikit-learn
import sklearn
print('sklearn: %s' % sklearn.__version__)
在命令行或您喜欢的 Python 编辑器中运行该文件。例如,键入:
python versions.py
这将打印您需要的每个密钥库的版本。
例如,在撰写本文时,我的系统得到了以下结果:
scipy: 0.18.1
numpy: 1.11.3
matplotlib: 1.5.3
pandas: 0.19.1
statsmodels: 0.6.1
sklearn: 0.18.1
如果您有错误,请立即停止并修复它。您可能需要查阅特定于您的平台的文档。
摘要
在这篇文章中,您发现了用于时间序列预测的 Python 生态系统。
你了解到:
- 大熊猫,statsmodels 和 scikit-learn 库是用 Python 预测的顶级时间序列。
- 如何自动和手动设置 Python SciPy 环境以进行开发。
- 如何确认您的环境已正确安装,并且您已准备好开始开发模型。
您还学习了如何在工作站上安装用于机器学习的 Python 生态系统。
您对 Python 的时间序列预测或此帖有任何疑问吗?在评论中提出您的问题,我会尽力回答。
用于时间序列预测的随机森林
随机森林是一种流行且有效的集成机器学习算法。
它广泛用于结构化(表格)数据集的分类和回归预测建模问题,例如电子表格或数据库表中的数据。
随机森林也可以用于时间序列预测,尽管它需要先将时间序列数据集转化为有监督的学习问题。它还需要使用一种专门的技术来评估模型,称为向前验证,因为使用 k-fold 交叉验证来评估模型会导致乐观偏差的结果。
在本教程中,您将发现如何开发用于时间序列预测的随机森林模型。
完成本教程后,您将知道:
- 随机森林是决策树算法的集合,可用于分类和回归预测建模。
- 可以使用滑动窗口表示将时间序列数据集转换为监督学习。
- 如何使用随机森林回归模型拟合、评估和预测时间序列预测。
我们开始吧。
时间序列预测随机森林 图片由 IvyMike 提供,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 随机森林集合
- 时间序列数据准备
- 时间序列的随机森林
随机森林集合
随机森林是决策树算法的集成。
它是决策树自举聚合(bagging) 的扩展,可用于分类和回归问题。
在打包过程中,会生成许多决策树,其中每个树都是从训练数据集的不同引导样本中创建的。引导样本是训练数据集的样本,其中一个示例可能在样本中出现不止一次。这被称为“带替换的采样”。
Bagging 是一种有效的集成算法,因为每个决策树都适合于稍微不同的训练数据集,并且反过来具有稍微不同的表现。与普通的决策树模型(如分类和回归树(CART))不同,集成中使用的树是未标记的,这使得它们略微超出了训练数据集。这是可取的,因为它有助于使每棵树更加不同,并且具有较少的相关预测或预测误差。
来自这些树的预测在所有决策树中被平均,导致比模型中的任何单个树更好的表现。
回归问题的预测是集合中所有树的预测平均值。对分类问题的预测是对集合中所有树的类别标签的多数投票。
- 回归:预测是整个决策树的平均预测。
- 分类:预测是跨决策树预测的多数票类标签。
随机森林包括从训练数据集中的自举样本构建大量决策树,如 bagging。
与打包不同,随机森林还包括在构建树的每个分割点选择输入特征(列或变量)的子集。通常,构建决策树包括评估数据中每个输入变量的值,以便选择分割点。通过将特征简化为可以在每个分割点考虑的随机子集,它迫使集合中的每个决策树更加不同。
结果是,由系综中的每棵树做出的预测,进而预测误差,或多或少是不同的或相关的。当对来自这些相关性较低的树的预测进行平均以做出预测时,它通常比袋装决策树产生更好的表现。
有关随机森林算法的更多信息,请参见教程:
时间序列数据准备
时间序列数据可以被称为监督学习。
给定一个时间序列数据集的数字序列,我们可以重构数据,使其看起来像一个有监督的学习问题。我们可以通过使用以前的时间步长作为输入变量,并使用下一个时间步长作为输出变量来实现这一点。
让我们用一个例子来具体说明。假设我们有一个时间序列如下:
time, measure
1, 100
2, 110
3, 108
4, 115
5, 120
我们可以通过使用前一时间步的值来预测下一时间步的值,从而将这个时间序列数据集重构为一个有监督的学习问题。
以这种方式重新组织时间序列数据集,数据将如下所示:
X, y
?, 100
100, 110
110, 108
108, 115
115, 120
120, ?
请注意,时间列被删除,一些数据行不可用于训练模型,例如第一行和最后一行。
这种表示被称为滑动窗口,因为输入和预期输出的窗口随着时间向前移动,为监督学习模型创建新的“样本”。
有关准备时间序列预测数据的滑动窗口方法的更多信息,请参见教程:
我们可以使用 Pandas 中的 shift()函数在给定输入和输出序列的期望长度的情况下,自动创建时间序列问题的新框架。
这将是一个有用的工具,因为它将允许我们用机器学习算法探索时间序列问题的不同框架,看看哪一个可能导致更好的模型。
下面的函数将把一个时间序列作为一个具有一列或多列的 NumPy 数组时间序列,并将其转换为具有指定数量的输入和输出的监督学习问题。
# transform a time series dataset into a supervised learning dataset
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg.values
我们可以使用这个函数为随机森林准备一个时间序列数据集。
有关该函数逐步开发的更多信息,请参见教程:
一旦准备好数据集,我们必须小心如何使用它来拟合和评估模型。
例如,用未来的数据拟合模型并让它预测过去是无效的。模型必须基于过去进行训练,并预测未来。
这意味着在评估期间随机化数据集的方法,如 k 倍交叉验证,不能使用。相反,我们必须使用一种叫做向前验证的技术。
在向前行走验证中,首先通过选择切割点将数据集分割成训练集和测试集,例如,除了最后 12 个月之外的所有数据都用于训练,最后 12 个月用于测试。
如果我们有兴趣进行一步预测,例如一个月,那么我们可以通过在训练数据集上训练和预测测试数据集中的第一步来评估模型。然后,我们可以将测试集中的真实观察值添加到训练数据集中,重新调整模型,然后让模型预测测试数据集中的第二步。
对整个测试数据集重复这一过程将给出对整个测试数据集的一步预测,由此可以计算误差度量来评估模型的技能。
有关向前验证的更多信息,请参见教程:
下面的函数执行向前行走验证。
它将时间序列数据集的整个监督学习版本和用作测试集的行数作为参数。
然后它遍历测试集,调用 random_forest_forecast() 函数进行一步预测。计算误差度量,并返回详细信息进行分析。
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# split test row into input and output columns
testX, testy = test[i, :-1], test[i, -1]
# fit model on history and make a prediction
yhat = random_forest_forecast(history, testX)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# summarize progress
print('>expected=%.1f, predicted=%.1f' % (testy, yhat))
# estimate prediction error
error = mean_absolute_error(test[:, -1], predictions)
return error, test[:, 1], predictions
调用 train_test_split() 函数将数据集拆分为训练集和测试集。
我们可以在下面定义这个函数。
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test, :], data[-n_test:, :]
我们可以使用randomforestreversor类进行一步预测。
下面的 random_forest_forecast() 函数实现了这一点,以训练数据集和测试输入行为输入,拟合一个模型,进行一步预测。
# fit an random forest model and make a one step prediction
def random_forest_forecast(train, testX):
# transform list into array
train = asarray(train)
# split into input and output columns
trainX, trainy = train[:, :-1], train[:, -1]
# fit model
model = RandomForestRegressor(n_estimators=1000)
model.fit(trainX, trainy)
# make a one-step prediction
yhat = model.predict([testX])
return yhat[0]
现在我们知道了如何准备时间序列数据来预测和评估随机森林模型,接下来我们可以看看在真实数据集上使用随机森林。
时间序列的随机森林
在本节中,我们将探讨如何使用随机森林回归器进行时间序列预测。
我们将使用标准的单变量时间序列数据集,目的是使用该模型进行一步预测。
您可以将本节中的代码用作自己项目的起点,并轻松地将其用于多元输入、多元预测和多步预测。
我们将使用每日女性出生数据,即三年间的每月出生数据。
您可以从这里下载数据集,并将其放在当前工作目录中,文件名为“每日女性出生总数. csv ”。
数据集的前几行如下所示:
"Date","Births"
"1959-01-01",35
"1959-01-02",32
"1959-01-03",30
"1959-01-04",31
"1959-01-05",44
...
首先,让我们加载并绘制数据集。
下面列出了完整的示例。
# load and plot the time series dataset
from pandas import read_csv
from matplotlib import pyplot
# load dataset
series = read_csv('daily-total-female-births.csv', header=0, index_col=0)
values = series.values
# plot dataset
pyplot.plot(values)
pyplot.show()
运行该示例会创建数据集的线图。
我们可以看到没有明显的趋势或季节性。
月出生时间序列数据集的线图
当预测最后 12 个月时,持久性模型可以实现大约 6.7 个出生的 MAE。这提供了一个表现基线,在这个基线之上,模型可以被认为是熟练的。
接下来,当对过去 12 个月的数据进行一步预测时,我们可以在数据集上评估随机森林模型。
我们将只使用前面的六个时间步长作为模型和默认模型超参数的输入,除了我们将在集合中使用 1000 棵树(以避免欠学习)。
下面列出了完整的示例。
# forecast monthly births with random forest
from numpy import asarray
from pandas import read_csv
from pandas import DataFrame
from pandas import concat
from sklearn.metrics import mean_absolute_error
from sklearn.ensemble import RandomForestRegressor
from matplotlib import pyplot
# transform a time series dataset into a supervised learning dataset
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg.values
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test, :], data[-n_test:, :]
# fit an random forest model and make a one step prediction
def random_forest_forecast(train, testX):
# transform list into array
train = asarray(train)
# split into input and output columns
trainX, trainy = train[:, :-1], train[:, -1]
# fit model
model = RandomForestRegressor(n_estimators=1000)
model.fit(trainX, trainy)
# make a one-step prediction
yhat = model.predict([testX])
return yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# split test row into input and output columns
testX, testy = test[i, :-1], test[i, -1]
# fit model on history and make a prediction
yhat = random_forest_forecast(history, testX)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# summarize progress
print('>expected=%.1f, predicted=%.1f' % (testy, yhat))
# estimate prediction error
error = mean_absolute_error(test[:, -1], predictions)
return error, test[:, -1], predictions
# load the dataset
series = read_csv('daily-total-female-births.csv', header=0, index_col=0)
values = series.values
# transform the time series data into supervised learning
data = series_to_supervised(values, n_in=6)
# evaluate
mae, y, yhat = walk_forward_validation(data, 12)
print('MAE: %.3f' % mae)
# plot expected vs predicted
pyplot.plot(y, label='Expected')
pyplot.plot(yhat, label='Predicted')
pyplot.legend()
pyplot.show()
运行该示例会报告测试集中每个步骤的预期值和预测值,然后是所有预测值的 MAE。
注:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,该模型比持久性模型表现得更好,实现了大约 5.9 次出生的 MAE,而不是 6.7 次出生。
你能做得更好吗?
您可以测试不同的随机森林超参数和时间步长数作为输入,看看是否可以获得更好的表现。在下面的评论中分享你的结果。
>expected=42.0, predicted=45.0
>expected=53.0, predicted=43.7
>expected=39.0, predicted=41.4
>expected=40.0, predicted=38.1
>expected=38.0, predicted=42.6
>expected=44.0, predicted=48.7
>expected=34.0, predicted=42.7
>expected=37.0, predicted=37.0
>expected=52.0, predicted=38.4
>expected=48.0, predicted=41.4
>expected=55.0, predicted=43.7
>expected=50.0, predicted=45.3
MAE: 5.905
将数据集最后 12 个月的一系列预期值和预测值进行比较,创建一个折线图。
这给出了模型在测试集上表现如何的几何解释。
使用随机森林预测的预期与出生的线图
一旦选择了最终的随机森林模型配置,就可以最终确定模型,并用于对新数据进行预测。
这称为样本外预测,例如超出训练数据集的预测。这与在模型评估过程中进行预测是一样的,因为我们总是希望使用我们期望在模型用于对新数据进行预测时使用的相同过程来评估模型。
下面的示例演示了在所有可用数据上拟合最终的随机森林模型,并在数据集结束后进行一步预测。
# finalize model and make a prediction for monthly births with random forest
from numpy import asarray
from pandas import read_csv
from pandas import DataFrame
from pandas import concat
from sklearn.ensemble import RandomForestRegressor
# transform a time series dataset into a supervised learning dataset
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg.values
# load the dataset
series = read_csv('daily-total-female-births.csv', header=0, index_col=0)
values = series.values
# transform the time series data into supervised learning
train = series_to_supervised(values, n_in=6)
# split into input and output columns
trainX, trainy = train[:, :-1], train[:, -1]
# fit model
model = RandomForestRegressor(n_estimators=1000)
model.fit(trainX, trainy)
# construct an input for a new prediction
row = values[-6:].flatten()
# make a one-step prediction
yhat = model.predict(asarray([row]))
print('Input: %s, Predicted: %.3f' % (row, yhat[0]))
运行该示例适合所有可用数据的随机森林模型。
使用过去六个月的已知数据准备新的输入行,并预测数据集结束后的下一个月。
Input: [34 37 52 48 55 50], Predicted: 43.053
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
蜜蜂
摘要
在本教程中,您发现了如何开发用于时间序列预测的随机森林模型。
具体来说,您了解到:
- 随机森林是决策树算法的集合,可用于分类和回归预测建模。
- 可以使用滑动窗口表示将时间序列数据集转换为监督学习。
- 如何使用随机森林回归模型拟合、评估和预测时间序列预测。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何重构时间序列预测问题
原文:
machinelearningmastery.com/reframe-time-series-forecasting-problem/
您不必按原样建立时间序列预测问题的模型。
有许多方法可以重新构建您的预测问题,既可以简化预测问题,又可能会暴露更多或不同的信息进行建模。重构最终可以产生更好和/或更稳健的预测。
在本教程中,您将了解如何使用 Python 重新构建时间序列预测问题。
完成本教程后,您将了解:
- 如何将时间序列预测问题重新定义为备用回归问题。
- 如何将时间序列预测问题重新定义为分类预测问题。
- 如何使用其他时间范围重新构建时间序列预测问题。
让我们开始吧。
如何重构您的时间序列预测问题 照片由 Sean MacEntee ,保留一些权利。
重塑问题的好处
重新定义您的问题是探索对预测内容的替代观点。
探索时间序列预测问题的备用框架有两个潜在的好处:
- 简化您的问题。
- 提供集合预测的基础。
这两种好处最终都会导致更加熟练和/或更强大的预测。
1.简化您的问题
也许预测项目中最大的胜利可能来自重构问题。
这是因为预测问题的结构和类型比数据变换的选择,模型的选择或模型超参数的选择具有更大的影响。
它是项目中最大的杠杆,必须仔细考虑。
2.集合预报
除了改变您正在处理的问题之外,重构还起到了另一个作用:它可以为您提供一组可以建模的不同但高度相关的问题。
这样做的好处是框架可能不同,需要在数据准备和建模方法上有所不同。
对同一问题的不同观点的模型可以从输入中捕获不同的信息,并且反过来导致熟练的预测,但是以不同的方式。这些预测可以在整体中组合以产生更熟练或更强大的预测。
在本教程中,我们将探讨您可以考虑重构时间序列预测问题的三种不同方法。
在我们深入研究之前,让我们看一个简单的单变量时间序列问题,即预测每日最低温度作为讨论的背景。
最低每日温度数据集
该数据集描述了澳大利亚墨尔本市 10 年(1981-1990)的最低日常温度。
单位为摄氏度,有 3,650 个观测值。数据来源被称为澳大利亚气象局。
了解有关数据市场上数据集的更多信息。
使用文件名“ daily-minimum-Temperats.sv ”将最低每日温度下载到当前工作目录。
注意:下载的文件包含一些问号(“?”)字符,必须先将其删除才能使用数据集。在文本编辑器中打开文件并删除“?”字符。同时删除文件中的任何页脚信息。
下面的示例将数据集加载为 Pandas 系列。
from pandas import Series
from matplotlib import pyplot
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
print(series.head())
series.plot()
pyplot.show()
运行该示例将打印已加载数据集的前 5 行。
Date Temperature
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
还创建了时间序列的线图。
最低每日温度数据集
朴素的时间序列预测
朴素的方法是按原样预测问题。
作为参考,我们将这称为朴素的时间序列预测。
在这种情况下,可以删除季节性信息以使序列季节性静止。
然后可以基于滞后观察的一些函数来建模时间序列。
例如:
Temp(t+1) = B0 + B1*Temp(t-1) + B2*Temp(t-2) ... Bn*Temp(t-n)
其中 Temp(t + 1) 是预测序列中的下一个温度,B0到Bn是从训练数据和 Temp( t-1) 至 Temp(tn) 是滞后观察。
这可能是很好的甚至是许多问题所要求的。
风险在于,如何构建问题的先入为主的想法影响了数据收集,反过来可能限制了结果。
回归框架
大多数时间序列预测问题是回归问题,需要预测实值输出。
以下是 5 种不同的方法,可以将此预测问题重新表述为替代回归问题:
- 预测与前一天相比最低温度的变化。
- 预测相对于过去 14 天平均值的最低温度。
- 预测相对于去年同月平均值的最低温度。
- 预测最低温度四舍五入到最接近的 5 摄氏度。
- 预测未来 7 天的平均最低温度。
使温度相对是一个线性变换,可能不会使问题更简单,更容易预测,但它可能会动摇新的想法,甚至可能会考虑新的数据来源。
它还可以帮助您更清楚地思考预测的准确率以及预测值的实际要求。
转换预测问题的粒度确实会改变问题的难度,并且如果问题的要求允许这样的重新定义,则非常有用。
下面是重新设定最低每日温度预测问题的示例,以预测每日温度四舍五入到最接近的 5 度。
from pandas import Series
from pandas import DataFrame
from pandas import concat
from math import floor
# load data
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# Create lagged dataset
values = DataFrame(series.values)
dataframe = concat([values.shift(1), values], axis=1)
dataframe.columns = ['t-1', 't+1']
# round forecast to nearest 5
for i in range(len(dataframe['t+1'])):
dataframe['t+1'][i] = int(dataframe['t+1'][i] / 5) * 5.0
print(dataframe.head(5))
运行该示例将打印重构问题的前 5 行。
该问题定义为前一天的最低温度,以摄氏度为单位,最小值为最接近的 5 度。
t-1 t+1
0 NaN 20.0
1 20.7 15.0
2 17.9 15.0
3 18.8 10.0
4 14.6 15.0
分类框架
分类涉及预测分类或标签输出(如“热”和“冷”)。
以下是将此预测问题重新定义为分类问题的 5 种不同方式:
- 预测最低温度是冷,中温还是暖。
- 预测最低温度的变化是小还是大。
- 预测最低温度是否为每月最低温度。
- 预测最低值是高于还是低于上一年的最低值。
- 预测未来 7 天的最低温度是上升还是下降。
转向分类可以简化预测问题。
这种方法打开了标签和二进制分类框架的想法。
输出变量的原生回归表示意味着大多数分类框架可能保持序数结构(例如冷,中,热)。意味着正在预测的类之间存在有序关系,这在预测“狗”和“猫”等标签时可能不是这种情况。
序数关系允许硬分类问题以及可以事后舍入到特定类别的整数预测问题。
下面是将最低每日温度预测问题转换为分类问题的示例,其中每个温度值是冷,中或热的序数值。这些标签映射到整数值,定义如下:
- 0(冷):< 10 摄氏度。
- 1(中等):> = 10 且< 25 摄氏度。
- 2(热):> = 25 摄氏度。
from pandas import Series
from pandas import DataFrame
from pandas import concat
from math import floor
# load data
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# Create lagged dataset
values = DataFrame(series.values)
dataframe = concat([values.shift(1), values], axis=1)
dataframe.columns = ['t-1', 't+1']
# round forecast to nearest 5
for i in range(len(dataframe['t+1'])):
value = dataframe['t+1'][i]
if value < 10.0:
dataframe['t+1'][i] = 0
elif value >= 25.0:
dataframe['t+1'][i] = 2
else:
dataframe['t+1'][i] = 1
print(dataframe.head(5))
运行该示例将打印重构问题的前 5 行。
给定前一天的最低温度(摄氏度),目标是将温度预测为冷,中或热(分别为 0,1,2)。
t-1 t+1
0 NaN 1.0
1 20.7 1.0
2 17.9 1.0
3 18.8 1.0
4 14.6 1.0
时间地平线框架
可以改变的另一个轴是时间范围。
时间范围是未来预测的时间步数。
以下是 5 种不同的方法,可以将此预测问题重新表述为不同的时间范围:
- 预测未来 7 天的最低温度。
- 预测 30 天内的最低温度。
- 预测下个月的平均最低温度。
- 预测下一周将具有最低最低温度的日期。
- 预测一年的最低温度值。
您很容易理解需要一步预测的想法。
专注于围绕时间范围重新解决问题迫使您思考点与多步预测以及未来需要考虑的距离。
您可能能够对未来做出预测,但技能可能会有所不同,进一步降低到您预测的未来。在思考预测的视野时,还要考虑预测的最低可接受表现。
下面的示例转换最低每日温度预测问题,以预测接下来 7 天的最低温度。
from pandas import Series
from pandas import DataFrame
from pandas import concat
from math import floor
# load data
series = Series.from_csv('daily-minimum-temperatures.csv', header=0)
# Create lagged dataset
values = DataFrame(series.values)
dataframe = concat([values.shift(1), values, values.shift(-1),
values.shift(-2), values.shift(-3), values.shift(-4), values.shift(-5),
values.shift(-6)], axis=1)
dataframe.columns = ['t-1', 't+1', 't+2', 't+3', 't+4', 't+5', 't+6', 't+7']
print(dataframe.head(14))
运行该示例将打印转换后的数据集的前 14 条记录。
问题定义为:给定前一天的最低日摄入温度,以摄氏度为单位,预测接下来 7 天的最低日常温度。
t-1 t+1 t+2 t+3 t+4 t+5 t+6 t+7
0 NaN 20.7 17.9 18.8 14.6 15.8 15.8 15.8
1 20.7 17.9 18.8 14.6 15.8 15.8 15.8 17.4
2 17.9 18.8 14.6 15.8 15.8 15.8 17.4 21.8
3 18.8 14.6 15.8 15.8 15.8 17.4 21.8 20.0
4 14.6 15.8 15.8 15.8 17.4 21.8 20.0 16.2
5 15.8 15.8 15.8 17.4 21.8 20.0 16.2 13.3
6 15.8 15.8 17.4 21.8 20.0 16.2 13.3 16.7
7 15.8 17.4 21.8 20.0 16.2 13.3 16.7 21.5
8 17.4 21.8 20.0 16.2 13.3 16.7 21.5 25.0
9 21.8 20.0 16.2 13.3 16.7 21.5 25.0 20.7
10 20.0 16.2 13.3 16.7 21.5 25.0 20.7 20.6
11 16.2 13.3 16.7 21.5 25.0 20.7 20.6 24.8
12 13.3 16.7 21.5 25.0 20.7 20.6 24.8 17.7
13 16.7 21.5 25.0 20.7 20.6 24.8 17.7 15.5
摘要
在本教程中,您了解了如何使用 Python 重新构建时间序列预测问题。
具体来说,你学到了:
- 如何设计时间序列问题的替代回归表示。
- 如何将预测问题构建为分类问题。
- 如何为预测问题设计备用时间范围。
您知道其他方法来重构您的时间序列预测问题吗? 在下面的评论中分享?
你有任何问题吗? 在下面的评论中询问他们,我会尽力回答。
如何使用 Python 重采样和插值您的时间序列数据
原文:
machinelearningmastery.com/resample-interpolate-time-series-data-python/
您可能会以错误的频率观察。
也许它们太精细或不够精细。 Python 中的 Pandas 库提供了更改时间序列数据频率的功能。
在本教程中,您将了解如何在 Python 中使用 Pandas 来增加和减少时间序列数据的采样频率。
完成本教程后,您将了解:
- 关于时间序列重采样,两种类型的重采样,以及您需要使用它们的两个主要原因。
- 如何使用 Pandas 将时间序列数据上采样到更高的频率并插入新的观测值。
- 如何使用 Pandas 将时间序列数据下采样到较低频率并总结较高频率的观测值。
让我们开始吧。
2016 年 12 月更新:修正了上采样和下采样的定义。
如何使用 Python 重新取样和插值您的时间序列数据 照片来自 sung ming whang ,保留一些权利。
重采样
重采样涉及更改时间序列观察的频率。
两种类型的重采样是:
- 上采样:增加样本频率的位置,例如从几分钟到几秒。
- 下采样:降低样本频率的地方,例如从几天到几个月。
在这两种情况下,都必须发明数据。
在上采样的情况下,可能需要小心确定如何使用插值计算细粒度观测值。在下采样的情况下,在选择用于计算新聚合值的摘要统计时可能需要小心。
您可能有兴趣重采样时间序列数据的原因可能有两个:
- 问题成帧:如果您的数据与您想要做出预测的频率相同,则可能需要重采样。
- 特征工程:重新取样还可用于为监督学习模型提供额外的结构或洞察学习问题。
这两种情况之间存在很多重叠。
例如,您可能拥有每日数据,并希望预测每月问题。您可以直接使用每日数据,也可以将其下采样到月度数据并开发模型。
特征工程视角可以在开发模型时使用来自时间尺度和更多时间尺度的观察的观察和总结。
让我们通过查看真实数据集和一些示例,使重新取样更具体。
洗发水销售数据集
该数据集描述了 3 年期间每月洗发水的销售数量。
单位是销售计数,有 36 个观察。原始数据集归功于 Makridakis,Wheelwright 和 Hyndman(1998)。
下面是前 5 行数据的示例,包括标题行。
"Month","Sales"
"1-01",266.0
"1-02",145.9
"1-03",183.1
"1-04",119.3
"1-05",180.3
下面是从数据市场获取的整个数据集的图表。
洗发水销售数据集
数据集显示趋势增加,可能还有一些季节性组件。
加载 Shampoo Sales Dataset
下载数据集并将其放在当前工作目录中,文件名为“ shampoo-sales.csv ”。
数据集中的时间戳没有绝对年份,但确实有一个月。我们可以编写一个自定义日期解析函数来加载这个数据集,并选择一个任意年份,例如 1900 年,以确定年份的基线。
下面是使用read_csv()中的自定义日期解析功能加载 Shampoo Sales 数据集的代码片段。
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)
print(series.head())
series.plot()
pyplot.show()
运行此示例将加载数据集并打印前 5 行。这显示了日期的正确处理,从 1900 年开始。
Month
1901-01-01 266.0
1901-02-01 145.9
1901-03-01 183.1
1901-04-01 119.3
1901-05-01 180.3
Name: Sales of shampoo over a three year period, dtype: float64
我们还得到了一个数据集图,显示了每月销售额的上升趋势。
洗发水销售数据集的情节
Upsample 洗发水销售
洗发水销售中的观察结果是每月一次。
想象一下,我们想要每日销售信息。我们必须将频率从月度上升到每日,并使用插值方案填写新的每日频率。
Pandas 库在 _ 系列 _ 和DataFrame对象上提供了一个名为resample()的函数。这可用于在下采样时对记录进行分组,并在进行上采样时为新观察创建空间。
我们可以使用此功能通过调用重采样并指定日历日频率或“D”的首选频率,将每月数据集转换为每日数据集。
Pandas 很聪明,您可以轻松地将频率指定为“1D”甚至是特定于域的内容,例如“5D”。请参阅本教程末尾的更多阅读部分,以获取可以使用的别名列表。
from pandas import read_csv
from pandas import datetime
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)
upsampled = series.resample('D')
print(upsampled.head(32))
运行此示例将打印上采样数据集的前 32 行,显示 1 月的每一天和 2 月的第一天。
Month
1901-01-01 266.0
1901-01-02 NaN
1901-01-03 NaN
1901-01-04 NaN
1901-01-05 NaN
1901-01-06 NaN
1901-01-07 NaN
1901-01-08 NaN
1901-01-09 NaN
1901-01-10 NaN
1901-01-11 NaN
1901-01-12 NaN
1901-01-13 NaN
1901-01-14 NaN
1901-01-15 NaN
1901-01-16 NaN
1901-01-17 NaN
1901-01-18 NaN
1901-01-19 NaN
1901-01-20 NaN
1901-01-21 NaN
1901-01-22 NaN
1901-01-23 NaN
1901-01-24 NaN
1901-01-25 NaN
1901-01-26 NaN
1901-01-27 NaN
1901-01-28 NaN
1901-01-29 NaN
1901-01-30 NaN
1901-01-31 NaN
1901-02-01 145.9
我们可以看到resample()函数通过将 NaN 值放入新值来创建行。我们可以看到我们仍然从原始数据的 1 月和 2 月的第一个销售量。
接下来,我们可以在这个新频率上插入缺失值。
_ 系列 _ Pandas 对象提供 _ 插值()_ 函数来插值缺失值,并且有一个很好的选择简单和更复杂的插值函数。您可能具有领域知识,可帮助选择如何插值。
一个好的起点是使用线性插值。这会在可用数据之间绘制一条直线,在本例中是在该月的第一天,并从该行填充所选频率的值。
from pandas import read_csv
from pandas import datetime
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)
upsampled = series.resample('D')
interpolated = upsampled.interpolate(method='linear')
print(interpolated.head(32))
运行此示例,我们可以看到插值。
Month
1901-01-01 266.000000
1901-01-02 262.125806
1901-01-03 258.251613
1901-01-04 254.377419
1901-01-05 250.503226
1901-01-06 246.629032
1901-01-07 242.754839
1901-01-08 238.880645
1901-01-09 235.006452
1901-01-10 231.132258
1901-01-11 227.258065
1901-01-12 223.383871
1901-01-13 219.509677
1901-01-14 215.635484
1901-01-15 211.761290
1901-01-16 207.887097
1901-01-17 204.012903
1901-01-18 200.138710
1901-01-19 196.264516
1901-01-20 192.390323
1901-01-21 188.516129
1901-01-22 184.641935
1901-01-23 180.767742
1901-01-24 176.893548
1901-01-25 173.019355
1901-01-26 169.145161
1901-01-27 165.270968
1901-01-28 161.396774
1901-01-29 157.522581
1901-01-30 153.648387
1901-01-31 149.774194
1901-02-01 145.900000
查看线图,我们看到绘制原始数据没有区别,因为绘图已经插入点之间的值以绘制线。
洗发水销售插值线性
另一种常见的插值方法是使用多项式或样条曲线来连接这些值。
这会创建更多曲线,并且在许多数据集上看起来更自然。使用样条插值需要指定顺序(多项式中的项数);在这种情况下,2 的订单就好了。
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)
upsampled = series.resample('D')
interpolated = upsampled.interpolate(method='spline', order=2)
print(interpolated.head(32))
interpolated.plot()
pyplot.show()
运行该示例,我们可以首先查看原始插值。
Month
1901-01-01 266.000000
1901-01-02 258.630160
1901-01-03 251.560886
1901-01-04 244.720748
1901-01-05 238.109746
1901-01-06 231.727880
1901-01-07 225.575149
1901-01-08 219.651553
1901-01-09 213.957094
1901-01-10 208.491770
1901-01-11 203.255582
1901-01-12 198.248529
1901-01-13 193.470612
1901-01-14 188.921831
1901-01-15 184.602185
1901-01-16 180.511676
1901-01-17 176.650301
1901-01-18 173.018063
1901-01-19 169.614960
1901-01-20 166.440993
1901-01-21 163.496161
1901-01-22 160.780465
1901-01-23 158.293905
1901-01-24 156.036481
1901-01-25 154.008192
1901-01-26 152.209039
1901-01-27 150.639021
1901-01-28 149.298139
1901-01-29 148.186393
1901-01-30 147.303783
1901-01-31 146.650308
1901-02-01 145.900000
回顾线图,我们可以在插值上看到更自然的曲线。
洗发水销售插值样条
通常,当您缺少观察值时,插值是一种有用的工具。
接下来,我们将考虑在另一个方向上重采样并降低观测频率。
降低洗发水销售量
销售数据是按月计算的,但也许我们希望数据是季度的。
这一年可分为 4 个营业季,3 个月一块。
Pandas 中的resample()函数不是在现有观测值之间创建新行,而是按新频率对所有观测值进行分组。
我们可以使用像“3M”这样的别名创建 3 个月的组,但如果我们的观察结果没有在 1 月,4 月,7 月或 10 月开始,则可能会遇到麻烦。熊猫确实有一个四分之一的“Q”别名,我们可以用它来达到这个目的。
我们现在必须决定如何从每组 3 条记录中创建新的季度值。一个很好的起点是计算本季度的平均月销售数字。为此,我们可以使用mean()函数。
综上所述,我们得到以下代码示例。
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)
resample = series.resample('Q')
quarterly_mean_sales = resample.mean()
print(quarterly_mean_sales.head())
quarterly_mean_sales.plot()
pyplot.show()
运行该示例将打印季度数据的前 5 行。
Month
1901-03-31 198.333333
1901-06-30 156.033333
1901-09-30 216.366667
1901-12-31 215.100000
1902-03-31 184.633333
Freq: Q-DEC, Name: Sales, dtype: float64
我们还绘制了季度数据,显示了 3 年原始观测中的 Q1-Q4。
洗发水销售季度下降
也许我们希望进一步将月度数据转化为年度数据,也许稍后可以使用它来模拟下一年的数据。
我们可以使用年末频率的别名“A”对数据进行下采样,这次使用总和来计算每年的总销售额。
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)
resample = series.resample('A')
quarterly_mean_sales = resample.sum()
print(quarterly_mean_sales.head())
quarterly_mean_sales.plot()
pyplot.show()
运行该示例显示了 3 年观察的 3 条记录。
我们还得到一个图,正确显示沿 x 轴的年份和沿 y 轴的每年销售总数。
洗发水销售额下降年度总和
进一步阅读
本节提供本教程中使用的 Pandas 函数的链接和进一步阅读。
- pandas.Series.resample API 文档了解有关如何配置 resample()函数的更多信息。
- Pandas 时间序列重采样示例,用于更一般的代码示例。
- Pandas Offset 在重采样时使用的所有内置方法用于更改数据粒度的别名。
- pandas.Series.interpolate API 文档了解有关如何配置 interpolate()函数的更多信息。
摘要
在本教程中,您了解了如何使用 Python 中的 Pandas 重采样时间序列数据。
具体来说,你学到了:
- 关于时间序列重采样以及下采样和上采样观察频率之间的差异和原因。
- 如何使用 Pandas 对时间序列数据进行上采样以及如何使用不同的插值方案。
- 如何使用 Pandas 对时间序列数据进行下采样以及如何汇总分组数据。
您对重采样或插值时间序列数据或本教程有任何疑问吗? 在评论中提出您的问题,我会尽力回答。