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.3.1 転移学習(P.072 – P.082) である。
※1. プログラムの詳細は、書籍を参考(P.072 – P.082)にして下さい。
※2. CNN の理解をもう少し深めたかったので, 再度, 復習した.
※3. 前回と, 異なる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 |
# -*- coding: utf-8 -*- # 1. library import. from __future__ import print_function import torch from torch import nn, optim from torch.utils.data import DataLoader from torchvision.datasets import ImageFolder from torchvision import transforms from tqdm import tqdm import time ~(略)~ # 定番のConvolutional Neural Networkをゼロから理解する. # https://deepage.net/deep_learning/2016/11/07/convolutional_neural_network.html # in: torch.Size([1, 3, 224, 224]) # out: torch.Size([1, 192, 3, 3]) conv_net = nn.Sequential( # 以下のように略記. # H: image height, W: image width # P: padding, KH: kernel height, KW: kernel weight # SH: stride height, SW: stride weight # in: dimension 3, out: dimension 32. # 111 = {(H)224 + 2 * (P)0 - (KH)4 / (SH)2} + 1 nn.Conv2d(3, 32, 4, stride=2), # 37 = 111 / (KH)3 nn.MaxPool2d(3), nn.ReLU(), # in: dimension 32. nn.BatchNorm2d(32), # in: dimension 32, out: dimension 96. # 18 = {(H)37 + 2 * (P)0 - (KH)3 / (SH)2} + 1 nn.Conv2d(32, 96, 3, stride=2), # 9 = 18 / (KH)2 nn.MaxPool2d(2), nn.ReLU(), # in: dimension 96. nn.BatchNorm2d(96), # in: dimension 96, out: dimension 192. # 6 = {(H)9 + 2 * (P)0 - (KH)4 / (SH)1} + 1 nn.Conv2d(96, 192, 4), # 3 = 6 / (KH)2 nn.MaxPool2d(2), nn.ReLU(), # in: dimension 192. nn.BatchNorm2d(192), # torch.Size([1, 192, 3, 3]) FlattenLayer() ) # 5. Finally, by convolution, check what kind of size it is. test_input = torch.ones(1, 3, 224, 224) # tensor: torch.Size([1, 3, 224, 224]) # 1 × (RGB)3 × (image height)224 × (image weight)224 print('-test_input---------------------------------------') print(test_input.size()) conv_output_size = conv_net(test_input).size()[-1] print('-conv_net-----------------------------------------') print(conv_net) print('-conv_output_size---------------------------------') print(conv_output_size) # 1728 = 1 * 192 * 3 * 3. ~(略)~ # 8. display processing time. end = time.time() print('--------------------------------------------------') print('Elapsed Time: ' + str(end - start) + "[sec]") |
※上記ソースについて, 下記のようなコメントの読み替えが必要です.
nn.Conv2d(3, 32, 4, stride=2) … # 111 = {(H)224 + 2 * (P)0 – (KH)4} / (SH)2 + 1
nn.Conv2d(32, 96, 3, stride=2) … # 18 = {(H)37 + 2 * (P)0 – (KH)3} / (SH)2 + 1
nn.Conv2d(96, 192, 4) … # 6 = {(H)9 + 2 * (P)0 – (KH)4} / (SH)1 + 1
■実行結果(epoch = 10).
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 |
-test_input--------------------------------------- torch.Size([1, 3, 224, 224]) -conv_net----------------------------------------- Sequential( (0): Conv2d(3, 32, kernel_size=(4, 4), stride=(2, 2)) (1): MaxPool2d(kernel_size=3, stride=3, padding=0, dilation=1, ceil_mode=False) (2): ReLU() (3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (4): Conv2d(32, 96, kernel_size=(3, 3), stride=(2, 2)) (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (6): ReLU() (7): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (8): Conv2d(96, 192, kernel_size=(4, 4), stride=(1, 1)) (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (10): ReLU() (11): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (12): FlattenLayer () ) -conv_output_size--------------------------------- 1728 100%|██████████| 23/23 [00:02<00:00, 8.88it/s] 0 0.7228032743388956 0.6460674157303371 0.5 100%|██████████| 23/23 [00:02<00:00, 9.15it/s] 1 0.6300705386833712 0.6938202247191011 0.5833333730697632 100%|██████████| 23/23 [00:02<00:00, 8.98it/s] 2 0.6060458611358296 0.7205056179775281 0.6833333969116211 100%|██████████| 23/23 [00:02<00:00, 8.75it/s] 3 0.528985005888072 0.7584269662921348 0.7166666984558105 100%|██████████| 23/23 [00:02<00:00, 8.63it/s] 4 0.4921892082149332 0.7696629213483146 0.8000000715255737 100%|██████████| 23/23 [00:02<00:00, 9.21it/s] 5 0.5014416643164374 0.7696629213483146 0.8000000715255737 100%|██████████| 23/23 [00:02<00:00, 9.08it/s] 6 0.45061514323407953 0.7907303370786517 0.8333333730697632 100%|██████████| 23/23 [00:02<00:00, 9.57it/s] 7 0.4644389802759344 0.7935393258426966 0.7500000596046448 100%|██████████| 23/23 [00:02<00:00, 9.75it/s] 8 0.4227466962554238 0.8132022471910112 0.7833333611488342 100%|██████████| 23/23 [00:02<00:00, 8.36it/s] 9 0.4435369643298062 0.8019662921348315 0.7833333611488342 -------------------------------------------------- Elapsed Time: 27.840532064437866[sec] |
■以上の実行結果から, 以下のことが分かった.
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 |
① 実行時間について, 以下の改善が見られた. -> stride = (2, 2) の設定を追加したことで, 処理の早い段階で, 情報量が大幅に削減されたため, と推測している. [前回] Elapsed Time: 56.54160785675049[sec] [今回] Elapsed Time: 27.840532064437866[sec] ② 精度について, 以下の改善が見られた(※理由は, 不明). [前回] 約67% [今回] 約80% ⑤ CNN の 構造 について, 理解を深めるため, 改めて, 以下のように追跡し, 参照URL① の 計算式を使って, 説明を追加した. [入力値(test_input)] 画像: 1枚 × (RGBの)3種類 × (高)224px × (幅)224px -> torch.Size([1, 3, 224, 224]) [Convolution Layer(その1)] nn.Conv2d(3, 32, 4, stride=2) … in(第一引数): dimension 3, out(第二引数): dimension 32 の 設定. -> 111 = {(H)224 + 2 * (P)0 - (KH)4} / (SH)2 + 1 ※画像: 1枚 × (RGBのチャンネル???)32種類 × (高)111px × (幅)111px に変換されるイメージ. [Pooling Layer(その1)] nn.MaxPool2d(3) … サイズが1/3となる. -> 37 = 111 / (KH)3 ※画像: 1枚 × (RGBのチャンネル???)32種類 × (高)37px × (幅)37px に変換されるイメージ. [Batch Normalization(その1)] nn.BatchNorm2d(32) … サイズは, 変わらない, [Convolution Layer(その1)] の out(第二引数): dimension 32 を 引数とするらしい. [Convolution Layer(その2)] nn.Conv2d(32, 96, 3, stride=2) … in(第一引数): dimension 32, out(第二引数): dimension 96 の 設定. -> 18 = {(H)37 + 2 * (P)0 - (KH)3} / (SH)2 + 1 ※画像: 1枚 × (RGBのチャンネル???)96種類 × (高)18px × (幅)18px に変換されるイメージ. [Pooling Layer(その2)] nn.MaxPool2d(2) … サイズが1/2となる. -> 9 = 18 / (KH)2 ※画像: 1枚 × (RGBのチャンネル???)96種類 × (高)9px × (幅)9px に変換されるイメージ. [Batch Normalization(その2)] nn.BatchNorm2d(96) … サイズは, 変わらない, [Convolution Layer(その2)] の out(第二引数): dimension 96 を 引数とするらしい. [Convolution Layer(その3)] nn.Conv2d(96, 192, 4) … in(第一引数): dimension 96, out(第二引数): dimension 192 の 設定. -> 6 = {(H)9 + 2 * (P)0 - (KH)4} / (SH)1 + 1 ※画像: 1枚 × (RGBのチャンネル???)192種類 × (高)6px × (幅)6px に変換されるイメージ. [Pooling Layer(その3)] nn.MaxPool2d(2) … サイズが1/2となる. -> 3 = 6 / (KH)2 ※画像: 1枚 × (RGBのチャンネル???)192種類 × (高)3px × (幅)3px に変換されるイメージ. [Batch Normalization(その3)] nn.BatchNorm2d(192) … サイズは, 変わらない, [Convolution Layer(その3)] の out(第二引数): dimension 192 を 引数とするらしい. [Flatten Layer] FlattenLayer() … サイズは, torch.Size([1, 192, 3, 3]) から, torch.Size([1, 1728]) に変換される. ※画像: 1枚 × (情報量)1728個 に変換されるイメージ. [出力値(conv_output_size)] ※画像: (情報量)1728個 に変換されるイメージ. |
■参照サイト
【参照URL①】定番のConvolutional Neural Networkをゼロから理解する.
■参考書籍
現場で使える! PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装 (AI & TECHNOLOGY)