繁体   English   中英

使用滚动 window 进行 sklearn 预处理?

[英]sklearn preprocessing with a rolling window?

我正在用 sklearn 分析时间序列。 为此,我已经实施了一个前向交叉验证拆分方案。 此外,我现在正试图找到一种有效的方法来将预处理器应用于输入数据,而不会引入信息泄漏。

显然,如果我简单地将例如标准缩放器应用于时间序列训练集 X,其中 t 在 [0,T] 中,那么缩放器将像这样转换 X:

Z = (X-mean(X))/std(X)

其中值 Z_t' 是基于 [0,T] 中的 t 计算的,其中包括前瞻性信息 {t>=t'}。 为了防止这种情况,需要根据(例如)大小为 n_roll 的滚动回溯 window 中的数据对每个样本 X_t 连续应用缩放方法:

Z_t = (X_t - mean(X[t-n_roll:t]))/std(X[t-n_roll:t]) for all t in [n_roll,T]

这会在开始时切掉与滑动 window 的大小相对应的训练集的一部分。 此外,根据滑动 window 的大小,这将(更多)计算密集,然后只应用一次缩放。

我正在寻找一种通用方法来调整 sklearn 中的预处理缩放器,以便可以以这种方式应用它们来获得转换后的特征矩阵 Z 而没有前瞻性偏差,并且与管道兼容。

这是可能的,还是我应该写一个手册 function 在我将数据输入管道之前对这样的数据进行预处理?

编辑

让我添加我编写的第一个示例代码,用于在将数据输入管道之前对其进行处理:

class WalkForwardTransformer():
    
    def __init__(self,transformer,n_roll,method='<t'):
        self.transformer = transformer
        self.method = method
        self.n_roll = n_roll
        return 
    
    def generate_walkforward_chunks(self,X):
        for i in range(self.n_roll,len(X)):
            yield X.iloc[i-self.n_roll:i]
            
    def transform(self, X: pd.DataFrame, verbose=0):
        ix = X.index[self.n_roll:]
        Xgen = self.generate_walkforward_chunks(X)
        Z = []
        for i,Xi in enumerate(Xgen): 
            if self.method=='<t':
                self.transformer.fit(Xi.iloc[:-1])
            elif self.method=='<=t':
                self.transformer.fit(Xi)
            else: 
                raise NotImplementedError(self.method)
            Xil = Xi.iloc[[-1]]
            Zil = self.transformer.transform(Xil)
            Z.append(Zil.tolist()[0])
            if verbose==1: 
                print('Progress: %0.2f%%'%((i+1)*100./(len(X)-self.n_roll)),end='\r')
        Z = pd.DataFrame(Z,index=ix,columns=X.columns)
        return Z 

class 可以使用任何具有.fit_transform()方法的变压器进行初始化。

在特征 maxtrix(1000 行,172 个特征)上运行代码:


wft = WalkForwardTransformer(MinMaxScaler(),method='<=t',n_roll=100)

t0 = perf_counter()
Z_train = wft.transform(X_train.iloc[:1000],verbose=1)
print('Time: %ds'%(perf_counter()-t0))

Z_train[Z_train.columns[0]].plot()

方法='<=t'

并使用 method='<t' 运行:

方法='<t'

运行(使用 MinMaxScaler())所需的时间约为每 1000 个点 4 秒。 因此,如上所述,这在大型数据集上会非常慢。 但是,以前瞻方式对数据进行预处理就足够了。

方法 <=t 和 <t 之间的区别在于,对于第一个方法,我们将缩放器拟合到包括 t 在内的数据上,然后应用于 t 处的点,而对于第二个方法,我们将数据拟合到但是不包括 t 和 t 上的标度。 因此,在 minmaxscaler 的情况下,显然,对于 <=t,值限制在 [0,1] 中,而对于 <t,情况不一定如此。

查看我的 repo seglearn,它可以为您执行此操作https://github.com/dmbee/seglearn

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM