Pytorch ImageFolderとDataloaderは、自作の画像データセットをロードします



Pytorch Imagefolder



pytorch画像データセットの読み込みプロセス

2.1 torchvision.datasets.ImageFolder()画像の読み取り

ImageFolderには、次の画像フォルダーの編成が必要です。
画像
さまざまなカテゴリに対応して、0、1、…、クラス1のタグがフォルダの順序に従って生成されます。このデータセットはImageFolderの要件を満たしているため、このメソッドを使用してデータセットを読み取ります。
ImageFolderクラスの定義は次のとおりです。

class ImageFolder(root, transform=None, target_transform=None, loader=default_loader, is_valid_file=None)

ルート :このデータセットのトレーニングセットを例にとると、categoryフォルダーを含む上位ディレクトリはD: pokemon_dataset trainである必要があります。
変換 :読み取り画像のデジタルマトリックスの変換、torchvision.transformsオブジェクトとして入力
target_transform :画像カテゴリ(タグ値)の変換
ローダ :画像を読み取る方法。デフォルトでは、PILImageオブジェクトをRGB形式で読み取ります。
is_valid_file :画像が破損していないか確認してください



通常の状況では、rootとtransformの2つのパラメーターを使用するだけでよく、他のパラメーターはデフォルトで選択できます。次に、ImageFolderの基本的な使用法をコードと組み合わせて紹介します。

from torchvision import transforms from torchvision.datasets import ImageFolder from torch.utils.data import DataLoader ROOT_TRAIN = r'D:pokemon_dataset rain' ROOT_TEST = r'D:pokemon_dataset est' # Subtract 0.5 from the pixel values ​​of the three RGB channels of the image and divide by 0.5, so as to get all the pixel values # Fixed to the range of [-1.0, 1.0] normalize = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) train_transform = transforms.Compose([ transforms.Resize((256, 256)), # Cropped to 256 * 256 transforms.RandomVerticalFlip(), # Random vertical flip transforms.ToTensor(), # Convert pixels in the range of 0-255 to tensor in the range of 0-1.0 normalize]) test_transform = transforms.Compose([ transforms.Resize((256, 256)), transforms.ToTensor(), normalize]) train_dataset = ImageFolder(ROOT_TRAIN, transform=train_transform) test_dataset = ImageFolder(ROOT_TEST, transform=test_transform)

多層ニューラルネットワークの分類性能をテストする予定なので、トレーニングデータはサイズ変更とランダムフリッピングによって前処理されます。 ToTensorの場合、PIL Imageオブジェクトは0〜1.0(C、H、W)次元テンソル(ここでは(3、256、256))の範囲のピクセル値に自動的に変換されるため、のピクセルを事前に計算する必要はありません。画像、正規化により、ピクセル値を[-1.0、1.0]の範囲に大まかに固定し、速度を上げることができます。モデルは収束します。変換プロセスのシーケンスリストは、作成時に渡す必要があることに注意してください。さらに、テストセットの処理フローは、選択した分類モデルによって異なります。ここでは、ランダムフリップが削除され、残りはトレーニングセットと一致しています。



print(len(train_dataset)) # Training set size (number of images) out: 1067 print(train_dataset[0]) # The first image tensor of the training set and the corresponding label, two-dimensional tuple print(train_dataset[0][0]) # Tensor of the first image in the training set print(train_dataset[0][1]) # The label of the first image in the training set

ImageFolderによって返されるオブジェクトは、データセット内のすべての画像と対応するラベルで構成される2次元タプルコンテナであり、インデックス作成と反復をサポートし、torch.utils.data.DataLoaderへの入力として使用できます。
テスト中は、gif形式の画像の読み取りをサポートしていないようです。さらに、グレースケール画像はデフォルトでRGB 3チャネルによって読み取られます(C = 3)。

2.2 torch.utils.data.DataLoader()データセットをロードする

DataLoaderの定義は次のとおりです。

class torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=<function default_collate>, pin_memory=False, drop_last=False)

ここにいくつかのより重要なパラメータがあります:
データセット :ロードするデータセット。ImageFolderの戻り結果を渡すことができます。
バッチサイズ :毎回読み取られる画像の数
シャッフル :読み順を乱すかどうか
num_workers :データをロードする子プロセスの数



train_dataloader = DataLoader(train_dataset, batch_size=4, shuffle=True) test_dataloader = DataLoader(test_dataset, batch_size=4, shuffle=False)

ここでは、batch_size = 4がトレーニングデータとテストデータに使用されます(batch_sizeは2の整数乗であると言われています)。トレーニングセットはランダムにスクランブルされ、テストセットはスクランブルされません。すべてのエポックは、データセット内のすべての画像を1回トラバースします。データセットがbatch_sizeの整数倍でない場合、最後の反復のBはbatch_sizeでは不十分(未満)になることに注意してください。

count = 0 for train_data in train_dataloader: count += 1 imgs, target = train_data print(imgs.size()) # out: (4, 3, 256, 256) print(target, target.dtype) # out: tensor([4, 4, 3, 0]), torch.int64 if count == 1: break

DataLoaderは反復可能なオブジェクトを返します。各反復の結果は、2次元のタプルです。最初の次元は(B、C、H、W)次元のテンソルで、画像データを格納します。2番目の次元は(B、)次元のテンソルで、対応する画像のラベルをbatch_sizeに保存します。

トレーニングとテスト中に、train_dataのimgとターゲットを適宜変更して、ネットワークと損失関数の要件を満たすことができます。例として多層ニューラルネットワークを取り上げます。線形層(torch.nn.Linear(C * H * W、h1_dim)の入力として、imgsを(B、C * H * W)次元テンソルに変更する必要があります。損失関数が選択されているtorch.nn.CrossEntropyLoss()の場合、クロスエントロピー損失関数は最初にターゲットに対してワンホットエンコーディングを自動的に実行し、次に対応する損失を計算するため、ターゲットを処理する必要はありません。

import torch as th import numpy as np out = th.randn((4, 5)) target = th.LongTensor([3, 1, 0, 1]) loss_f = th.nn.CrossEntropyLoss() loss = loss_f(out, target) out_np = out.numpy() tar_np = np.array([[0, 0, 0, 1, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) def softmax_cross_entropy(arr): exp_arr = np.exp(arr) for i in range(len(exp_arr)): exp_arr[i] /= np.sum(exp_arr[i]) result = np.sum(np.log(exp_arr) * tar_np) / -4 return result result = softmax_cross_entropy(out_np) print(loss, result) # out: tensor(2.3829) 2.3828649520874023