【问题标题】:Feature engineering for timeseries dataset in Python [closed]Python中时间序列数据集的特征工程[关闭]
【发布时间】:2017-09-11 17:42:01
【问题描述】:

我有一个包含n 观测值的数据集,其中所有观测值都有m 时间步长。我还有一个 n*m 数组,其中包含每个给定观察值的每个时间步长的标签。

我正在对该数据集进行特征工程,以根据我拥有的标签在数据中找到有意义的特征。是否有任何 Python 包可以促进这个过程?

我遇到了tsfresh (https://github.com/blue-yonder/tsfresh),尽管它似乎只打算在我们有一个标签来分类每个观察而不是一个标签来分类每个时间步时使用,就像我的情况一样。

【问题讨论】:

  • 大家好,我是tsfresh的作者。你能更详细地澄清你的数据吗? (可能带有屏幕截图或简短示例),然后我可以告诉您 tsfresh 是否适合您的案例。

标签: python feature-extraction


【解决方案1】:

你可以试试Featuretools。它是一个开源自动化特征工程库,明确处理时间以确保您不会引入标签泄漏。

对于您的数据,您可以创建两个实体:"observations""timesteps",然后应用 featuretools.dfs (Deep Feature Synthesis) 为每个时间步生成特征。您可以将实体视为关系数据库中的表。

对您的问题特别有用的是 Featuretools 中的累积原语,这些操作使用许多按时间排序的实例来计算单个值。在您的情况下,如果有多个时间步长的观测值,每个时间步长都有一个特定值,您可以使用CumMean primitive 计算先前时间步长的平均值。

这是一个例子:

from featuretools.primitives import Day, Weekend, Percentile, CumMean, CumSum
import featuretools as ft
import pandas as pd
import numpy as np
timesteps = pd.DataFrame({'ts_id': range(12),
                          'timestamp': pd.DatetimeIndex(start='1/1/2018', freq='1d', periods=12),
                          'attr1': np.random.random(12),
                          'obs_id': [1, 2, 3] * 4})
print(timesteps)

       attr1  obs_id  timestamp  ts_id
0   0.663216       1 2018-01-01      0
1   0.455353       2 2018-01-02      1
2   0.800848       3 2018-01-03      2
3   0.938645       1 2018-01-04      3
4   0.442037       2 2018-01-05      4
5   0.724044       3 2018-01-06      5
6   0.304241       1 2018-01-07      6
7   0.134359       2 2018-01-08      7
8   0.275078       3 2018-01-09      8
9   0.499343       1 2018-01-10      9
10  0.608565       2 2018-01-11     10
11  0.340991       3 2018-01-12     11


entityset = ft.EntitySet("timeseries")
entityset.entity_from_dataframe("timesteps",
                                timesteps,
                                index='ts_id',
                                time_index='timestamp')
entityset.normalize_entity(base_entity_id='timesteps',
                           new_entity_id='observations',
                           index='obs_id',
                           make_time_index=True)

# per timestep
cutoffs = timesteps[['ts_id', 'timestamp']]
feature_matrix, feature_list = ft.dfs(entityset=entityset,
                                      target_entity='timesteps',
                                      cutoff_time=cutoffs,
                                      trans_primitives=[Day, Weekend, Percentile, CumMean, CumSum],
                                      agg_primitives=[])
print(feature_matrix.iloc[:, -6:])


       CUMMEAN(attr1 by obs_id)  CUMSUM(attr1 by obs_id)  CUMMEAN(PERCENTILE(attr1) by obs_id)  CUMSUM(CUMMEAN(attr1 by obs_id) by obs_id)  CUMSUM(PERCENTILE(attr1) by obs_id)  observations.DAY(first_timesteps_time)
ts_id
0                      0.100711                 0.100711                              1.000000                                    0.100711                             1.000000                                       1
1                      0.811898                 0.811898                              1.000000                                    0.811898                             1.000000                                       2
2                      0.989166                 0.989166                              1.000000                                    0.989166                             1.000000                                       3
3                      0.442035                 0.442035                              0.500000                                    0.442035                             0.500000                                       1
4                      0.910106                 0.910106                              0.800000                                    0.910106                             0.800000                                       2
5                      0.427610                 0.427610                              0.333333                                    0.427610                             0.333333                                       3
6                      0.832516                 0.832516                              0.714286                                    0.832516                             0.714286                                       1
7                      0.035121                 0.035121                              0.125000                                    0.035121                             0.125000                                       2
8                      0.178202                 0.178202                              0.333333                                    0.178202                             0.333333                                       3
9                      0.085608                 0.085608                              0.200000                                    0.085608                             0.200000                                       1
10                     0.891033                 0.891033                              0.818182                                    0.891033                             0.818182                                       2
11                     0.044010                 0.044010                              0.166667                                    0.044010                             0.166667                                       3

此示例还使用“截止时间”来告诉特征计算引擎仅使用每个“ts_id”或“obs_id”指定时间之前的数据。您可以在文档中的this page 上阅读有关截止时间的更多信息。

Featuretools 让您做的另一件很酷的事情是在“观察”表中构建每个观察的特征,而不是每个时间步长。为此,请更改“target_entity”参数。在以下示例中,我们使用每次观察的最后一个时间戳作为截止时间,这将确保从该时间之后不再使用任何数据(例如 2018 年 1 月 11 日来自 obs_id = 2 的数据将不会包含在obs_id = 1 的 Percentile() 计算,截止时间为 2018-01-10)。

# per observation
ocutoffs = timesteps[['obs_id', 'timestamp']].drop_duplicates(['obs_id'], keep='last')
ofeature_matrix, ofeature_list = ft.dfs(entityset=entityset,
                                        target_entity='observations',
                                        cutoff_time=ocutoffs,
                                        trans_primitives=[Day, Weekend, Percentile, CumMean, CumSum])
print(ofeature_matrix.iloc[:, -6:])

        PERCENTILE(STD(timesteps.attr1))  PERCENTILE(MAX(timesteps.attr1))  PERCENTILE(SKEW(timesteps.attr1))  PERCENTILE(MIN(timesteps.attr1))  PERCENTILE(MEAN(timesteps.attr1))  PERCENTILE(COUNT(timesteps))
obs_id
1                               0.666667                          1.000000                           0.666667                          0.666667                           0.666667                      1.000000
2                               0.333333                          0.666667                           0.666667                          0.666667                           0.333333                      0.833333
3                               1.000000                          1.000000                           0.333333                          0.333333                           1.000000                      0.666667

最后,实际上可以将 tsfresh 与 Featuretools 结合使用作为“自定义原语”。这是一项高级功能,但如果您有兴趣,我可以解释更多。

【讨论】:

  • 感谢有用的提示。你能解释更多关于 PERCENTILE 变量的信息吗?我不知道我们如何准确地创建这些变量。假设我有一些历史数据,我如何计算未来新数据的PERCENTILE?
【解决方案2】:

如果您提供有关该问题的更多详细信息,我可以更详细地回答。但是,根据我的理解,您想使用您拥有的时间序列数据进行预测。

在 Python 中有一个名为 keras 的包用于机器学习。你可以做的是,你可以使用 LSTM 来训练你的模型。 keras对LSTMs的支持非常好。

【讨论】:

  • 这听起来像是一个流行语的答案,您建议在不了解 OP 应用的情况下使用 LSTM。此外,在 keras 中,对 1dim LSTM 的支持还不是很好。如果 OP 想要对这些时间序列进行分类,LSTM 不是正确的工具
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2019-03-09
  • 2022-06-13
  • 2018-09-08
  • 2019-05-10
  • 1970-01-01
  • 2021-12-09
相关资源
最近更新 更多