torch.utils.data研究ノート

実際、それは翻訳された
公式ウェブサイトです:https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader

  Pytorchのデータ読み込みツールでは、torch.utils.data.DataLoaderクラスが中心的な役割を果たします。これは、データセットに対するPythonイテレーターであり、以下をサポートします。

  • マップおよびイテレータタイプのデータセット。
  • カスタムデータの読み込み手順。
  • 自動バッチ処理
  • シングルプロセスおよびマルチプロセスのデータ読み込み。
  • 自動メモリピン留め

DataLoaderクラスコンストラクターと呼ばれるコンストラクターパラメーターを構成  することによるこれらのオプション

DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
           batch_sampler=None, num_workers=0, collate_fn=None,
           pin_memory=False, drop_last=False, timeout=0,
           worker_init_fn=None, *, prefetch_factor=2,
           persistent_workers=False)

  次の章では、これらのオプションの効果と使用法について詳しく説明します。

1.データセットタイプ

  そのDataLoader中で最も重要なのはDataset、たとえばデータをロードするためのデータセットを指定するコンストラクターパラメーターでした。Pytorchでは2つの異なるデータセットタイプが提供されています。

  • マップタイプのデータセット
  • イテレータタイプのデータセット

1.1。マップタイプのデータセット

  データセットのマップタイプは、キーまたはインデックスをデータサンプルにマッピングするクラスで実現さ__getitem__()__len__()ます。
  たとえば、画像と関連タグのdataset[idx]ディスクフォルダからの最初の読み取りを表しiます。
  詳細については、データセットを参照しください

1.2。イテレータタイプのデータセット

  イテレータタイプのデータセットはIterableDataset、インターフェイス関数を実装するクラスのサブセットであり__iter__()、データサンプルのイテレータを表します。ランダムな読み取りと書き込みが困難または可能性が低く、バッチサイズがフェッチするデータに依存する状況では、このタイプのデータセットがより適しています。
  たとえばiter(dataset)、リモートデータベースから読み取ったデータストリームやリアルタイムログを返すことができます。
  詳細については、IterableDatasetを参照してください

クラス中に
  使用されるマルチスキームによるデータ読み込みプロセスIterableDatasetで、同じデータに対して、異なるワークプロセスがそれぞれ同じレプリカを生成する場合、重複データを排除するために、データを異なる方法で配置する必要があります。特定の操作方法は、IterableDatasetドキュメントを参照できます。

2.データ読み込み手順とサンプリングツール

  イテレータタイプのデータセットの場合、データロード命令はユーザー定義のイテレータによって完全に決定されます。これにより、データの大きなブロックの読み取りやバッチサイズの動的設定の実装が非常に簡単になります(たとえば、一度に1つのサンプルバッチを選択(歩留まり)できます)。
  このセクションの残りの部分では、主にマップタイプのデータセットについて説明します。torch.utils.data.Samplerこのクラスは、データのロードプロセスで使用されるインデックスまたはキー値のシーケンスを指定するために使用されます。これは、インデックスからデータセットまでの反復可能なオブジェクトを表します。たとえば、SGDを使用する場合Sampler、インデックスをランダムに配置して、一度に1つのサンプルを選択(生成)したり、ミニバッチSGDのサンプルの小さなグループを選択(生成)したりできます。パラメータに
  基づいて、サンプリングツールのスクランブルされたシーケンスまたは値が自動的に作成さDataLoaderますshuffleさらに、ユーザーパラメータはsampler、カスタムwhereSamplerインスタンスを指定して、サンプリングごとにキーまたはインデックスを取得することもできます
  batch_samplerパラメータを使用して、毎回一連のインデックス値を生成できるカスタムサンプリングツールを設定できます。自動操作はバッチパラメータにすることができbatch_sizedrop_last詳細については次のセクション参照してください。


  データセットのイテレータータイプであり、必ずしもインデックスキーである必要はないため、パラメーターは反復タイプのデータセット用ではbatch_sizeありdrop_lastません。

2.1バッチデータまたは非バッチデータをロードする

  DataLoaderパラメータbatch_sizedrop_lastおよびbatch_samplerバッチに統合された自動的にサンプリングされたデータ。

