导读:

在组装训练数据的时候,我们经常要用过去的数据来预测当前的值,但过去数据向后去多少位,就是一个取数据窗口大小的问题了。

随着数据序列向后偏移,我们取的历史数据也要随之向后移动,这种移动的取数据方法,就叫做数据滚动窗口。

文中给出了两种取历史数据方法:

1、使用rolling函数自定义长度,

2、或者使用expanding方法,对所有先前值进行取值计算

正文:

在我们开始使用机器学习算法之前,时间序列数据必须重新构建为监督学习数据集。

时间序列中没有输入和输出功能的概念。相反,我们必须选择要预测的变量,并使用特征工程来构建将用于对未来时间步骤进行预测的所有输入。

在本教程中,您将了解如何使用Python对时间序列数据执行特征工程,以使用机器学习算法对时间序列问题进行建模。

特征工程的目标

特征工程的目标是在新输入特征和输出特征之间提供强大且理想的简单关系,以便监督学习算法进行建模。

实际上,我们正在移动复杂性。

输入和输出数据之间的关系存在复杂性。在时间序列的情况下,没有输入和输出变量的概念; 我们也必须发明这些并从头开始构建有监督的学习问题。

我们可以依靠复杂模型的能力来破译问题的复杂性。如果我们能够更好地揭示数据中输入和输出之间的内在关系,我们可以更容易地使这些模型的工作(甚至使用更简单的模型)。

困难在于我们不知道我们试图揭示的输入和输出之间潜在的固有功能关系。如果我们知道,我们可能不需要机器学习。

相反,我们唯一的反馈是在监督学习数据集上开发的模型的性能或我们创建的问题的“视图”。实际上,最好的默认策略是使用所有可用知识从时间序列数据集中创建许多优秀数据集,并使用模型性能(和其他项目要求)来帮助确定问题的优秀特性和良好视图。

为清楚起见,我们将重点关注示例中的单变量(一个变量)时间序列数据集,但这些方法同样适用于多变量时间序列问题。接下来,让我们看一下我们将在本教程中使用的数据集。

最低每日温度数据集

在这篇文章中,我们将使用最低每日温度数据集。

该数据集描述了澳大利亚墨尔本10年(1981-1990)的最低日常温度。

单位为摄氏度,有3,650个观测值。数据来源被称为澳大利亚气象局。

下面是前5行数据的示例,包括标题行。

 

1

2

3

4

5

6

"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

下面是从数据市场获取的整个数据集的图表。

python求滚动相关系数 python滚动回归_数据集

                                           最低每日温度

数据集显示了增长的趋势,可能还有一些季节性成分。

在此处下载并了解有关数据集的更多信息。

注意:下载的文件包含一些问号(“?”)字符,在使用数据集之前必须删除这些字符。在文本编辑器中打开文件并删除“?”字符。同时删除文件中的任何页脚信息。

滞后特征

滞后特征是时间序列预测问题转化为监督学习问题的经典方式。

最简单的方法是在给定前一时间(t-1)的值的情况下预测下一次(t + 1)的值。具有移位值的监督学习问题如下所示:

Value(t-1), Value(t+1)
Value(t-1), Value(t+1)
Value(t-1), Value(t+1)

Pandas库提供shift()函数,以帮助从时间序列数据集创建这些移位或滞后特征。将数据集移动1会创建t-1列,为第一行添加NaN(未知)值。没有移位的时间序列数据集表示t + 1。

让我们以一个例子来具体化。温度数据集的前3个值分别为20.7,17.9和18.8。因此,前3个观测值的移位和未移位温度列表如下:

Shifted, Original
NaN, 20.7
20.7, 17.9
17.9, 18.8

我们可以使用沿列轴(轴= 1)的concat()函数将移位列连接到一个新的DataFrame中。

综合这些,下面是为我们的日常温度数据集创建滞后特征的示例。从加载的序列中提取值,并创建这些值的移位和未移位列表。为清晰起见,每个列也在DataFrame中命名。

from pandas import Series
from pandas import DataFrame
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
temps = DataFrame(series.values)
dataframe = concat([temps.shift(1), temps], axis=1)
dataframe.columns = ['t-1', 't+1']
print(dataframe.head(5))

