Python yield 實現滑動窗口截取時間序列數據(滑動步長可調)

在處理時間序列預測或者時間序列分類任務的時候,經常會遇到“滑動窗口(sliding window)”的概念,包括在之前寫的二十幾篇有關時間序列預測或者分類的文章中或多或少也反覆提及這個概念。與卷積神經網絡處理圖像的原理類似,在序列數據中“滑動窗口”用來截取序列片段,從而將原始數據重塑爲指定長度的樣本,以便模型的建模。

滑動窗口的實現方法比較多,可以使用for循環,但是在處理大量數據就顯得捉襟見肘了,這時候Python yield就派上用場了。關於Python yield的原理與使用,需要一定基礎,之前專門寫過一篇文章介紹,感興趣的可以參考:深入淺出解析 Python yield

在日常的業務需求中,滑動窗口函數一般是跟訓練集測試集的劃分是分開定義的。如果是比較簡單的情況,可以定義在一個函數中。


方法1

下邊的例子是家庭用電量預測的例子中的滑動窗口實現方法。

先看一下數據集的情況:
在這裏插入圖片描述
由上圖可知,使用的訓練集(下面代碼中的train)的shape爲(1442,8),採樣點爲1442個,特徵數(features)爲8個(8列)。通過滑動窗口和切片相結合的方式來將以上採樣數據劃分成樣本(samples),其中滑動窗口的寬度和滑動步長(sw_width) 可以設置爲參數,方便後期調參的時候,找到適合自己業務需求的窗口寬度和滑動步長。代碼實現:

def sliding_window(train, sw_width=7, n_out=7, in_start=0):
    '''
    該函數實現窗口寬度爲7、滑動步長爲1的滑動窗口截取序列數據
    '''
    data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 將以周爲單位的樣本展平爲以天爲單位的序列
    X, y = [], []
    
    for _ in range(len(data)):
        in_end = in_start + sw_width
        out_end = in_end + n_out
        
        # 保證截取樣本完整,最大元素索引不超過原序列索引,則截取數據;否則丟棄該樣本
        if out_end < len(data):
            # 訓練數據以滑動步長1截取
            train_seq = data[in_start:in_end, 0]
            train_seq = train_seq.reshape((len(train_seq), 1))
            X.append(train_seq)
            y.append(data[in_end:out_end, 0])
        in_start += 1
        
    return np.array(X), np.array(y)

有了以上說明,稍微有點基礎應該不難理解。感興趣的可參考這篇文章:時間序列預測15:Multi-input / Multi-head CNN 實現用電量/發電量預測


方法2

該方法是單列截取數據,可以結合for循環和np.vstack方法將多列數據堆疊起來,該部分是項目中的一個點,等項目完成,會在以後的文章中介紹。 該方法可以指定滑動窗口的寬度和滑動步長。先看一下數據集的情況,方便理解實現的功能。
在這裏插入圖片描述
由上圖可知,數據集(下面代碼中的train)的shape爲(875,10),採樣點爲875個,特徵數(features)爲10個(10列)。代碼實現:

def _slide_window(rows, sw_width, sw_steps):
    '''
    函數功能:
    按指定窗口寬度和滑動步長實現單列數據截取
    --------------------------------------------------
    參數說明:
    rows:單個文件中的行數;
    sw_width:滑動窗口的窗口寬度;
    sw_steps:滑動窗口的滑動步長;
    '''
    start = 0
    s_num = (rows - sw_width) // sw_steps # 計算滑動次數
    new_rows = sw_width + (sw_steps * s_num) # 完整窗口包含的行數,丟棄少於窗口寬度的採樣數據;
    
    while True:
        if (start + sw_width) > new_rows: # 如果窗口結束索引超出最大索引,結束截取;
            return
        yield start, start + sw_width
        start += sw_steps

使用上邊的數據集測試一下:

_test_list = []
for start,end in _slide_window(test_concat_file.shape[0], 100, 40):
	'''
	此處可以添加for循環或者其他方式,以實現處理多列數據
	'''
    _test_list.append(test_concat_file['ax'][start:end])
    '''
    此處可添加判斷條件,以實現數組堆疊
	'''

查看生成樣本列表的長度:

len(_test_list)

輸出:

20

查看最後一個樣本所包含的採樣數據信息:

_test_list[19]

輸出:

760      0.1245
761    0.124742
762    0.124991
763    0.125238
764    0.125482
         ...   
855    0.185577
856    0.185849
857    0.186137
858    0.186466
859    0.186857
Name: ax, Length: 100, dtype: object

當然實現方法有很多,本文只舉了兩個在用的方法,希望對需要的人有幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章