如何在 scikit-learn 中自动发现时间序列数据的滞后并使用时间序列数据进行分类

How to auto-discover a lagging of time-series data in scikit-learn and classify using time-series data

我目前有一个巨大的时间序列数组,其中包含多个证券和经济统计数据的时间序列数据。

我已经用sci-kit learn写了一个函数来分类数据,但是这个函数只使用非滞后时间序列数据。

有没有办法,在 Python 中,使用 sci-kit 自动 将所有这些时间序列延迟到 find 什么时间序列(如果有的话)往往滞后于其他数据?

我正在努力创建一个使用历史数据预测未来表现的模型。

您可以简单地使用 numpy.roll()。不要忘记擦除环绕的元素,例如你不想要 [6,7,1,2,3,4,5][NA,NA,1,2,3,4,5].

没有。在 Python 中,没有办法使用 sci-kit 自动 滞后所有这些时间序列来找出哪些时间序列(如果有的话)倾向于滞后其他数据。 你必须写一些代码

TLDR 但为那些关心

的人在字里行间加上了一些 QF 宝石

序言:

"There is no dinner for free"所以要得到想要的结果是要付出代价的,但是你知道这样做是非常值得的,所以,获得高级创造力,numpy 实用知识和 scikit-learn 工具准备好,并将想象力的音量按钮调到最大。

接下来,不要指望该过程会在几秒钟内交付结果。

具有 AI/ML-hyperparameters 搜索工作计划的经验 DataSETs 跨越约 X.shape ~ ( 400, 200000 ),最好的泛化 ML -引擎超参数化交叉验证在分布式多处理集群上通常需要几天时间。

As a bonus for directing further Quant research efforts:

a sample from a similar feature-engineering research, with LDF()/GDF() indcators about varying predictive power of respective features elaborated into an extendedDataSET:
as written below, one may realise that
just the top 1. feature is responsible for 43% per se
and the next 27. features account for +17%
and the "rest" 360+ features added the remaining 40% into decisions as importances report
(
individual feature and pre-lagging detail$ are not publi$hed here for obviou$ rea$on$
and are free to be discussed separately
)