运行该示例将打印具有滞后功能的新数据集的前5行。

t-1 t+1
0 NaN 20.7
1 20.7 17.9
2 17.9 18.8
3 18.8 14.6
4 14.6 15.8

您可以看到我们必须丢弃第一行才能使用数据集来训练监督学习模型,因为它没有足够的数据可供使用。

滞后特征的添加被称为滑动窗口方法,在这种情况下窗口宽度为1.就好像我们在每个观察的时间序列中滑动焦点,只关注窗口宽度内的内容。

我们可以扩展窗口宽度并包含更多滞后功能。例如,下面的上述情况被修改为包括最后3个观察值以预测下一个时间步的值。

from pandas import Series
from pandas import DataFrame
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
temps = DataFrame(series.values)
dataframe = concat([temps.shift(3), temps.shift(2), temps.shift(1), temps], axis=1)
dataframe.columns = ['t-3', 't-2', 't-1', 't+1']
print(dataframe.head(5))

运行此示例将打印新滞后数据集的前5行。

t-3 t-2 t-1 t+1
0 NaN NaN NaN 20.7
1 NaN NaN 20.7 17.9
2 NaN 20.7 17.9 18.8
3 20.7 17.9 18.8 14.6
4 17.9 18.8 14.6 15.8

同样,您可以看到我们必须丢弃没有足够数据训练监督模型的前几行。

滑动窗口方法的一个难点是为您的问题制作窗口的大小。

也许一个很好的起点是执行灵敏度分析并尝试一组不同的窗口宽度,从而创建一组不同的数据集“视图”,并查看哪些结果表现更好的模型。会有一个收益递减点。

另外,为什么要停止使用线性窗口?也许您需要上周,上个月和去年的滞后值。同样,这归结于特定领域。

在温度数据集的情况下,来自前一年或前几年的同一天的滞后值可能是有用的。

我们可以使用窗口做更多事情而不是包含原始值。在下一节中,我们将介绍包含在窗口中汇总统计信息的功能。

滚动窗口统计

添加原始滞后值之外的步骤是在先前时间步骤中添加值的摘要。

我们可以计算滑动窗口中值的汇总统计数据,并将它们作为我们数据集中的要素包含在内。也许最有用的是前几个值的平均值,也称为滚动均值。

例如,我们可以计算前两个值的平均值,并使用它来预测下一个值。对于温度数据,我们必须等待3个时间步,然后才能使用2个值来取平均值,然后才能使用该值来预测第3个值。

例如:

mean(t-2, t-1), t+1
mean(20.7, 17.9), 18.8
19.3, 18.8

Pandas提供了一个rolling()函数,它在每个时间步都创建一个带有值窗口的新数据结构。然后,我们可以在为每个时间步骤收集的值窗口上执行统计函数,例如计算平均值。

首先,必须改变系列。然后可以创建滚动数据集,并在每个窗口上计算两个值的平均值。

以下是前三个滚动窗口中的值:

#, Window Values
1, NaN
2, NaN, 20.7
3, 20.7, 17.9

这表明我们在第3行之前不会有可用的数据。

最后,与上一节一样,我们可以使用concat()函数构建一个只包含新列的新数据集。

下面的示例演示了如何使用窗口大小为2的Pandas执行此操作。

from pandas import Series
from pandas import DataFrame
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
temps = DataFrame(series.values)
shifted = temps.shift(1)
window = shifted.rolling(window=2)
means = window.mean()
dataframe = concat([means, temps], axis=1)
dataframe.columns = ['mean(t-2,t-1)', 't+1']
print(dataframe.head(5))

运行该示例将打印新数据集的前5行。我们可以看到前两行没用。

  • 第一个NaN是由系列的转变创造的。
  • 第二个因为NaN不能用于计算平均值。
  • 最后,第三行显示用于预测18.8系列中第3个值的19.30(平均值20.7和17.9)的预期值。

mean(t-2,t-1) t+1
0 NaN 20.7
1 NaN 17.9
2 19.30 18.8
3 18.35 14.6
4 16.70 15.8

