PyTorchのTransformを使い方|自作Transformの作成方法も解説
- Transformが何をやっているかよくわからない…
- Transformを一度体系的に学びたい
本記事では、その悩みを徹底的に解決します。
Transformを使用することで、高度な前処理を簡単に実装することができます。
また、PyTorchはカスタマイズ性が高く、複数の前処理を同時に行ったり、自分で定義した関数を容易に使用することができます。
一見、Transformは複雑に感じますが、一度習得してしまうとなくてはならない存在になります。
PyTorchのTransformの使い方
PyTorchでデータを前処理する場合、『transforms』パッケージを使用します。
transformsを利用することで簡単に画像の前処理ができます。
実際に、具体的な使用方法を以下の順番で解説していきます。
- torchvision.transformsから使用する前処理のクラスをインスタンス化
- 画像に対して前処理を実行
transformsパッケージから使用する前処理のクラスをインスタンス化
まずは、transformsパッケージから画像に対して使用する前処理のクラスをインスタンス化します。
具体的には以下のように行います。
# インスタンス化
使用するtransforms = transforms.使用するtransforms()
よくわからない方は、この後、画像やTensorに対して具体的に前処理を行うため、そのタイミングで理解できます!
そもそもTensorがよくわからないという方は下記を一読してから先に進んでください。
画像に対して前処理を実行
インスタンス化した前処理を画像に対して実行していきます。
具体的には、以下で実行します。
前処理された画像 = 前処理のインスタンス(画像)
これで前処理を施すことができます。
TransformsはDatasetパッケージと同時に使用することで威力を発揮します。
Datasetについて学びたい方は下記を参考にしてください。
Transformsの種類
Transformsには以下の2種類があります。
- 画像データを変換
- Tensorを変換
本記事では、画像データを変換する方法を説明してからTensorを変換する方法を説明していきます。
サンプルデータをロード
今回使用するサンプルデータをロードしましょう。
下記のコードを実行してください。
cifar10 = torchvision.datasets.CIFAR10(root='cifar10_root', train=True, download=True)
これでCifar10というデータをインポートすることができました。
このDatasetのうち一枚の画像を今回は使用します。
使用する画像を下記のコードで確認してみましょう。
<Input>
image, label = cifar10[0]
fig, ax = plt.subplots(figsize=(6, 6))
ax.imshow(image)
ax.set_title('cifar10, label=6', fontsize=15)
ax.axis('off')
plt.show()
<Output>
この蛙の画像を使用します。
画像を変換するためのTransform
ここでは、画像を変換する主要なTransformを説明していきます。
- RandomAffine : ランダムにアフィン変換を行う
- RandomHorizontalFlip : 確率pで水平方向に反転
- RandomVerticalFlip : 確率pで垂直方向に反転
- RandomRotation : ランダムな角度で回転
- Grayscale : グレイスケールに変換
- ToTensor ; PIL image, Numpy配列をTensorに変換
まずは、具体例を3枚表示するための関数をあらかじめ定義してください。
def plot_figs(image0, image1, image2):
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
axes[0].imshow(image0)
axes[1].imshow(image1)
axes[2].imshow(image2)
axes[0].axis('off')
axes[1].axis('off')
axes[2].axis('off')
plt.show()
RandomAffine : ランダムにアフィン変換を行う
RandomAffineクラスを使って画像をランダムにアフィン変換を施すことができます。
RandomAffine | |
---|---|
degree | (-degree, degree)で回転角度を指定 |
translate | (x方向の移動, y方向の移動)を指定 |
scale | (scaleの最小値, scaleの最大値)を指定 |
shear | (-x軸に対するせん断の角度, x軸に対するせん断の角度)を指定 |
下記に具体的なコードを示します。
<Input>
affine1 = transforms.RandomAffine(degrees=(-30, 30), scale=(0.5, 2.5))
affine2 = transforms.RandomAffine(degrees=(-30, 30), translate=(0.1, 0.1), scale=(0.5, 1.5), shear=(-0.1, 0.1))
image_affine1 = affine1(image)
image_affine2 = affine2(image)
plot_figs(image, image_affine1, image_affine2)
<Output>
RandomHorizontalFlip : 確率pで水平方向に反転
RandomHorizontalFlipクラスを使用することで、確率pで水平方向に反転を行うことができます。
RandomHorizontalFlip | |
---|---|
p | 水平方向に反転する確率 |
具体的なコードを下記に示します。
<Input>
hflip1 = transforms.RandomHorizontalFlip(p=0.8)
image_hflip1 = hflip1(image)
image_hflip2 = hflip1(image)
plot_figs(image, image_hflip1, image_hflip2)
<Output>
RandomVerticalFlip : 確率pで垂直方向に反転
RandomVerticalFlipクラスを使用することで、確率pで垂直方向に反転を行うことができます。
RandomVerticalFlip | |
---|---|
p | 垂直方向に反転する確率 |
具体的なコードを下記に示します。
<Input>
vflip1 = transforms.RandomVerticalFlip(p=0.8)
image_vflip1 = vflip1(image)
image_vflip2 = vflip1(image)
plot_figs(image, image_vflip1, image_vflip2)
<Output>
RandomRotation : ランダムな角度で回転
RandomRotationクラスで、画像をランダムな角度で回転させることができます。
RandomRotation | |
---|---|
degree | (-degree, degree)で回転させる角度を指定 |
center | 回転させる中心位置を指定 |
expand | Trueにすると回転した画像が収まるように出力する |
具体的なコードを下記に示します。
<Input>
rotation1 = transforms.RandomRotation(90)
rotation2 = transforms.RandomRotation(degrees=(-90, 90), center=(0,0), expand=True)
image_rotated1 = rotation1(image)
image_rotated2 = rotation2(image)
plot_figs(image, image_rotated1, image_rotated2)
<Output>
Grayscale : グレイスケールに変換
Grayscaleクラスを使用することで画像をグレイスケールに変換することができます。
Grayscale | |
---|---|
num_output_channels | 出力チャネル数 |
<Input>
gray1 = transforms.Grayscale(num_output_channels=1)
gray2 = transforms.Grayscale(num_output_channels=3)
image_gray1 = gray1(image)
image_gray2 = gray2(image)
plot_figs(image, image_gray1, image_gray2)
<output>
ToTensor : PIL image, Numpy配列をTensorに変換
ToTensorクラスは、PIL Image, Numpy配列をTensorに変換するとができます。
画像の場合、PIL Imageだと(高さ, 幅, チャネル)で画素値が[0, 255]を(チャネル, 幅, 高さ)で画素値が[0, 1.0]のTensorに変換します。
具体的なコードを下記に示します。
totensor = transforms.ToTensor()
tensor = totensor(image)
実際にTensorの形状を確認してみます。
<Input>
print(tensor.size())
<Output>
torch.Size([3, 32, 32])
(チャネル, 高さ, 幅)の配列に変換されました。
Tensorを変換するためのTransform
ここからは、Tensorを変換するためのTransformを説明していきます。
基本的な使い方は、画像を変換するときと変わりません。
Normalize : 指定した平均, 標準偏差でTensorを正規化
Normalizeクラスを使用することで、指定した平均, 標準偏差でTensorを正規化することができます。
Normalize | |
---|---|
mean | 各チャネルの平均 |
std | 各チャネルの標準偏差 |
norm = transforms.Normalize(mean=[0, 0, 0], std=[1.0, 1.0, 1.0])
normed_tensor = norm(tensor)
ToPILImage : Tensorを画像に変換
ToPILImageを使用することでTensorを画像に変換することができます。
<Input>
PIL = transforms.ToPILImage()
image = PIL(tensor)
fig, ax = plt.subplots(figsize=(6, 6))
ax.imshow(image)
ax.axis('off')
plt.show()
<Output>
複数のTransformerを実行する
複数のTransformerを実行する方法を説明していきます。
Compose : 複数のTransformを前から実行
Composeクラスを使用することで、複数のTransformを前からまとめて実行することができます。
具体的なコードを下に示します。
<Input>
affine = transforms.RandomAffine(degrees=(-10, 10), scale=(0.9, 1.1))
totensor = transforms.ToTensor()
normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0))
trans = transforms.Compose([affine, totensor, normalize])
data = trans(image)
print(data.size())
<Output>
torch.Size([3, 32, 32])
これで複数のTransformを実行することができます。
他にもランダムにTransformを実行するRandomApplyやRandomChoice等もありますが、ほとんど使用しません。
自作Transformを作成する
自分で関数を定義し、Lambdaに渡すことで自作のTransformを作成することができます。
具体的なコードを下記に示します。
<Input>
# 自作関数
def square(x):
x = x**2
return x
# sample
data = torch.tensor([1, 2, 3, 4])
# Lambdaクラスを使用
square = transforms.Lambda(square)
squared_data = square(data)
print(squared_data)
<Output>
tensor([ 1, 4, 9, 16])
まとめ
PyTorchのTransformsパッケージを徹底解説しました。
transformをdatasetの引数に設定するだけで高度な前処理を簡単に行うことができます。
また、ComposeクラスやLambdaクラスを使用することでカスタマイズ性は格段に上がります。
本記事が皆様にって有益であると幸いです。
『深層学習を実装したい!』という方は下記を参考にしてください
Pythonを学習するのに効率的なサービスを紹介していきます。
まず最初におすすめするのは、Udemyです。
Udemyは、Pythonに特化した授業がたくさんあり、どの授業も良質です。
また、セール中は1500円定義で利用することができ、コスパも最強です。
下記の記事では、実際に私が15個以上の講義を受講して特におすすめだった講義を紹介しています。
他のPythonに特化したオンライン・オフラインスクールも下記の記事でまとめています。
自分の学習スタイルに合わせて最適なものを選びましょう。
また、私がPythonを学ぶ際に使用した本を全て暴露しているので参考にしてください。