python遍歷迭代器自動鏈式處理資料

365/24/60發表於2022-01-08

pytorch.utils.data可相容迭代資料訓練處理,在dataloader中使用提高訓練效率:藉助迭代器避免記憶體溢位不足的現象、藉助鏈式處理使得資料讀取利用更高效(可類比作業系統的資源調控)

書接上文,使用迭代器鏈式處理資料,在Process類的__iter__方法中執行掛載的預處理方法,可以巢狀包裹多層處理方法,類似KoaJs洋蔥模型,在for迴圈時,自動執行預處理方法返回處理後的資料

分析下述示例中輸入資料依次執行順序:travel -> deep -> shuffle -> sort -> batch,實際由於巢狀迴圈或設定快取的存在,資料流式會有變化,具體如後圖分析

from torch.utils.data import IterableDataset
# ...

import random

class Process(IterableDataset):
    def __init__(self, data, f):
        self.data = data
        # 繫結處理函式
        self.f = f   
    def __iter__(self):
        # for迴圈遍歷時,返回一個當前環節處理的迭代器物件
        return self.f(iter(self.data)) 

a = ['a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9']
b = ['b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9']
c = ['c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9']
# data = [[j + str(i) for i in range(10)] for j in ['a','b', 'c'] ]
data = [a, b, c]
def travel(d):
    for i in d:
        # print('travel ', i)
        yield i
def deep(d):
    for arr in d:
        for item in arr:
            yield item

def shuffle(d, sf_size=5):
    buf = []
    for i in d:
        buf.append(i)
        if len(buf) >= sf_size:
            random.shuffle(buf)
            for j in buf:
                # print('shuffle', j)
                yield j
            buf = []
    for k in buf:
        yield k

def sort(d):
    buf = []
    for i in d:
        buf.append(i)
        if len(buf) >= 3:
            for i in buf:
                # print('sort', i)
                yield i
            buf = []
    for k in buf:
        yield k

def batch(d):
    buf = []
    for i in d:
        buf.append(i)
        if len(buf) >= 16:
            for i in buf:
                # print('batch', i)
                yield i
            buf = []
# 對訓練資料進行的多個預處理步驟
dataset = Process(data, travel)
dataset = Process(dataset , deep)
dataset = Process(dataset , shuffle)
dataset = Process(dataset , sort)
train_dataset = Process(p, batch)

# 可在此處斷點測試
for i in p:
    print(i, 'train')

# train_data_loader = DataLoader(train_dataset,num_workers=args.num_workers,prefetch_factor=args.prefetch)
# train(model , train_data_loader)

由上可以構造資料流式方向 :batch(iter(sort(iter(shuffle(iter(deep(iter(travel(iter( d ))))))))))

根據資料流式抽取部分過程畫出時序圖如下:

相關文章