|>>> aFeatureImportancesMAP_v4( loc_PREDICTOR, X_v412 )

 ID.|LDF( fI ) | GDF|HUMAN_READABLE_FEATURE_NAME[COL] min()     | MAX()    | var()
 ___|__________|____|___________________________[___]___________|__________|____________
    |          |    |                           [   ]           |          |
  0. 0.4360231 | 43%| __________xxxxxxxxxxxxxCE [216] min:  ... | MAX: ... | var():  ...
  1. 0.0464851 | 48%| __________xxxxxxxxxxxxx_0 [215] min:  ... | MAX: ... | var():  ...
  2. 0.0104704 | 49%| __________xxxxxxxxxxxxx_1 [251] min:  ... | MAX: ... | var():  ...
  3. 0.0061596 | 49%| __________xxxxxxxxxxxxx_3 [206] min:  ... | MAX: ... | var():  ...
  4. 0.0055069 | 50%| __________xxxxxxxxxxxxx_2 [203] min:  ... | MAX: ... | var():  ...
  5. 0.0053235 | 50%| __________xxxxxxxxxxxxx_3 [212] min:  ... | MAX: ... | var():  ...
  6. 0.0050404 | 51%| ________f_xxxxxxxxxxxxx_7 [261] min:  ... | MAX: ... | var():  ...
  7. 0.0049998 | 52%| ________f_xxxxxxxxxxxxx_7 [253] min:  ... | MAX: ... | var():  ...
  8. 0.0048721 | 52%| __________xxxxxxxxxxxxx_4 [113] min:  ... | MAX: ... | var():  ...
  9. 0.0047981 | 52%| __________xxxxxxxxxxxxx_4 [141] min:  ... | MAX: ... | var():  ...
 10. 0.0043784 | 53%| __________xxxxxxxxxxxxx_3 [142] min:  ... | MAX: ... | var():  ...
 11. 0.0043257 | 53%| __________xxxxxxxxxxxxx_4 [129] min:  ... | MAX: ... | var():  ...
 12. 0.0042124 | 54%| __________xxxxxxxxxxxxx_1 [144] min:  ... | MAX: ... | var():  ...
 13. 0.0041864 | 54%| ________f_xxxxxxxxxxxxx_8 [260] min:  ... | MAX: ... | var():  ...
 14. 0.0039645 | 55%| __________xxxxxxxxxxxxx_1 [140] min:  ... | MAX: ... | var():  ...
 15. 0.0037486 | 55%| ________f_xxxxxxxxxxxxx_8 [252] min:  ... | MAX: ... | var():  ...
 16. 0.0036820 | 55%| ________f_xxxxxxxxxxxxx_8 [268] min:  ... | MAX: ... | var():  ...
 17. 0.0036384 | 56%| __________xxxxxxxxxxxxx_1 [108] min:  ... | MAX: ... | var():  ...
 18. 0.0036112 | 56%| __________xxxxxxxxxxxxx_2 [207] min:  ... | MAX: ... | var():  ...
 19. 0.0035978 | 56%| __________xxxxxxxxxxxxx_1 [132] min:  ... | MAX: ... | var():  ...
 20. 0.0035812 | 57%| __________xxxxxxxxxxxxx_4 [248] min:  ... | MAX: ... | var():  ...
 21. 0.0035558 | 57%| __________xxxxxxxxxxxxx_3 [130] min:  ... | MAX: ... | var():  ...
 22. 0.0035105 | 57%| _______f_Kxxxxxxxxxxxxx_1 [283] min:  ... | MAX: ... | var():  ...
 23. 0.0034851 | 58%| __________xxxxxxxxxxxxx_4 [161] min:  ... | MAX: ... | var():  ...
 24. 0.0034352 | 58%| __________xxxxxxxxxxxxx_2 [250] min:  ... | MAX: ... | var():  ...
 25. 0.0034146 | 59%| __________xxxxxxxxxxxxx_2 [199] min:  ... | MAX: ... | var():  ...
 26. 0.0033744 | 59%| __________xxxxxxxxxxxxx_1 [ 86] min:  ... | MAX: ... | var():  ...
 27. 0.0033624 | 59%| __________xxxxxxxxxxxxx_3 [202] min:  ... | MAX: ... | var():  ...
 28. 0.0032876 | 60%| __________xxxxxxxxxxxxx_4 [169] min:  ... | MAX: ... | var():  ...
 ...
 62. 0.0027483 | 70%| __________xxxxxxxxxxxxx_8 [117] min:  ... | MAX: ... | var():  ...
 63. 0.0027368 | 70%| __________xxxxxxxxxxxxx_2 [ 85] min:  ... | MAX: ... | var():  ...
 64. 0.0027221 | 70%| __________xxxxxxxxxxxxx_1 [211] min:  ... | MAX: ... | var():  ...
 ...
104. 0.0019674 | 80%| ________f_xxxxxxxxxxxxx_3 [273] min:  ... | MAX: ... | var():  ...
105. 0.0019597 | 80%| __________xxxxxxxxxxxxx_6 [ 99] min:  ... | MAX: ... | var():  ...
106. 0.0019199 | 80%| __________xxxxxxxxxxxxx_1 [104] min:  ... | MAX: ... | var():  ...
 ...
169. 0.0012095 | 90%| __________xxxxxxxxxxxxx_4 [181] min:  ... | MAX: ... | var():  ...
170. 0.0012017 | 90%| __________xxxxxxxxxxxxx_3 [  9] min:  ... | MAX: ... | var():  ...
171. 0.0011984 | 90%| __________xxxxxxxxxxxxx_4 [185] min:  ... | MAX: ... | var():  ...
172. 0.0011926 | 90%| __________xxxxxxxxxxxxx_1 [ 19] min:  ... | MAX: ... | var():  ...
 ...
272. 0.0005956 | 99%| __________xxxxxxxxxxxxx_2 [ 33] min:  ... | MAX: ... | var():  ...
273. 0.0005844 | 99%| __________xxxxxxxxxxxxx_2 [127] min:  ... | MAX: ... | var():  ...
274. 0.0005802 | 99%| __________xxxxxxxxxxxxx_3 [ 54] min:  ... | MAX: ... | var():  ...
275. 0.0005663 | 99%| __________xxxxxxxxxxxxx_3 [ 32] min:  ... | MAX: ... | var():  ...
276. 0.0005534 | 99%| __________xxxxxxxxxxxxx_1 [ 83] min:  ... | MAX: ... | var():  ...
 ...
391. 0.0004347 |100%| __________xxxxxxxxxxxxx_2 [ 82] min:  ... | MAX: ... | var():  ...

因此,宁可计划并预留更多的 vCPU 核心容量
,也不要期望 运行 在笔记本电脑上进行此类搜索即将到来的午餐时间...


