PyTorch 0.4.1 examples (コード解説) : 画像分類 – Oxford 花 17 種 (AlexNet)

PyTorch 0.4.1 examples (コード解説) : 画像分類 – Oxford 花 17 種 (AlexNet)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 08/05/2018 (0.4.1)

* 本ページは、github 上の以下の pytorch/examples と keras/examples レポジトリのサンプル・コードを参考にしています:

* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

AlexNet

PyTorch 0.4.1 の自作のサンプルをコードの簡単な解説とともに提供しています。
初級チュートリアル程度の知識は仮定しています。

MNIST / Fashion-MNIST / CIFAR-10 & CIFAR-100 について一通りウォークスルーしましたので、
異なる画像データセット上で AlexNet を試してみます。

 

University of Oxford: 17 種フラワー・データセット

ここでは University of Oxford が提供している古典的な題材を利用します。
データセットの詳細は 17 Category Flower Dataset を参照してください。

 

データセットとデータローダ

最初にデータセットを用意するために、画像データをストアしたディレクトリを torchvision.datasets.ImageFolder でラップします :

from torchvision import datasets, transforms

ds_train = datasets.ImageFolder(traindir,
                        transforms.Compose([
                            transforms.RandomResizedCrop(224),
                            transforms.RandomHorizontalFlip(),
                            transforms.ToTensor(),
                            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
                            ])
                        )

ds_test = datasets.ImageFolder(valdir,
                        transforms.Compose([
                            transforms.Resize(256),
                            transforms.CenterCrop(224),
                            transforms.ToTensor(),
                            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
                            ])
                        )

そしてデータローダ :

import torch.utils.data as data

dataloader_train = data.DataLoader(ds_train, batch_size=BATCH_SIZE, shuffle=True, num_workers=2)
dataloader_test  = data.DataLoader(ds_test, batch_size=BATCH_SIZE, shuffle=False)

 

モデル定義

AlexNet の実装は torchvision に含まれていますが、まずは自前で実装してみましょう。
ブロックに分けたのは便宜的なものです。

※ AlexNet の詳細は ImageNet Classification with Deep Convolutional Neural Networks を参照してください。

import torch.nn as nn
import torch.nn.functional as F
import torch.nn.init as init
import torch.optim as optim


class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()

        self.output1 = nn.Sequential (
            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),   # out : 55 x 55
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),   # out : 27 x 27
            nn.BatchNorm2d(96)
        )

        self.output2 = nn.Sequential(
            nn.Conv2d(96, 256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),   # out : 13 x 13
            nn.BatchNorm2d(256)
        )

        self.features = nn.Sequential(
            nn.Conv2d(256, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),   # out : 6 x 6
            nn.BatchNorm2d(256)
        )

        self.classifier = nn.Sequential (
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(4096, NUM_CLASSES),
        )


    def forward(self, x):
        x = self.output1(x)
        x = self.output2(x)
        x = self.features(x)

        x = x.view(x.size(0), 256 * 6 * 6)   # out : 9216
        return  self.classifier(x)

 

訓練と評価

最初に最適な学習率のあたりをつけるために、学習率: 0.005, 0.0025, 0.001, 0.0005, 0.00025 そして 0.0001 の各々で 100 エポック訓練してみました :

到達した精度は以下のようなものです。1.0e-4 から 5.0e-4 程度であれば問題ないようです :

  • 0.005 – 83.46 %
  • 0.0025 – 86.61 %
  • 0.001 – 87.40 %
  • 0.0005 – 88.98 %
  • 0.00025 – 89.76 %
  • 0.0001 – 88.19 %

 

初期化の変更

学習率の範囲を少し絞った上で、重み層の初期化を init.kaiming_uniform_ から init.orthogonal_ に変更して訓練してみました :

それほど大きな差があるわけではありませんが、90 % に到達しました :

  • 0.001 – 88.19 %
  • 0.0005 – 88.98 %
  • 0.00025 – 90.55 %

 

torchvision 実装モデル

ここまで上で定義した AlexNet モデルを利用してきましたが、torchvision にも実装は含まれています。
使用方法は次のように簡単です :

from torchvision.models import AlexNet, alexnet

model = alexnet(pretrained=False, num_classes=NUM_CLASSES).to(device)

学習率 0.00025 で 100 エポック訓練すると精度 84.25 % に到達しましたが、上述のモデルに比較すると精度があまり出ません。ソースを見ると一つの理由としてはバッチ正規化層を使用していない点があげられます。

 

以上