Programming lab

PytorchのTransformを使い方(自作Transform)

PytorchのTransformを使い方(自作Transform)

 

 

  • Transformが何をやっているかよくわからない…
  • Transformを一度体系的に学びたい

本記事では、その悩みを徹底的に解決します。

Transformを使用することで、高度な前処理を簡単に実装することができます。

また、Pytorchはカスタマイズ性が高く、複数の前処理を同時に行ったり、自分で定義した関数を容易に使用することができます。

一見、Transformは複雑に感じますが、一度習得してしまうとなくてはならない存在になります。

 

 

PytorchのTransformの使い方

 

Pytorchでデータを前処理する場合、『transforms』パッケージを使用します。

transformsを利用することで簡単に画像の前処理ができます。

実際に、具体的な使用方法を以下の順番で解説していきます。

  1. torchvision.transformsから使用する前処理のクラスをインスタンス化
  2. 画像に対して前処理を実行

 

transformsパッケージから使用する前処理のクラスをインスタンス化

 

まずは、transformsパッケージから画像に対して使用する前処理のクラスをインスタンス化します。

具体的には以下のように行います。

# インスタンス化
使用するtransforms = transforms.使用するtransforms()

 

よくわからない方は、次章で画像やTensorを具体的に前処理を行うので、そのタイミングで理解できるので安心してください。

Tensorがよくわからないという方は下記を参考にしてください。

 

【Pytorch】tensor型とは(知らないとまずいものをまとめてみた)PyTorchのTensorに関してまとめてみました。この中で紹介しているTensorの関数やメソッドは、どれも機械学習で必要不可欠なものばかりです。15分程度で読み終わるので一読して頭を整理させましょう。...

 

画像に対して前処理を実行

 

インスタンス化した前処理を画像に対して実行していきます。

具体的には、以下で実行します。

前処理された画像 = 前処理のインスタンス(画像)

 

これで前処理を施すことができます。

TransformsはDatasetパッケージと同時に使用することで威力を発揮します。

Datasetについて学びたい方は下記を参考にしてください。

 

PytorchのDatasetを徹底解説(自作データセットも作れる)PyTorchのDataset作成方法を徹底的に解説しました。本記事を読むことで、Numpy, PandasからDatasetを作成したり、自作のDatasetを作成しモジュール化する作業を初心者の方でも理解できるように徹底的に解説しました。...

 

 

Transformsの種類

 

Transformsには以下の2種類があります。

  1. 画像データを変換
  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を説明していきます。

  1. RandomAffine : ランダムにアフィン変換を行う
  2. RandomHorizontalFlip : 確率pで水平方向に反転
  3. RandomVerticalFlip : 確率pで垂直方向に反転
  4. RandomRotation : ランダムな角度で回転
  5. Grayscale : グレイスケールに変換
  6. 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.imshow(image1)
    axes.imshow(image2)
    axes[0].axis('off')
    axes.axis('off')
    axes.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>

RandomAffine変換

 

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>

HorizontalFlip変換

 

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>

VerticalFlip変換

 

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>

RandomRotation変換

 

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>

Grayscale変換

 

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=)
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>

PILに変換

 

複数の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()

# Lambdaクラスを使用
square = transforms.Lambda(square)
squared_data = square(data)

print(squared_data)

 

<Output>

tensor([ 1,  4,  9, 16])

 

まとめ

 

PytorchのTransformsパッケージを徹底解説しました。

transformをdatasetの引数に設定するだけで高度な前処理を簡単に行うことができます。

また、ComposeクラスやLambdaクラスを使用することでカスタマイズ性は格段に上がります。

本記事が皆様にって有益であると幸いです。

『深層学習を実装したい!』という方は下記を参考にしてください

 

【PyTorch入門】多層パーセプトロンでMNISTを分類本記事では、PyTrochで多層パーセプトロンを構築し、手書き文字のデータセットのMNISTを分類しました。本記事を理解することでPytorchを使用してディープラーニングを構築する基本が身につきます。...

 

ABOUT ME
努力のガリレオ
【運営者】 : 東大で理論物理を研究中(経歴)東京大学, TOEIC950点, NASA留学, カナダ滞在経験有り, 最優秀塾講師賞, オンライン英会話講師試験合格, ブログと独自コンテンツで収益6桁達成 【編集者】: イングリッシュアドバイザーとして勤務中(経歴)中学校教諭一種免許取得[英語],カナダ留学経験あり, TOEIC650点