PyTorch データ変換
PyTorch では、データ変換(Data Transformation)は、データを読み込む際にデータを処理するメカニズムであり、元のデータをモデルのトレーニングに適した形式に変換します。主に torchvision.transforms が提供するツールを使用します。
データ変換は、基本的なデータ前処理(正規化、サイズ調整など)を実現できるだけでなく、データ拡張(ランダムクロップ、フリップなど)にも役立ち、モデルの汎化能力を向上させます。
なぜデータ変換が必要なのか?
データ前処理:
- データの形式、サイズ、範囲を調整し、モデルの入力に適したものにします。
- 例えば、画像は固定サイズに調整し、テンソル形式に変換して [0,1] に正規化する必要があります。
データ拡張:
- トレーニング中にデータを変換して、多様性を高めます。
- 例えば、ランダムな回転、フリップ、クロップによってデータサンプルのバリエーションを増やし、過学習を防ぎます。
柔軟性:
- 一連の変換操作を定義することで、データを動的に処理でき、データ読み込みの複雑さを簡素化できます。
PyTorch では、torchvision.transforms モジュールが画像処理用のさまざまな変換操作を提供します。
基本的な変換操作
| 変換関数名 | 説明 | 例 |
|---|---|---|
| transforms.ToTensor() | PIL 画像または NumPy 配列を PyTorch テンソルに変換し、ピクセル値を自動的に [0, 1] に正規化します。 | transform = transforms.ToTensor() |
| transforms.Normalize(mean, std) | 画像を標準化し、データをゼロ平均と単位分散に適合させます。 | transform = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) |
| transforms.Resize(size) | 画像サイズを調整し、ネットワークに入力される画像サイズが一貫していることを保証します。 | transform = transforms.Resize((256, 256)) |
| transforms.CenterCrop(size) | 画像の中心から指定されたサイズの領域をクロップします。 | transform = transforms.CenterCrop(224) |
1、ToTensor
PIL 画像または NumPy 配列を PyTorch テンソルに変換します。
同時にピクセル値を [0, 255] から [0, 1] に正規化します。
from torchvision import transforms transform = transforms.ToTensor()
2、Normalize
データを標準化し、特定の平均と標準偏差に適合させます。
通常、画像データに使用され、ピクセル値をゼロ平均と単位分散に正規化します。
transform = transforms.Normalize(mean=[0.5], std=[0.5]) # 归一化到 [-1, 1]
3、Resize
画像のサイズを調整します。
transform = transforms.Resize((128, 128)) # 将图像调整为 128x128
4、CenterCrop
画像の中心から指定されたサイズの領域をクロップします。
transform = transforms.CenterCrop(128) # 裁剪 128x128 的区域
データ拡張操作
| 変換関数名 | 説明 | 例 |
|---|---|---|
| transforms.RandomHorizontalFlip(p) | 画像をランダムに水平反転します。 | transform = transforms.RandomHorizontalFlip(p=0.5) |
| transforms.RandomRotation(degrees) | 画像をランダムに回転します。 | transform = transforms.RandomRotation(degrees=45) |
| transforms.ColorJitter(brightness, contrast, saturation, hue) | 画像の明るさ、コントラスト、彩度、色相を調整します。 | transform = transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1) |
| transforms.RandomCrop(size) | 指定されたサイズの領域をランダムにクロップします。 | transform = transforms.RandomCrop(224) |
| transforms.RandomResizedCrop(size) | 画像をランダムにクロップし、指定されたサイズに調整します。 | transform = transforms.RandomResizedCrop(224) |
1、RandomCrop
画像から指定されたサイズをランダムにクロップします。
transform = transforms.RandomCrop(128)
2、RandomHorizontalFlip
一定の確率で画像を水平反転します。
transform = transforms.RandomHorizontalFlip(p=0.5) # 50% 概率翻转
3、RandomRotation
ランダムな角度で回転します。
transform = transforms.RandomRotation(degrees=30) # 随机旋转 -30 到 +30 度
4、ColorJitter
画像の明るさ、コントラスト、彩度、色相をランダムに変更します。
transform = transforms.ColorJitter(brightness=0.5, contrast=0.5)
変換の組み合わせ
| 変換関数名 | 説明 | 例 |
|---|---|---|
| transforms.Compose() | 複数の変換を組み合わせて、順番に適用します。 | transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), transforms.Resize((256, 256))]) |
transforms.Compose を使用して複数の変換を組み合わせます。
transform = transforms.Compose([
transforms.Resize((128, 128)),
transforms.RandomHorizontalFlip(p=0.5),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5], std=[0.5])
])
カスタム変換
transforms が提供する機能で要件を満たせない場合は、カスタムクラスまたは関数で実装できます。
例
def __call__(self, x):
# ここで任意の変換ロジックをカスタマイズできます
return x * 2
transform = CustomTransform()
例
画像データセットへの変換の適用
MNIST データセットを読み込み、変換を適用します。
例
from torch.utils.data import DataLoader
# 変換を定義
transform = transforms.Compose([
transforms.Resize((128, 128)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5], std=[0.5])
])
# データセットを読み込み
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
# DataLoader を使用
train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)
# 変換後のデータを確認
for images, labels in train_loader:
print("画像テンソルサイズ:", images.size()) # [batch_size, 1, 128, 128]
break
出力結果は次のとおりです:
图像张量大小: torch.Size([32, 1, 128, 128])
変換効果の可視化
次のコードは、元のデータと変換後のデータの比較を示しています。
例
from torchvision import datasets
from torchvision import datasets, transforms
# 元の画像と拡張後の画像の可視化
transform_augment = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(30),
transforms.ToTensor()
])
# データセットを読み込み
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform_augment)
# 画像を表示
def show_images(dataset):
fig, axs = plt.subplots(1, 5, figsize=(15, 5))
for i in range(5):
image, label = dataset[i]
axs[i].imshow(image.squeeze(0), cmap='gray') # (1, H, W) を (H, W) に変換
axs[i].set_title(f"Label: {label}")
axs[i].axis('off')
plt.show()
show_images(dataset)
表示は次のようになります:
