独自のデータセットをデータローダーにパッケージ化する方法は?4つの方法でパックします。

序文

このような状況に遭遇することがよくあります。使用されるデータはライブラリ自体のものではありません。この場合、トレーニングであろうとテストであろうと、自分でデータにインデックスを付け、毎回batch_size仕様に従ってインデックスを付ける必要があります。 。私が最初に考えたのは(100個のサンプルがあると仮定して)、たとえば自分でインデックステーブルを作成することでした。たとえばidx = np.arange(1,100,1)、最初shuffle(idx)にそれを見てから、毎回インデックスを作成するためにbatch_sizeの添え字を取りますが、常に1つのことが不自然だと感じています。

方法1:データセットとDataLoaderを継承する

from torch.utils.data import Dataset,DataLoader
import torch
train_X = torch.randn(100,28,28)
train_Y = torch.randn(100)
class Dataset(Dataset):
    def __init__(self,x,y):
        # self.x = x.unsqueeze(dim=1)
        self.y = y
    
    def __len__(self):
        return len(self.x)
    
    def __getitem__(self,idx):
        return self.x[idx],self.y[idx]
train_DL = DataLoader(Dataset(train_X,train_Y),batch_size=10,shuffle=True)
for idx,(xb,yb) in enumerate(train_DL):
    print(idx,xb.shape)

公式サイトでは次のように説明しています。ここに写真の説明を挿入

  • 上記の例では、同じ名前のデータセットのサブクラスを作成しました
  • そして必要に応じて、getitemとlenを書き直します
  • 次に、このクラスをDataLoaderに渡し、パラメータを設定します:batch_sizeとshuffle

方法2:データセットを継承してDataLoaderをカプセル化する

class DataLoader:
    def __init__(self, dl, func):
        self.dl = dl # 我们的数据集
        self.func = func # 我们的操作对象
    def __len__(self):
        return len(self.dl)
    def __iter__(self):
        batches = iter(self.dl)
        for b in batches:
            yield (self.func(*b))

方法1に基づいて、DataLoaderを自分でカプセル化します。ここで、funcは、データのロード時にデータを処理するために使用されるカスタムdef preprocess(x,y): return x.view(...),y関数です。たとえば、このような関数です。

方法3:TensorDataset&DataLoader

私は基本的にこの方法を使用します。2行のコードだけです。

from torch.utils.data import TensorDataset,DataLoader
Train_DS = TensorDataset(train_x,train_y)
Train_DL = DataLoader(Train_DS,shuffle=True,batch_size = 10)

詳細:DataLoaderのcollat​​e_fnパラメーター設定

私が見た例はすべて画像ですので、感情分類で遭遇した問題について話させてください。実際、各写真のラベルの長さが異なるように、各文の単語数も異なります。バッチで、それらの次元が同じであることを確認する方法は?文の次元=単語の数*単語のベクトルの次元、後者は心配する必要はありません。私たちがしなければならないことは、各文の単語数が同じであることを確認することです。戦略は、ベンチマークとしてバッチ内の単語数が最も多い文を見つけてから、他の短い文を補足することです(すべてゼロのベクトルを追加するだけです)。上手。DataLoaderのcollat​​e_fnは、このような「パディング」プロセスを実装できます。

とりあえず「ばかげた」方法を使っているので、まずは一般的な考え方をコードで表現し、後で完全なコードを追加してみましょう。

size = 100 # 表示每一个单词表示的向量维度
def collate_fn(batch):
    batch.sort(key = lambda x:len(x[0]),reverse=True)
    x, y = zip(*batch)
    pad_x = []
    nums = []
    max_num = len(x[0])  
    for i in range(len(x)):
        temp = x[i]  # num_of_words * size
        for j in range(max_num - len(temp)):
            temp.append([0] * size)
        pad_x.append(temp_x)
        nums.append(len(x[i]))
    return pad_x,y,lens
# Then
Train_DS = TensorDataset(train_x,train_y)
Train_DL = DataLoader(Train_DS,shuffle=True,batch_size = 10,collate_fn = collate_fn)

わかりますか?わからない場合は、説明できるように最善を尽くします(結局のところ、私のレベルは限られています)。

まず第一に、collat​​e_fnによって渡されるバッチはリストです!リストの長さはbatch_sizeです。これは、batch_size要素があることを意味します。すべての要素もリストです!このリストには、train_xのサンプルとtrain_yの分類ラベルの2つの要素があります。解決したいのは、train_xのこのサンプル、その0番目の次元(単語の数を表す)であり、他のサンプルの単語の数は異なります。
次に、最初に、リストの最初の要素(つまり、train_xのサンプル)の0ディメンション(降順)に従って、バッチ内のリストを並べ替えます。
そうすれば、理解しやすくなります。max_numは、train_xの各サンプルの最大単語数を表します(この単語数より少ない場合)。最初にmax_num-len(temp)、つまり欠落しているワード(n)の数を計算してから、n個のサイズ0のベクトルを追加します。

上記のリファレンスブック:PyTorchは無料のデータ読み取りを実現します

さらに、collat​​e_fnパラメーターを使用すると、「batch_sizeで除算されますが、残りのサンプル」の処理方法の問題も解決できます。
詳細については、ブログを参照してください。Pytorchヒント1:DataLoaderのcollat​​e_fnパラメーター

更新

そうですね、データローダーには便利です。collat​​e_fnは高度ではありませんが、基本的です(特に、NLPの場合)。

総括する

一般に、方法3とcollat​​e_fnパラメーターで十分です。方法2ではfuncをカスタマイズできますが、batch_sizeサンプルを一緒に読み取る方法と、シャッフルを実装する方法は別の問題です。対照的に、方法1では、funcもカスタマイズできます。データセットを設定するステップでは、スクイーズを解除して1つのディメンションを追加する(dim = 1)など、いくつかの操作を実行できます。

何かがおかしい、またははっきりしないと感じた場合は、コメント欄で批判または指摘してください、ありがとうございます!

おすすめ

転載: blog.csdn.net/jokerxsy/article/details/106504932