我们可以计算出更多的统计数据,甚至可以用不同的数学方法来计算“窗口”的定义。

下面是另一个示例,显示窗口宽度为3,数据集包含更多摘要统计信息,特别是窗口中的最小值,平均值和最大值。

您可以在代码中看到我们明确指定滑动窗口宽度为命名变量。这使我们可以在计算系列的正确移位和将窗口宽度指定为rolling()函数时使用它。

在这种情况下,窗口宽度为3表示我们必须将系列向前移动2个时间步长。这使得前两行NaN。接下来,我们需要计算窗口统计信息,每个窗口有3个值。在我们甚至从窗口中的系列中获得足够的数据以开始计算统计数据之前,它需要3行。前5个窗口中的值如下:

#, Window Values
1, NaN
2, NaN, NaN
3, NaN, NaN, 20.7
4, NaN, 20.7, 17.9
5, 20.7, 17.9, 18.8

这表明我们不会期望至少在第5行(数组索引4)之前可用的数据

from pandas import Series
from pandas import DataFrame
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
temps = DataFrame(series.values)
width = 2
shifted = temps.shift(width - 1)
print(shifted.head(12))
# 向上统计的步长
window = shifted.rolling(window=4)
# 分别取过去四天的最小值,均值,最大值
dataframe = concat([window.min(), window.mean(), window.max(), temps], axis=1)
dataframe.columns = ['min', 'mean', 'max', 't+1']
print(dataframe.head(15))

运行代码将打印新数据集的前5行。

我们可以检查第5行(数组索引4)上值的正确性。我们可以看到确实17.9是最小值,20.7是[20.7,17.9,18.8]窗口中值的最大值。

min mean max t+1
0 NaN NaN NaN 20.7
1 NaN NaN NaN 17.9
2 NaN NaN NaN 18.8
3 NaN NaN NaN 14.6
4 17.9 19.133333 20.7 15.8

扩展窗口统计

另一种可能有用的窗口包括该系列中的所有先前数据。

这称为扩展窗口,可以帮助跟踪可观察数据的边界。与DataFrame上的rolling()函数一样,Pandas提供了一个expanded ()函数,该函数收集每个时间步的所有先前值的集合。

可以汇总这些先前数字列表并将其作为新功能包括在内。例如,下面是该系列的前5个步骤的展开窗口中的数字列表:

#, Window Values
1, 20.7
2, 20.7, 17.9,
3, 20.7, 17.9, 18.8
4, 20.7, 17.9, 18.8, 14.6
5, 20.7, 17.9, 18.8, 14.6, 15.8

同样,您可以看到我们必须转换系列一次性步骤,以确保我们希望预测的输出值从这些窗口值中排除。因此输入窗口如下所示:

#, Window Values
1, NaN
2, NaN, 20.7
3, NaN, 20.7, 17.9,
4, NaN, 20.7, 17.9, 18.8
5, NaN, 20.7, 17.9, 18.8, 14.6

值得庆幸的是,统计计算不包括扩展窗口中的NaN值,这意味着不需要进一步修改。

下面是计算每日温度数据集上展开窗口的最小值,平均值和最大值的示例。

# create expanding window features
from pandas import Series
from pandas import DataFrame
from pandas import concat
series = Series.from_csv('daily-minimum-temperatures-in-me.csv', header=0)
print(series.head(15))
temps = DataFrame(series.values)
# 使用expanding方法,对先前所有值进行统计
window = temps.expanding()
dataframe = concat([window.min(), window.mean(), window.max(), temps.shift(0)], axis=1)
dataframe.columns = ['min', 'mean', 'max', 't+1']
print(dataframe.head(15))

运行该示例将打印数据集的前5行。

检查扩展的最小值,平均值和最大值的点显示具有预期效果的示例。

    min       mean   max   t+1
0  20.7  20.700000  20.7  17.9
1  17.9  19.300000  20.7  18.8
2  17.9  19.133333  20.7  14.6
3  14.6  18.000000  20.7  15.8
4  14.6  17.560000  20.7  15.8