私のシリーズを続けて、過去10-20年間で计算机ビジョン领域を革新した古典的な畳み込み神经ネットワークの構築について述べます。今回は、PyTorchを使用して原始的なVGGという非常に深い畳み込み神经ネットワークを構築します。このシリーズの前の記事は、私のプロフィールで見ることができ、主にLeNet5とAlexNetです。
今回も以前と同様に、VGGのアーキテクチャとその直观性、そして当時の結果について探ることにします。次に、私たちのデータセット、CIFAR100を探ることにし、最適なメモリ使用法のコードを使用してプログラムに読み込みます。その後、PyTorchを使用して原始的にVGG16(数字は層の数を指し、基本的にはVGG16とVGG19の2つのバージョンがあります)を実装し、それを私たちのデータセットにトレーニングし、テストセットに評価して、未見のデータ上でのパフォーマンスを見ます。
VGG
AlexNetの成果に基づいて、VGGは畳み込み神経망(CNN)の別の重要な側面、深さに焦点を置く。それはSimonyanとZissermanによって開発されました。通常、16の畳み込み層で構成されますが、19層にも拡張できます(そのため、VGG-16とVGG-19の両方のバージョンがあります)。すべての畳み込み層は3×3のフィルターを含みます。官方論文ここ
から、ネットワークについて詳しく読むことができます。情報源
データ読み込み
データセット
モデルの構築前に、マシン学習プロジェクトで最も重要なのは、データセットを読み取り、分析し、前処理することです。この記事では、CIFAR-100データセットを使用します。このデータセットは、CIFAR-10と同じようなものですが、100クラスにあり、それぞれ600画像が含まれます。それぞれのクラスには、500の学習画像と100のテスト画像があります。CIFAR-100の100のクラスは、20の超クラスに分けられています。それぞれの画像には、「fine」ラベル(それが属しているクラス)、および「coarse」ラベル(それが属している超クラス)が付属しています。ここでは「fine」ラベルを使用します。CIFAR-100のクラス列表は以下の通りです。
CIFAR-100データセットのクラス一覧
ライブラリの導入
ここでは、torch
(モデルの構築や学習に使用)、torchvision
(データの読み取り/処理、コンピュータビジョン用のデータセットとその処理方法を含む)およびnumpy
(数学的な操作)を主に使用します。また、GPUが利用可能であれば使用できるように変数device
を定義します。
データを読み込む
torchvision
は、コンピュータビジョンの大量的なデータセットに簡単なアクセスを提供し、これらのデータセットを簡単で直观的な方法で前処理する機能を提供しています
- train/validationデータまたはtestデータを引数に応じて返す
data_loader
関数を定義します - まず、
normalize
変数を定義します。これには、データセット内の各チャンネル(赤、緑、青)の平均と標準偏差が含まれます。これらは手動で計算することもできますが、オンラインでも入手できます。これは、データをリサイズし、テンソルに変換した後に正規化するtransform
変数に使用されます - test引数が真の場合、データセットのtest分割を簡単に読み込み、以下で説明するデータローダーを使用して返します
- test引数が假の場合(デフォルトの動作でもあります)、train分割のデータを読み込み、乱数でtrainとvalidationセット(0.9:0.1)に分割します
- 最後に、データローダーを使用します。これはCIFAR100のような小さなデータセットでは性能に影響を与えないかもしれませんが、大きなデータセットでは性能を大幅に低下させることがあり、一般的に良い慣習とされています。データローダーは、バッチごとにデータに対してイテレーションすることができます。この時、イテレーション中にデータを読み込み、すべてのデータを一度にRAMに読み込むのではなくできます。
VGG16 を scratch から構築
scratch からモデルを構築するためには、まず torch
中でモデル定義がどのように機能しているかを理解する必要があり、ここで使用する異なる種類の層の仕組みを学ぶ必要があります。
- すべてのカスタムモデルは
nn.Module
クラスを継承する必要があり、これはモデルのトレーニングを助ける基本的な機能を提供します。 - 次に、私たちがする必要がある主要なことは二つあります。まず、
__init__
関数内で私のモデルの異なる層を定義し、これらの層が入力に対して実行される順序をforward
関数内で定義する必要があります。
今、私たちが使用している異なる種類の層を定義しましょう。
nn.Conv2d
: これらはフィルターの kernel size を引数として受け取る convolutional layers です。入力と出力チャンネルの数、以及び strides や padding も必要であれば受け取ることができます。nn.BatchNorm2d
: これは convolutional layer の出力に batch normalization を適用します。nn.ReLU
: これは网络上でさまざまな出力に適用される激活関数です。nn.MaxPool2d
: これは与えられたカーネルサイズで最大プーリングを適用するnn.Dropout
: これは与えられた確率で出力にドロップアウトを適用するnn.Linear
: これは基本的に全結合層ですnn.Sequential
: これは技術的に層ではないが、同じステップの一部だった操作を組み合わせるのに役立ちます
この知識を使い、私たちは今、論文のアーキテクチャーを使用してVGG16モデルを構築することができます:
VGG16のScratchから
超参数
どのような機械学習や深層学習プロジェクトでも重要な部分があり、それは超 parameterを最適化することです。ここで、異なる値に実験するのではなく、事前に定義する必要があります。これには、エポックの数、ミスのサイズ、学習率、損失関数と最適化器が含まれます。
超 parameterの設定
トレーニング
私たちは、現在、モデルのトレーニングを行う準備ができています。まず、torch
でモデルをトレーニングする方法を見て、その後、コードを確認します。
- すべてのエポックにつき、私たちの
train_loader
内の画像とラベルを通り、利用可能な場合はGPUにそれらを移動します。これは自動的に行われます。 - 私たちは、モデルを使用してラベルに予測を行い、予測と真のラベル間の損失をloss functionを使用して計算します。(
model(images)
)criterion(outputs, labels)
を使用します。 - そして、その損失を逆向き传播します。(
loss.backward
)重みを更新します。(optimizer.step()
)ただ、更新する前に勾配を0に設定してください。これはoptimizer.zero_grad()
を使用して行われます。 - また、すべてのエポックの最後に、私たちはvalidation setを使用してモデルの精度を計算します。この場合、勾配が必要없으므로、より速い評価を行うために
with torch.no_grad()
を使用します。
次に、これらを以下のコードに結合します。
トレーニング
上記のコードの出力を以下のように確認することができます。これは、モデルが実際に学習していることを示しています。なぜなら、每一次に損失が減少しているからです。
トレーニング損失
テスト
テストのためには、test_loader
で正しく同じコードを使用します。
テスト
上記のコードを使用し、20エポックでモデルをトレーニングしました。その結果、テストセットの精度が75%に達しました。
結論
この記事で行ったことをまとめましょう:
- まず、VGG-16モデルの構造と各种の層を理解しました。
- 次に、
torchvision
を使用してCIFAR100データセットを読み取り、前処理しました。 - そして、
PyTorch
を使用して、torch
にあるさまざまな種類の層を理解しながら、自己的VGG-16モデルを構築しました。 - 最後に、CIFAR100データセットでモデルをトレーニングし、テストしました。そして、モデルはテストデータセットで75%の精度で良く機能していました。
将来的な研究
この記事を通じて、良いイントロダクションと実際の学習ができますが、さらに多くを学ぶためには、これを拡張し、他に何ができるか探るのがおすすめです。
- datasetを異なるものを試してみてください。その一つはCIFAR10またはImageNetデータセットの一部です。
- 異なるハイパーパラメーターを試して、モデルに最適な組み合わせを見つけることができます。
- 最後に、データセットから層の追加または削除を試して、それらがモデルの能力に及ぼす影響を見ます。さらに良いことに、このモデルのVGG-19バージョンを構築してみてください。
Source:
https://www.digitalocean.com/community/tutorials/vgg-from-scratch-pytorch