深層学習に精通している友人は、深層学習モデルのトレーニングが主にデータ、モデル、損失関数、オプティマイザー、反復トレーニングの 5 つのモジュールで構成されていることを知っているはずです。以下の図に示すように、Pytorch データ読み取りメカニズムはデータ モジュールのメイン ブランチです。
Pytorchのデータ読み込みはDataset+Dataloaderで完了します。で、
-
DataSet: データセットを定義します。元のデータ サンプルと対応するラベルをデータセットにマッピングして、インデックスによるその後のデータの読み取りを容易にします。同時に、データ形式の変換やデータ拡張などの前処理操作も Dataset で実行できます。
-
DataLoader: データセットを繰り返し読み取ります。データサンプルはバッチで処理され、ランダムな順序でシャッフルされるなどして、トレーニング中のデータの反復読み取りを容易にします。
データセット
データセットは、データをどこでどのように読み取るかという問題を解決するために使用されます。Pytorch によって提供される Dataset は抽象クラスであり、カスタマイズされたデータ セットはすべて Dataset を継承し、DataLoader クラスによる直接呼び出しのために __init__()、__getitem__()、および __len__() クラス メソッドをオーバーライドする必要があります。
-
__init__: データセットの初期化。
-
__getitem__: 指定されたインデックスのサンプル データを取得する方法を定義し、最後にインデックスに対応するサンプル ペア {サンプル データ x:ラベル y} を返します。
-
__len__: データセット内のサンプルの数。
以下は、cifar10 データ セットを例として、Dataset カスタム データ セットを実装するコード サンプルです。
from torch.utils.data import Dataset
from PIL import Image
import os
class Mydata(Dataset):
"""
步骤一:继承 torch.utils.data.Dataset 类
"""
def __init__(self,data_dir,label_dir):
"""
步骤二:实现 __init__ 函数,初始化数据集,将样本和标签映射到列表中
"""
self.data_dir = data_dir
self.label_dir = label_dir
# 用join把路径拼接一起可以避免一些因“/”引发的错误
self.path = os.path.join(self.data_dir,self.label_dir)
# 将该路径下的所有文件变成一个列表
self.img_path = os.listdir(self.path)
def __getitem__(self,idx):
"""
步骤三:实现 __getitem__ 函数,定义指定 index 时如何获取数据,并返回单条数据(样本数据、对应的标签)
"""
# 根据index(idx),从列表中取出图片
# img_path列表里每个元素就是对应图片文件名
img_name = self.img_path[idx]
# 获得对应图片路径
img_item_path = os.path.join(self.data_dir,self.label_dir,img_name)
# 使用PIL库下Image工具,打开对应路径图片
img = Image.open(img_item_path)
label = self.label_dir
# 返回图片和对应标签
return img,label
def __len__(self):
"""
步骤四:实现 __len__ 函数,返回数据集的样本总数
"""
return len(self.img_path)
# data_dir,label_dir可自定义数据集目录
train_custom_dataset = MyData(data_dir,label_dir)
test_custom_dataset = MyData(data_dir,label_dir)
データローダー
実際のプロジェクトでは、データ量が多い場合、メモリや I/O 速度の制限などを考慮すると、すべてのデータを一度にメモリにロードしたり、トレーニング中に 1 つのデータだけを使用してデータをロードしたりすることは不可能です。今回必要となるのは複数の処理と反復読み込みであり、Dataloader が登場します。
DataLoader は、データセットとサンプラーを組み合わせて、特定のデータセットに対して反復可能なオブジェクトを提供する反復可能なデータ ローダーです。データセット内の複数のオブジェクトの統合を完了できます。
Pytorch のデータ読み取りメカニズムの DataLoader モジュールには、Sampler と Dataset という 2 つのサブモジュールが含まれており、Sampler モジュールはインデックス インデックスを生成し、Dataset モジュールはインデックスに基づいてデータを読み取ります。DataLoaderのデータ読み込み処理を下図に示します。
-
データローダー: データローダー モジュールに入ります。
-
DataloaderIter: __iter__ 関数を入力して複数のプロセスを使用するかどうかを決定し、対応する読み取りメカニズムを開始します。
-
サンプラー: サンプリングを通じて、各バッチサイズで読み取るデータを選択し、これらのデータのインデックスを返します。
-
Index: バッチサイズのデータのインデックス。
-
DatasetFetcher: インデックスに対応するデータを取得します。
-
データセット: dataset[idx] を呼び出して対応するデータを取得し、リストに結合します。
-
getitem: データセットの中核であり、インデックスを使用してデータを取得します。
-
img、label: データを読み取ります。
-
Collate_fn: 読み込んだデータをリスト形式からバッチ形式に変換します。
-
バッチ データ: バッチ形式のデータ。最初の要素は画像、2 番目の要素はラベルです。
Pytorch の DataLoader クラスは次のように定義されます。
class torch.utils.data.DataLoader(
"""
构建可迭代的数据装载器,训练时,每一个for循环,每一次迭代,
从DataLoader中获取一个batch_size大小的数据
"""
dataset,
batch_size=1,
shuffle=False,
sampler=None,
batch_sampler=None,
num_workers=0,
collate_fn=None,
pin_memory=False,
drop_last=False,
)
-
dataset: ロードされるデータセット、Dataset オブジェクト。
-
batch_size: 各バッチで読み取られたサンプルの数。たとえば、batch_size=16 は、各バッチで 16 個のサンプルを読み取ることを意味します。
-
shuffle: 各エポックをシャッフルするかどうか。shuffle=True は、オーバーフィッティングの可能性を減らすためにデータを取得するときにサンプルの順序をシャッフルすることを意味します。
-
サンプラー: インデックスインデックス。
-
batch_sampler: インデックスを返すサンプラーをパックし、設定されたbatch_sizeに従ってインデックスのセットを返します。
-
num_workers: データを同期/非同期で読み取ります。num_workers=0 は、データのロードが同期され、メイン プロセスで完了することを意味します。num_workers の値を 0 より大きく設定すると、データのマルチプロセス非同期ロードが有効になり、データの読み取り速度が向上します。
-
pin_memory: データを一時バッファにコピーするかどうか。
-
Collate_fn: 複数のサンプルをミニバッチに結合します。この関数が指定されていない場合、Pytorch 内のデフォルト関数が呼び出されます。
-
drop_last: 不完全なバッチ サンプルを破棄します。drop_last=True は、データ セット サンプルの数をbatch_sizeで割り切れない場合、最後の不完全なバッチ サンプルが破棄されることを意味します。
「
追加情報
エポック: すべてのトレーニング サンプルがモデルに入力されています。これをエポックと呼びます。
反復: サンプルのバッチ (batch_size) がモデルに入力されます。これは反復と呼ばれます。
Batchsize : バッチサイズと呼ばれるサンプルのバッチのサイズ。エポックの反復回数を決定するために使用されます。
」
コードの実装例は以下のとおりです。
import torch
import torch.utils.data as Data
BATCH_SIZE = 5
x = torch.linspace(1, 10, 10)
y = torch.linspace(10, 1, 10)
# 将数据集转换为torch可识别的类型
torch_dataset = Data.TensorDataset(x, y)
loader = Data.DataLoader(
dataset=torch_dataset,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=0
)
for epoch in range(3):
for step, (batch_x, batch_y) in enumerate(loader):
print('epoch', epoch,
'| step:', step,
'| batch_x', batch_x.numpy(),
'| batch_y:', batch_y.numpy())
上記のメソッドを通じて、データ リーダー ローダーを初期化してトレーニング データ セット torch_dataset をロードできます。