簡體   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