Pytorchの使い方まとめ【入門者向け】

スポンサードリンク



こんにちは。sinyです。

最近Pytorchを学習し始めましたが、四苦八苦しております・・・

基本知識をまとめて効率よく学習するためにpytorchでよく使う基本知識のまとめ記事を作成しました。

継続してアップデートしていきます。

 

Linear 層

■nn.Linear 線形結合を計算するクラス

  • nn.Linear(入力サイズ,出力サイズ)
    例nn.Linear(64, 32)

    net = nn.Linear(in_features=3, out_features=1, bias=False)

損失関数

■nn.MSELoss 損失関数を計算するクラス
■optimizer = optim.SGD(net.parameters(), lr=0.1)

torch.nn.Module

すべてのニューラルネットワークモジュールの基本クラス。
モデルもこのクラスをサブクラス化する必要がある。

モジュールには他のモジュールを含めることもできる。
これにより、モジュールをツリー構造にネストできる。
サブモジュールを通常の属性として割り当てることもできる。

サンプルコード

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
       x = F.relu(self.conv1(x))
       return F.relu(self.conv2(x)

 

add_module(name, module)

nn.Moduleクラスのメソッドで、現在のモジュールに子モジュールを追加するメソッド。
モジュールは、指定された名前を使用して属性としてアクセスできる。

class Module(object)内にadd_moduleメソッドが定義されている。

パラメータは以下の2つ。

  • name(string)
    子モジュールの名前。 子モジュールは、指定された名前を使用してこのモジュールからアクセスできる。
  • module(Module)
    モジュールに追加される子モジュール。

学習モードと推論モード

pytorchには学習モードと推論モードがある。

  • 学習モード:まず学習時にはmodel.train()を実行て学習モードにする(デフォルト)
  • 推論時にはmodel.eval()を実行して、推論モードに切り替える。
    ※DropoutレイヤとBNレイヤをevaluationモードにするために必要。

Conv2D層

 

torch.nn.Conv2d(インプット,アウトプット,カーネルサイズ,ストライド,パディング)
  ※設定例:COnv2d(256, 512, kernel_size=2, stride=2, padding=1)
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')

画像処理の注意点

PytorchとPillowでは画像要素の順番が異なる。

  • pytorch:(チャネル、高さ、幅)の順
  • pillow:(高さ、幅、チャネル)の順

pytorchで生成されたテンソルをpillowで扱うには順番を変える必要がある。
→numpy().transpose((軸の順番を指定))
 例:numpy().transpose((1, 2, 0))
      ※チャネル、高さ、幅 →高さ、幅、チャンネルに入れ替える。

np.clip() は,区間の最大値大きい入力はその最大値に,逆に最小値より小さい入力はその最小値にする関数。

 ちなみにOpenCVで画像を読み込んだ場合は[高さ][幅][色BGR]の順番でデータが読み込まれるので注意。

Pytorchのネットワークに画像を入力する際の注意点

データをミニバッチの形にする必要があるので、unsqueeze_(0)を使って入力データにミニバッチの次元を追加する必要がある。

torch.Size([3, 224, 224])  → torch.Size([1, 3, 224, 224])

DatasetとDataLoader

Pytorchには特徴量XとラベルYをまとめたコンテナがあり、TensorDatasetという。
これは、Datasetを承継したクラス。

TensorDatasetにはTensorの見渡すことができる。
TensorDatasetをDataLoaderに渡すと、ループ処理で一部のデータだけを受け取ることができる。

 

前処理系

torchvision

 

Transforms:画像でよく使われる前処理は用意してくれています。

— Compose:復数のTransformのリスト化
— Scale:大きさ変更
— CenterCrop:真ん中でクロッピング
— RandomCrop:ランダムにクロッピング
— RandomHorizontalFlip:ある確率でFlip
— Normalize:正規化
— ToTensor:PIL.ImageやnumpyをTensor化

Dropout

ドロップアウトの適用。

  • nn.Dropout(0.5)

BatchNormalization

バッチ正規化の適用。

  • nn.BatchNorm1d(k)

    BatchNorm2d(num_featureseps=1e-05momentum=0.1affine=Truetrack_running_stats=True)

  • num_features:
    input  size (N, C, H, W)のから予測されるCの値
  • momentum: 
    running_meanおよびrunning_varの計算に使用される値。 累積移動平均(つまり、単純平均)の場合、なしに設定できます。 デフォルト:0.1

torch.nn.Sequential(*args)

モジュールは、コンストラクターに渡された順序で追加されます。
あるいは、モジュールの順序付き辞書も渡すことができます。

サンプルコード

# Example of using Sequential
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# Example of using Sequential with OrderedDict
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

ちなみに、nn.Sequentialを承継すると、自動的にforwardメソッドが実装されるので改めてforwardを定義する必要がない。
(順伝搬を自動的に時やってくれる)

nn.Embedding

テキストデータのトークン化。

Embeddingの第1引数は、トークンの種類、第2引数がトークン化後の次元数を指定。
以下の例では、1万種類の単語で、10次元にベクトル化している例。

from torch import nn

embed = nn.Embedding(10000, 10, padding_idx=0)
# Embedding層への入力はint64のTensor
input = torch.tensor([1, 2, 5, 3, 7], dtype=torch.int64)
# 出力はfloat32のTensor
output = embed(input)
print(output)
#実行結果
torch.Size([5, 10])
Ttensor([[ 0.2863, -0.9933, -0.3370,  0.7446,  0.1270,  0.9122,  0.8053,  1.1777,
          1.6362,  0.8427],
        [ 0.3914, -0.5673,  0.1302,  1.5891, -0.3513,  0.4035,  0.5454,  1.1263,
          0.1845,  2.2371],
        [-0.2012, -0.4765, -1.2089, -0.4344,  0.5657, -0.1567,  0.6673, -2.2443,
          0.5802,  0.3313],
        [-0.0597,  0.5443, -0.4766, -0.3870,  1.8742,  0.3107, -0.2455, -0.3967,
          0.7191, -0.3401],
        [-1.2419, -0.3370, -0.1736,  1.8406,  0.7087,  0.8820, -0.1836, -0.3523,
          0.4609,  0.4240]], grad_fn=<EmbeddingBackward>)

 

※padding_idxを指定することで、そのIDはすべて0のベクトルになる。

 

max関数

torchのMax関数の利用。
tensorデータ中のMAX値を返してくれる。

 

a = torch.randn(1, 3)
print(a)
print("=================================")
print(a.max(1))
print("=================================")
print(torch.max(a))

#実行結果

tensor([[ 0.8915,  0.2779, -0.1820]])
=================================
torch.return_types.max(
values=tensor([0.8915]),
indices=tensor([0]))
=================================
tensor(0.8915)

 

torch.max(inputdimkeepdim=Falseout=None)

  • dimを省略するとinputの中で一番大きい値を返す。
  • dim=1を指定すると行方向で1番大きい値を返す。
  • dim=0を指定すると列方向で1番大きい値を返す。

以下、参考例です。

a = torch.randn(4, 4)
print(a)
print(torch.max(a))  #最大値を1つ取得
print(torch.max(a, 1))  #行方向の最大値を取得
print(torch.max(a, 0))  #列方向の最大値を1つ取得
x,y = torch.max(a, 1) #行方向の最大値を取得
print(x)
print(y)

#出力結果
tensor([[ 1.2307, -0.4622, -0.7571, -0.7515],
        [-1.0053,  0.1498,  0.5119,  0.1440],
        [-0.6871,  1.4413, -0.4745,  1.4345],
        [ 0.7839, -0.0550,  0.2228,  0.6828]])

tensor(1.4413)

torch.return_types.max(
values=tensor([1.2307, 0.5119, 1.4413, 0.7839]),
indices=tensor([0, 2, 1, 0]))

torch.return_types.max(
values=tensor([1.2307, 1.4413, 0.5119, 1.4345]),
indices=tensor([0, 2, 1, 2]))

tensor([2.4926, 0.6446, 1.8843, 1.3954])  #print(x)の結果
tensor([3, 2, 3, 2])   #print(y)の結果

 

x,y = torch.max(a, 1)のようにするとxに値、yにIndexを取得することができる。

 

 

ImageFolder

 

訓練、テストデータのフォルダ構成例

└─data
    ├─test
    │  ├─bike
    │  └─car
    └─train
        ├─bike
        └─car

 

ImageFolderを使うと、自動でクラス分けとラベル付けがされる。

フォルダ名をクラス名、各クラスにINDEXを割り当ててくれる。

from torchvision.datasets import ImageFolder
from torchvision import transforms
from torch.utils.data import TensorDataset, DataLoader

# ImageFolder関数を使用してDatasetを作成する
train_imgs = ImageFolder(
    "./data/train",
    transform=transforms.Compose([
      transforms.ToTensor()]

print(train_imgs.classes)
print(train_imgs.class_to_idx)

#実行結果

['bike', 'car']
{'bike': 0, 'car': 1}

 

save_imageメソッド

 

save_image(tensorfilenamenrow=8padding=2normalize=Falserange=Nonescale_each=Falsepad_value=0)

パラメータ
  • tensor・・・4次元のミニバッチTensor:形状 (B x C x H x W) 
                       ※複数指定できるがすべて同一の形状でないとだめ。
          ※例:torch.Size([4, 3, 128, 128])
  • filename・・・保存するファイル名
  • nrow・・・グリッドの各行に表示される画像の数
          ※最終グリッドサイズは(B / nrow、nrow)
          ※デフォルトは8
  • padding ・・・パディング数(デフォルトは2)

y1,y2,y3の形状がすべてtorch.Size([4, 3, 128, 128])とすると、以下のコードで4x4の画像ファイル(sample.jpg)が生成される。

from torchvision.utils import save_image

save_image(torch.cat([y1,y2,y3], 0), "sample.jpg", nrow=4)


from IPython.display import Image,display_jpeg
display_jpeg(Image('sample.jpg'))

 

torch.arange

連続値で初期化されたTensorオブジェクトを生成した場合はtorch.arangeが使える。

# 0から20までの数値で初期化された1次元のTensor
t = torch.arange(0, 10)
print(t)

tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19])

 

torch.nn.ModuleList

pythonのリストのようにpytorchのモジュールを生成したい場合は、nn.ModuleListが便利。

以下は、全結合層を10個作成する例。

module_list = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])
for i in module_list:
    print(i)

Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)
Linear(in_features=10, out_features=10, bias=True)

 

おすすめの記事