2.1.1。自動バッチ処理(デフォルト)

  このアイテムは最も一般的に使用されます。これは、最小のバッチデータのいくつかを取得し、それらを同じサンプルのバッチに統合することと同じです。つまり、テンソルの次元の1つはバッチ次元(通常は最初の項目)です。
  パラメータbatch_size(デフォルトは1)がないNone場合、データは個別のデータではなく、バッチロードツールデータとして返されます。データバッチロードツール取得モードキーを指定するためのパラメータbatch_sizedrop_lastデータ。マップタイプのデータの場合、ユーザーはbatch_sampler一度にキーのリストを返すように設定することもできます。

ノート
  パラメータbatch_sizedrop_last実際のパラメータに基づいてsampler構築batch_samplerデータセットのマップタイプはsampler、ユーザーが設定することも、パラメーターshuffle構造に基づいて設定することもできます。データセットのイテレータータイプsamplerは、仮想の無制限サンプラーです。サンプラーの詳細については、を参照してくださいここに


  データセットから取得した複数のタイプのデータをマナー反復処理する場合、各プロセスで、データの最後のバッチの数がbatch_size設定されたパラメーターよりも少ない場合、パラメーターdrop_lastはバッチを破棄します。

  サンプリングツールを使用してサンプルのリストを取得した後collate_fn、データのリストをバッチに並べ替える機能によって設定されたパラメーター集中型マップデータからデータをロードする方法の後に
  パラメータcollate_fn設定することは、次のことと同等です。

for indices in batch_sampler:
    yield collate_fn([dataset[i] for i in indices])

  イテレータタイプのデータセットからデータをロードする方法は、次と同等です。

dataset_iter = iter(dataset)
for indices in batch_sampler:
    yield collate_fn([next(dataset_iter) for _ in indices])

collate_fn関数に  渡されるパラメーターはカスタマイズできます。たとえば、シーケンスデータをバッチの最大長まで入力します。collate_fn詳細に関するパラメータ、参照はここにあります

2.1.2。自動バッチ処理をキャンセルします

  場合によっては、ユーザーはデータセットコードでバッチ操作を手動で制御したい場合や、分離されたサンプルをロードしたい場合があります。たとえば、データのバッチを直接ロードする方が便利な場合があります(たとえば、データベースから大量のデータを読み取る、またはメモリから連続データを読み取る)、またはバッチのサイズはデータまたはプログラムに依存します分離されたサンプル上にあります。これらのシナリオでは、自動バッチを適用しなくなる可能性があります(collate_fn仕上げサンプルを使用します)。ツールロードデータによる各操作は、インスタンスのデータセットを直接返す方が便利な場合があります。
  ときセットが同時にとき(デフォルト)、バッチは自動的に閉じられます。データセットからのサンプルは、パラメータ処理機能によって取得されます   自動バッチ機能をオフにすると、デフォルトではNumPy配列のみがTensorタイプのPyTorchになり、他の配列は変更されません。   この時点で、マップタイプのデータセットからデータをロードする方法は次のようになります。batch_sizebatch_samplerNonebatch_samplerNonecollate_fn
collate_fn

for index in sampler:
    yield collate_fn(dataset[index])

  イテレータタイプのデータセットからデータをロードする方法は、次と同等です。

for data in iter(dataset):
    yield collate_fn(data)

collate_fn詳細に関するパラメータ、参照はここにあります

3.collate_fn使用する

  バッチでの自動ターンオンとターンオフの場合collate_fn、効果は異なります。
  自動バッチ処理がオフになっている場合collate_fn、関数は分離されたデータサンプルによって呼び出され、結果はデー​​タ読み込みイテレータを介して返されます。
  自動バッチ処理がオンになっている場合collate_fn、関数はデータサンプルのリストによって呼び出され、入力データサンプルを1つのバッチに統合して、データ読み込みイテレータからの戻りを容易にします。自動バッチオープンcollate_fnパフォーマンスのデフォルトについての次の説明
  説明した一例では、画像データの各サンプルと整数タグが3チャネルの場合、それぞれがタプルデータセットを返します。つまり(图像,标签)collate_fnこれらのタプルをタプルに統合したデフォルトのリストです。タプルは、バッチ処理された画像テンソルとバッチラベルテンソル。デフォルトcollate_fnには次の機能があります。

  • テンソルの最初の位置にバッチの寸法を作成します
  • 常にNumPy配列とPyTorch数値データをPyTorchのテンソルタイプに変換します
  • データ構造を変更しないでください。たとえば、各サンプルがディクショナリタイプの場合、同じキーセットを含むディクショナリが返されますが、値としてバッチテンソルが使用されます(元の値セットを量子化できない場合は、辞書の値としてリストします)。リスト、タプル、名前付きタプルなどは類似しています。

  ユーザーはカスタムのものを使用できますcollate_fn例:最初のディメンション以外のディメンションに沿った並べ替え、異なる長さのシーケンスの入力、カスタムタイプのサポートの追加など。

