1. 環境は、Window 10 Home (64bit) 上で行った。
2. Anaconda3 (64bit) – Spyder上で、動作確認を行った。
3. python の バージョンは、python 3.7.0 である。
4. pytorch の バージョンは、pytorch 0.4.1 である。
5. GPU は, NVIDIA社 の GeForce GTX 1050 である。
6. CPU は, Intel社 の Core(TM) i7-7700HQ である。
今回確認した内容は、現場で使える! PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装 (AI & TECHNOLOGY) の 4.4 CNN回帰モデルによる画像の高解像化(P.083 – P.088) である。
※1. プログラムの詳細は、書籍を参考(P.083 – P.088)にして下さい。
※2. ConvTranspose2d が出てきたので, 改めて本家のサイトを確認し, プログラム上に, 計算式等をメモした.
■CNN回帰モデル(書籍CNNモデルを抜粋・加筆).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# -*- coding: utf-8 -*- # 1. library import. from __future__ import print_function import torch from torch import nn, optim from torchvision.datasets import ImageFolder from torchvision import transforms from torch.utils.data import DataLoader import os, time ~(略)~ # 4. declare network. # torch.nn # https://pytorch.org/docs/stable/nn.html#torch.nn.ConvTranspose2d # ex. # Input: torch.Size([1, 3, 128, 128]) # Output: torch.Size([1, 3, 512, 512]) net = nn.Sequential( # 次元の計算について, 公式サイト通りとする. # ex. # kernel_size = (2, 3) ならば, kernel_size[0] = 2, kernel_size[1] = 3 # kernel_size = 5 ならば, kernel_size[0] = 5, kernel_size[1] = 5 # padding = (3, 5) ならば, padding[0] = 3, padding[1] = 5 # padding = 2 ならば, padding[0] = 2, padding[1] = 2 # stride = (4, 5) ならば, stride[0] = 4, stride[1] = 5 # stride = 3 ならば, stride[0] = 3, stride[1] = 3 # dilation は, ここでは, 初期値 (1, 1) を 使用するため, dilation[0] = 1, dilation[1] = 1 # output_padding は, ここでは, 初期値 0 を 使用するため, output_padding[0] = 0, output_padding[1] = 0 # Conv2d # Input: (N, Cin, Hin, Win) # Output: (N, Cout, Hout, Wout) # Hout = (Hin + 2 × padding[0] − dilation[0] × (kernel_size[0] − 1) − 1) / stride[0] + 1 # Wout = (Win + 2 × padding[1] − dilation[1] × (kernel_size[1] − 1) − 1) / stride[1] + 1 # ConvTranspose2d # Input: (N, Cin, Hin, Win) # Output: (N, Cout, Hout, Wout) # Hout = (Hin − 1) × stride[0] − 2 × padding[0] + kernel_size[0] + output_padding[0] # Wout = (Win − 1) × stride[1] − 2 × padding[1] + kernel_size[1] + output_padding[1] # 1. Conv2d # Input: (1, 3, 128, 128) # Hout = (128 + 2 × 1 − 1 × (4 − 1) − 1) / 2 + 1 = 64 # Wout = (128 + 2 × 1 − 1 × (4 − 1) − 1) / 2 + 1 = 64 # Output: (1, 256, 64, 64) nn.Conv2d(3, 256, 4, stride = 2, padding = 1), nn.ReLU(), # 1. BatchNorm2d # same shape as input. # Input: (1, 256, 64, 64) # Output: (1, 256, 64, 64) nn.BatchNorm2d(256), # 2. Conv2d # Input: (1, 256, 64, 64) # Hout = (64 + 2 × 1 − 1 × (4 − 1) − 1) / 2 + 1 = 32 # Wout = (64 + 2 × 1 − 1 × (4 − 1) − 1) / 2 + 1 = 32 # Output: (1, 512, 32, 32) nn.Conv2d(256, 512, 4, stride = 2, padding = 1), nn.ReLU(), # 2. BatchNorm2d # same shape as input. # Input: (1, 512, 32, 32) # Output: (1, 512, 32, 32) nn.BatchNorm2d(512), # 1. ConvTranspose2d # Input: (1, 512, 32, 32) # Hout = (32 - 1) × 2 - 2 × 1 + 4 + 0 = 64 # Wout = (32 - 1) × 2 - 2 × 1 + 4 + 0 = 64 # Output: (1, 256, 64, 64) nn.ConvTranspose2d(512, 256, 4, stride = 2, padding = 1), nn.ReLU(), # 1. BatchNorm2d # same shape as input. # Input: (1, 256, 64, 64) # Output: (1, 256, 64, 64) nn.BatchNorm2d(256), # 2. ConvTranspose2d # Input: (1, 256, 64, 64) # Hout = (64 - 1) × 2 - 2 × 1 + 4 + 0 = 128 # Wout = (64 - 1) × 2 - 2 × 1 + 4 + 0 = 128 # Output: (1, 128, 128, 128) nn.ConvTranspose2d(256, 128, 4, stride = 2, padding = 1), nn.ReLU(), # 2. BatchNorm2d # same shape as input. # Input: (1, 128, 128, 128) # Output: (1, 128, 128, 128) nn.BatchNorm2d(128), # 3. ConvTranspose2d # Input: (1, 128, 128, 128) # Hout = (128 - 1) × 2 - 2 × 1 + 4 + 0 = 256 # Wout = (128 - 1) × 2 - 2 × 1 + 4 + 0 = 256 # Output: (1, 64, 256, 256) nn.ConvTranspose2d(128, 64, 4, stride = 2, padding = 1), nn.ReLU(), # 3. BatchNorm2d # same shape as input. # Input: (1, 64, 256, 256) # Output: (1, 64, 256, 256) nn.BatchNorm2d(64), # 4. ConvTranspose2d # Input: (1, 64, 256, 256) # Hout = (256 - 1) × 2 - 2 × 1 + 4 + 0 = 512 # Wout = (256 - 1) × 2 - 2 × 1 + 4 + 0 = 512 # Output: (1, 3, 512, 512) nn.ConvTranspose2d(64, 3, 4, stride = 2, padding = 1), ) # 5. dummy data. test_input = torch.ones(1, 3, 128, 128) conv_output_size = net(test_input).size() print('-input size --------------------------------------') print(test_input.size()) print('-net----------------------------------------------') print(net) print('-output size--------------------------------------') print(conv_output_size) # 6. display processing time. end = time.time() print('--------------------------------------------------') print('Elapsed Time: ' + str(end - start) + "[sec]") |
■実行結果(input size = torch.Size([1, 3, 128, 128]) の 場合).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-input size -------------------------------------- torch.Size([1, 3, 128, 128]) -net---------------------------------------------- Sequential( (0): Conv2d(3, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (1): ReLU() (2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (3): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (4): ReLU() (5): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (6): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (7): ReLU() (8): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (9): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (10): ReLU() (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (12): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (13): ReLU() (14): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (15): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) ) -output size-------------------------------------- torch.Size([1, 3, 512, 512]) -------------------------------------------------- Elapsed Time: 1.847071886062622[sec] |
■実行結果(input size = torch.Size([1, 3, 32, 32]) の 場合).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-input size -------------------------------------- torch.Size([1, 3, 32, 32]) -net---------------------------------------------- Sequential( (0): Conv2d(3, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (1): ReLU() (2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (3): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (4): ReLU() (5): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (6): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (7): ReLU() (8): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (9): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (10): ReLU() (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (12): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) (13): ReLU() (14): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (15): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1)) ) -output size-------------------------------------- torch.Size([1, 3, 128, 128]) -------------------------------------------------- Elapsed Time: 1.452575922012329[sec] |
■以上の実行結果から, 以下のことが分かった.
1 2 3 4 5 6 |
以下の内容の通り, 入力画像 の 縦・横サイズ が, それぞれ4倍に拡大されることを確認できた. ① 入力サイズ torch.Size([1, 3, 128, 128]) に対応する 出力サイズ は, torch.Size([1, 3, 512, 512]) となること. ※画像: 1枚 × (RGBのチャンネル)3種類 × (高)512px × (幅)512px に変換されるイメージ. ② 入力サイズ torch.Size([1, 3, 32, 32]) に対応する 出力サイズ は, torch.Size([1, 3, 128, 128]) となること. ※画像: 1枚 × (RGBのチャンネル)3種類 × (高)128px × (幅)128px に変換されるイメージ. |
■参照サイト
【参照URL①】torch.nn.Conv2d
【参照URL②】torch.nn.BatchNorm2d
【参照URL③】torch.nn.ConvTranspose2d
■参考書籍
現場で使える! PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装 (AI & TECHNOLOGY)