滚动/时间序列预测
使用 tsfresh 提取的特征可以用于许多不同的任务,例如时间序列分类、压缩或预测。本节解释了如何使用这些特征进行时间序列预测。
假设你有一个特定股票的价格,例如苹果,有100个时间步的数据。现在,你想构建一个基于特征的模型来预测苹果股票的未来价格。你可以去掉最后一个价格值(今天的),并从今天的时间序列中提取特征来预测今天的价格。但这只会给你一个训练的例子。相反,你可以重复这个过程:对于你的股票价格时间序列中的每一天,去掉当前值,提取直到该值的特征并训练以预测该天的值(你去掉的)。你可以把它想象成在一个排序的时间序列数据上移动一个裁剪窗口:在每个移动步骤中,你提取通过裁剪窗口看到的数据来构建一个新的、更小的时间序列,并只在这个时间序列上提取特征。然后你继续移动。在 tsfresh 中,将裁剪窗口移动到你的数据上以创建更小的时间序列裁剪的过程称为 rolling。
滚动是将单个时间序列转换为多个时间序列的一种方法,每个时间序列比前一个时间序列晚一个(或n个)时间步长。tsfresh 中实现的滚动工具可以帮助您将数据重塑(并滚动)为可以应用常规 tsfresh.extract_features() 方法的格式。这意味着提取时间序列窗口和特征提取的步骤是分开的。
请注意,这里的“时间”不一定指时钟时间。在支持的 数据格式 中,DataFrame 的“排序”列给每个测量结果赋予了一个顺序状态。在时间序列的情况下,这可以是*时间*维度,而在其他情况下,这可以是位置、频率等。
下图展示了该过程:
另一个例子可以在流数据中找到,例如,在工业4.0应用中。在这里,你通常一次得到一行新数据,并使用它来预测机器故障。为了训练你的模型,你可以通过在第一个时间步之后、前两个时间步之后等,向分类器提供数据,来模拟流数据。
在 tsfresh 中,滚动是通过辅助函数 tsfresh.utilities.dataframe_functions.roll_time_series() 实现的。此外,我们提供了 tsfresh.utilities.dataframe_functions.make_forecasting_frame() 方法,作为一个方便的包装器,可以快速为给定的序列构建容器和目标向量。
让我们通过一个示例来看看它是如何工作的:
滚动机制
我们研究以下扁平的 DataFrame 示例,这是一个适合 tsfresh 的格式(参见 数据格式)。注意,滚动操作也适用于所有其他时间序列格式。
id |
时间 |
x |
y |
|---|---|---|---|
1 |
1 |
1 |
5 |
1 |
2 |
2 |
6 |
1 |
3 |
3 |
7 |
1 |
4 |
4 |
8 |
2 |
8 |
10 |
12 |
2 |
9 |
11 |
13 |
在上面的扁平DataFrame中,我们测量了两个传感器x和y在四个或两个时间步长(1, 2, 3, 4, 8, 9)中对两个不同实体(id 1和2)的值。
如果你想跟随学习,这里是生成这些数据的Python代码:
import pandas as pd
df = pd.DataFrame({
"id": [1, 1, 1, 1, 2, 2],
"time": [1, 2, 3, 4, 8, 9],
"x": [1, 2, 3, 4, 10, 11],
"y": [5, 6, 7, 8, 12, 13],
})
现在,我们可以使用 tsfresh.utilities.dataframe_functions.roll_time_series() 来获取连续的子时间序列。你可以想象有一个窗口在你的时间序列数据上滑动,并提取出通过这个窗口可以看到的每一个数据。窗口有三个参数可以调整:
max_timeshift 定义了窗口的最大尺寸。提取的时间序列的最大长度为 max_timeshift + 1。(它们也可能更小,因为开始时间戳的过去值较少)。
min_timeshift 定义了每个窗口的最小尺寸。较短的时间序列(通常在开始时)将被省略。
高级设置:rolling_direction:如果你想在正向(递增排序)或负向(递减排序)方向滑动。你几乎不需要负向方向,所以你可能不想改变默认设置。该参数的绝对值决定了每次切割步骤你想移动多少。
列参数与通常的 数据格式 相同。
让我们看看我们的数据样本会发生什么:
from tsfresh.utilities.dataframe_functions import roll_time_series
df_rolled = roll_time_series(df, column_id="id", column_sort="time")
新的数据集仅由旧数据集的值组成,但具有新的ID。同时,排序列的值(在此例中为``time``)也被复制。如果你按``id``分组,你将得到以下部分(或“窗口”):
id |
时间 |
x |
y |
|---|---|---|---|
(1,1) |
1 |
1 |
5 |
id |
时间 |
x |
y |
|---|---|---|---|
(1,2) |
1 |
1 |
5 |
(1,2) |
2 |
2 |
6 |
id |
时间 |
x |
y |
|---|---|---|---|
(1,3) |
1 |
1 |
5 |
(1,3) |
2 |
2 |
6 |
(1,3) |
3 |
3 |
7 |
id |
时间 |
x |
y |
|---|---|---|---|
(1,4) |
1 |
1 |
5 |
(1,4) |
2 |
2 |
6 |
(1,4) |
3 |
3 |
7 |
(1,4) |
4 |
4 |
8 |
id |
时间 |
x |
y |
|---|---|---|---|
(2,8) |
8 |
10 |
12 |
id |
时间 |
x |
y |
|---|---|---|---|
(2,9) |
8 |
10 |
12 |
(2,9) |
9 |
11 |
13 |
现在,您可以在滚动数据上运行通常的特征提取过程:
from tsfresh import extract_features
df_features = extract_features(df_rolled, column_id="id", column_sort="time")
你将为上述每个部分生成特征,然后可以使用这些特征来训练你的预测模型。
变量 |
x__abs_energy |
x__absolute_sum_of_changes |
… |
|---|---|---|---|
id |
… |
||
(1,1) |
1.0 |
0.0 |
… |
(1,2) |
5.0 |
1.0 |
… |
(1,3) |
14.0 |
2.0 |
… |
(1,4) |
30.0 |
3.0 |
… |
(2,8) |
100.0 |
0.0 |
… |
(2,9) |
221.0 |
1.0 |
… |
例如,对于 id (1,3) 的特征是使用 id=1 的数据提取的,直到并包括 t=3``(即 ``t=1、t=2 和 t=3)。
如果你想为一个预测任务训练模型,tsfresh 还提供了函数 tsfresh.utilities.dataframe_functions.make_forecasting_frame(),它将帮助你正确匹配目标向量。这个过程在下图中进行了可视化。它展示了如何使用紫色的滚动子时间序列作为特征矩阵 X 构建的基础(如果 f 是 extract_features 函数)。绿色的数据点需要由模型预测,并作为目标向量 y 中的行使用。请注意,这仅适用于单个 id 和 kind 的一维时间序列。
参数和实现说明
上面的示例展示了整体滚动机制,该机制创建了新的时间序列。现在,我们讨论新时间序列的命名约定。
为了识别每一个子序列,tsfresh 使用将被预测的点的时戳与旧的标识符一起作为“id”。对于正向滚动,这个 timeshift 是子序列中的最后一个时戳。对于负向滚动,它是第一个,例如,上述数据框在负方向上滚动会给我们:
id |
时间 |
x |
y |
|---|---|---|---|
(1,1) |
1 |
1 |
5 |
(1,1) |
2 |
2 |
6 |
(1,1) |
3 |
3 |
7 |
(1,1) |
4 |
4 |
8 |
(1,2) |
2 |
2 |
6 |
(1,2) |
3 |
3 |
7 |
(1,2) |
4 |
4 |
8 |
(1,3) |
3 |
3 |
7 |
(1,3) |
4 |
4 |
8 |
(1,4) |
4 |
4 |
8 |
(2,8) |
8 |
10 |
12 |
(2,8) |
9 |
11 |
13 |
(2,9) |
9 |
11 |
13 |
你可以使用它来预测当前值,使用未来的时间序列值(如果这在你的情况下有意义)。
选择非默认的 max_timeshift 或 min_timeshift 会使提取的子时间序列变小,甚至完全移除它们(例如,使用 min_timeshift = 1 时,正向滚动情况下的 (1,1)``(即 ``id=1,timeshift=1)将会消失)。使用绝对值较大的 ``rolling_direction``(例如 -2 或 2)将跳过一些窗口(在这种情况下,每两个跳过一个)。