让我们制定一个工作计划

预期的 auto-find 服务,由于多种原因,不是 scikit-learn 的一部分,但是,目标是可以实现的。

我们将使用以下适应步骤,这将使我们能够使其发挥作用:

  1. 我们将依靠 scikit-learn 的能力来搜索 [learner + [=23= 的最佳串联]] 对于定义明确的 AI/ML 问题

  2. 出于显而易见的原因,我们将依靠 numpy 权力来支持 scikit-learn 阶段

  3. 我们将依赖于相当适当的 scikit-learn AI/ML-引擎处理和过程控制(pipelineGridSearchCV 等) ,对于这种大规模攻击的低级性能进行了更好的优化,而不是试图依赖 "externally" 协调的 for-looping (它失去了所有有价值的 cache/data-locality 进步)并且已知具有显着的性能劣势。

  4. 我们将用快速、一步、先验 DataSET 适应

  5. 来替代希望的自动发现
  6. 我们让scikit-learn决定(定量表示)哪些预滞后特征,人工合成复合DataSET阐述在 [4] 中终于有了最好的预测能力


[4] DataSET 适应智能 numpy 辅助工具:

您的 DataSET 包含未指定数量的 TimeSeries 数据。对于每一个这样的,你假设一些预滞后可能有更好的预测能力,你想找到(定量支持这样的选择,对于最终的 ML 预测器)。

所以让我们首先为 DataSET 的源部分中的每个 TimeSerie DataSET[i,:] 构造 DataSET 的扩展部分,其中包含此 TimeSerie 的相应预滞后版本:

>>> def generate_TimeSERIE_preLAGs( aTimeSERIE, pre_lag_window_depth ):
...     #
...     # COURTESY & THANKS TO:
...     #                     Nicolas P. Rougier, INRIA
...     #             Author: Joe Kington / Erik Rigtorp
...     #
...     shape   = ( aTimeSERIE.size - pre_lag_window_depth + 1,
...                 pre_lag_window_depth
...                 )
...     strides = ( aTimeSERIE.itemsize,
...                 aTimeSERIE.itemsize
...                 )
...     return np.lib.stride_tricks.as_strided( aTimeSERIE,
...                                             shape,
...                                             strides = strides
...                                             )
...
>>> xVECTOR = np.arange( 10 )
>>>
>>> pre_laggz_on_xVECTOR = generate_TimeSERIE_preLAGs( xVECTOR, 4 )
>>>
>>> pre_laggz_on_xVECTOR
array([[0, 1, 2, 3],
       [1, 2, 3, 4],
       [2, 3, 4, 5],
       [3, 4, 5, 6],
       [4, 5, 6, 7],
       [5, 6, 7, 8],
       [6, 7, 8, 9]])
>>>

有了这样的扩展(更宽,你知道很多)但静态 extendedDataSET,现在包含原始 TimeSERIE 向量和所有希望测试其预滞后版本,您的 ML 搜索开始。

相位[1.A]
最初使用 scikit-learn 工具选择支持你假设的最佳特征
+
阶段 [1.B]
下一步开始超参数优化以获得支持学习者最大泛化能力的最佳交叉验证结果。

阶段 [1.B],自然应该 运行 在 extendedDataSET 的子集上(因为为了 scikit-learn 特征评估而有意扩展-选择阶段 [1.A] ).


结语:
死亡纪念: Quants 不喜欢这样...但是

为了您对 TimeSeries 分析和定量建模的进一步兴趣,you might be interested in the best answer on this >>>

相关性并不意味着因果关系,因此在制定要执行的决策时需要更加谨慎(纸总是比市场处理得更多 :o))。

试试这个

import pandas as pd
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin

class InsertLags(BaseEstimator, TransformerMixin):
    """
    Automatically Insert Lags
    """
    def __init__(self, lags):
        self.lags = lags

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):
        original_cols=list(range(len(X[0,:])))
        for lag in self.lags:
            X_lagged=pd.DataFrame(X[:,original_cols]).shift(lag).as_matrix()
            X=np.concatenate((X,X_lagged), axis=1)
        return X

然后测试一下

add_lags=InsertLags([1,2,3])

test=np.array([[1,3,5,7,9],
      [2,4,6,8,10]]).T

test

add_lags.fit_transform(test)

这应该创建一个自动创建滞后的 sklearn 转换器。如果你愿意,你可以让 original_cols 成为 class 的初始化函数的一部分,这样你就可以有选择地滞后变量。