4.シングルプロセスおよびマルチプロセスのデータ読み込み

  DataLoaderデフォルトでは、単一のプロセスが使用されます。
PythonのGILは、スレッドの同時実行を疑似同時実行にします。データのロード時にコードブロックが発生しないようにするために、PyTorchはnum_workers、正の整数を使用するために必要なパラメーターのみを使用してマルチプロセスデータのロードを実現する簡単な方法を提供します

4.1。単一プロセスのデータ読み込み

  このモードでは、初期化で取得したデータはDataLoader同じプロセスで完了します。したがって、データの読み込みによって計算がブロックされる場合があります。ただし、データがプロセス間で共有されるシナリオ(共有メモリ、データ記述子など)、またはデータの量がメモリに完全にロードされるほど少ないシナリオでは、このモードの方が適切な場合があります。さらに、単一プロセスのロード方法で異常な中断が発生した場合、提供されるエラー情報が理解しやすくなり、デバッグが容易になります。

4.2。マルチプロセスデータの読み込み

  正の整数パラメータ設定num_workersを使用すると、指定された数のロードプロセスマルチプロセスロードツールが返されます。
  このモードでは、DataLoader(呼び出しのようにenumerate(dataloader)イテレータを作成するたびにnum_workers、作業プロセスが作成されます。datasetcollate_fnそしてworker_init_fn各プロセスに転送され、データの初期化とアクセスに使用されます。これは、内部IOとともにデータアクセスと変換がワークプロセスで実行されることを意味します。
  子プロセスで実行される作業では、呼び出し時にプロセスが返すtorch.utils.data.get_worker_info()情報(プロセスID、データセットへのコピー、初期化シードなど)を取得できます。ユーザーはデータコードを設定するか、関数を呼び出すことができます。これにより、各サブプロセスがデータセットの例の独自のコピーとは独立して動作できるようになり、子プロセスで実行するかどうかを決定するためにコードを使用できます。たとえば、この関数は、データセットをスライスするときに役立ちます。   マップタイプのデータセットの場合、メインプロセスはサンプラーを使用してシーケンス番号のリストを生成し、それらを子プロセスに渡します。したがって、シーケンスを中断する操作はメインプロセスで完了し、メインプロセスはロードのシーケンス番号を割り当てることによってロードプロセスをガイドします。   イテレータタイプのデータセットの場合、各ワーカープロセスはデータセットインスタンスのコピーを取得するため、これにより、単純なマルチプロセスで結果が繰り返されます。またはを使用することにより、ユーザーは各コピーを個別に構成できます。ドキュメントを参照してください。)同様に、マルチプロセスロードでは、最後のバッチ容量バッチの各プロセスが破棄するというパラメータが不満になります。   反復が完了するか、イテレータがガベージコレクションされると、子プロセスは閉じられます。mainNoneworker_init_fn

torch.utils.data.get_worker_info()worker_init_fnIterableDataset drop_last


  マルチプロセスのロードプロセスでCUDAテンソルを返すように警告することはお勧めしません。細かい場所がたくさんあるためです(複数のプロセスを参照するか、CUDA CUDAテンソルCUDAマルチプロセスを使用する場合は共有します)。マルチプロセスロードの場合は、自動メモリピン留め(つまりpin_memory=Trueを使用することをお勧めします。これにより、CUDAを使用できるグラフィックカードにデータが転送されます。

4.2.1。プラットフォームでの異なるパフォーマンス

  子プロセスがPythonのマルチプロセスに依存している場合でも、WindowsプラットフォームとUnixプラットフォームでのパフォーマンスは異なります。

  • Unixのデフォルトのマルチプロセススタートアッププログラムはfork()です。これにより、子プロセスは、コピーされたアドレス空間を介してデータセットとPythonパラメータ関数に直接アクセスできます。
  • Windowsではデフォルトでマルチプロセスプログラムが開始されspawn()、それは別のインタプリタを起動し、その中でメインスクリプトの実行は、その後、通訳を通して、pickleモジュールのシリアル化の道受け取るためにdatasetcollate_fnだけでなく、他のパラメータの内部サブプロセス機能。

  この個別のシリアル化は、マルチプロセスデータがロードされるときにWindowsとの互換性を確保するために、次の2つの手順を実行する必要があることを意味します。

  • if __name__ == '__main__':子プロセスがロードされた後に複数回実行されないようにするために、メインスクリプトがラップされました。たとえば、DataLoaderここでデータを設定して論理インスタンス作成できます。
  • カスタムを確認collate_fnworker_init_fnまたはdatasetコードがトップに定義されているとされている__main__子プロセスでの可用性を確保することができ文の外で検証。
4.2.2。マルチプロセスデータロードのランダム性

  デフォルトでは、各サブプロセスはbase_seed + worker_idモードを使用しています。ランダムシードが提供されます。これbase_seedは、メインプロセスによって長整数RNGモジュールを使用して生成されます。ただし、子プロセスを初期化するプロセスでは、他のライブラリ(NumPyなど)のシードもコピーされるため、各子プロセスから返される乱数は同じになります。ここで参照により解決されます
  ではworker_init_fnPyTorchシードを取得できるtorch.utils.data.get_worker_info().seedか、torch.initial_seed()取得できます。また、データが他のパッケージのシードにロードされる前に取得できます。

5.メモリの固定(固定)

  固定メモリ領域(ページロック領域など)を使用してホストからグラフィックカードにデータをコピーすると、速度が速くなります。使用方法については、こちらを参照しください固定メモリに配置された選択されたデータテンソルを自動的
  にDataLoader設定するためのデータをロードするためpin_memory=True、CUDA対応のグラフィックスにデータをより速く転送できます。
  デフォルトの固定メモリロジックは、テンソルまたはテンソルを含むMap / Iterableタイプのみを認識できます。バッチがカスタムタイプ(collate_fn返されるのはカスタムタイプ)であるか、その中の各アイテムがカスタムタイプである場合、固定化ロジックはそれらを認識できず、返される結果はメモリに固定されません。カスタムバッチタイプのサポートを実装する場合は、カスタムタイプのpin_memory()メソッドでデータのタイプを実装する必要があります
  例えば

# 自定义类
class SimpleCustomBatch:
    def __init__(self, data):
        transposed_data = list(zip(*data))
        self.inp = torch.stack(transposed_data[0], 0)
        self.tgt = torch.stack(transposed_data[1], 0)

    # 自定义内存 pinning 方法
    def pin_memory(self):
        self.inp = self.inp.pin_memory()
        self.tgt = self.tgt.pin_memory()
        return self

def collate_wrapper(batch):
    return SimpleCustomBatch(batch)

inps = torch.arange(10 * 5, dtype=torch.float32).view(10, 5)
tgts = torch.arange(10 * 5, dtype=torch.float32).view(10, 5)
dataset = TensorDataset(inps, tgts)

loader = DataLoader(dataset, batch_size=2, collate_fn=collate_wrapper,
                    pin_memory=True)

for batch_ndx, sample in enumerate(loader):
    print(sample.inp.is_pinned())
    print(sample.tgt.is_pinned())

公式ウェブサイトの後半では、データセットに関連するクラスをリストして紹介します。その中には、いくつかのクラスのユースケースが引用されています
ユースケースのあるクラスは次のとおりです。

  • torch.utils.data.IterableDataset
  • torch.utils.data.BufferedShuffleDataset(dataset、buffer_size)
  • torch.utils.data.WeightedRandomSampler(weights、num_samples、replacement = True、generator = None)
  • torch.utils.data.BatchSampler(sampler、batch_size、drop_last)
  • torch.utils.data.distributed.DistributedSampler(dataset、num_replicas = None、rank = None、shuffle = True、seed = 0、drop_last = False)

おすすめ

転載: blog.csdn.net/qq_29695701/article/details/115354889