古典的ニューラルネットワーク (3) ブロックを使用した VGG_ ネットワーク
1 VGG の概要
1.1 VGGの概要
VGG-Net
オックスフォード大学のコンピュータビジョングループと同社が共同開発した深層畳み込みネットワークで、DeepMind
2014年ILSVRC
のコンペでは分類プロジェクトで2位、測位プロジェクトで1位を獲得した。これらの繰り返し構造は、ループとサブルーチンを使用することで、最新の深層学習フレームワークのコードに簡単に実装できます。VGG-Net
主な貢献は次のとおりです。- 小さなサイズの畳み込みカーネルを
3x3
備えた深いネットワーク( ) は、大きなサイズの畳み込みカーネルを備えた浅いネットワークよりも優れていることが証明されています。 - ネットワークの汎化パフォーマンスに対する深さの重要性を実証します。
- ブロックを使用すると、非常にコンパクトに定義されたネットワークが得られます。ブロックを使用すると、複雑なネットワークを効率的に設計できます。
- データ拡張技術であるサイズ ディザリング
scale jittering
の有効性が検証されています。
- 小さなサイズの畳み込みカーネルを
VGG-Net
最大の問題はパラメータの数であり、VGG-19
基本的には畳み込みネットワーク アーキテクチャが最も多くのパラメータを持ちます。
1.2 AlexNet と VGG の比較
-
AlexNet や LeNet と同様に、VGG ネットワークは 2 つの部分に分割できます。最初の部分は主に畳み込み層とプーリング層で構成され、2 番目の部分は全結合層で構成されます。
-
VGG ニューラル ネットワークの最初の部分は、いくつかの VGG ブロックを接続することによって形成されます。完全に接続されたモジュールは AlexNet と同じです。
-
と比較すると
AlexNet
、VGG-Net
最初の全結合層の入力はfeature map
大きくなります:7x7 vs 6x6
、512 vs 256
。
1.3 VGGニューラルネットワークの5つのグループ構造
VGG-Net
構造には 5 つのグループがあり (次のように表されますA~E
)、各構造グループは類似していますが、違いはネットワークの深さにあります。
-
構造のさまざまな部分は黒の太字で示されています。
-
畳み込み層のパラメーターは です
convx-y
。ここで、x
は畳み込みカーネルのサイズ、y
は畳み込みカーネルの数です。例: は畳み込みカーネルを
conv3-64
表します。64
3x3
-
畳み込み層のチャネル数は小さい (64 チャネル) から始まり、各プーリング層の後に 512 に達するまで畳み込み層のチャネル数が 2 倍になります。
-
各畳み込み層の後には
ReLU
活性化関数が続きます。
-
224x224
入力レイヤー:の固定サイズの画像RGB
。 -
畳み込み層: 畳み込みステップ サイズは 1 です。
-
充填方法: 畳み込みの前後で同じ空間解像度が維持されるように畳み込み層の入力を充填します。
3x3
畳み込み:same
塗りつぶし、つまり入力の上下左右の 1 ピクセルを塗りつぶします。1x1
コンボリューション: パディングは必要ありません。
-
3x3
コンボリューションカーネルサイズ:と の2 種類があります1x1
。-
3x3
コンボリューション カーネル: これは、左右、上下、中央などの概念を捉える最小サイズです。 -
1x1
コンボリューション カーネル: 入力チャンネルの線形変換。ReLU
その後に、入力チャンネルに非線形変換を実行するアクティベーション関数が続きます。
-
-
-
プーリング層: 最大プーリングが使用されます。
- プーリング層は畳み込み層の後に接続されますが、すべての畳み込み層の後にプーリングが続くわけではありません。
- プーリング ウィンドウは
2x2
、ストライドは 2 です。
-
ネットワークの最後の 4 つの層は次のとおりです:: 完全に接続された 3 つの層 + 1 つの
softmax
層。- 最初の 2 つの完全接続層は両方とも 4096 ニューロンで、3 番目の完全接続層は 1000 ニューロンです (1000 クラスの分類が実行されるため)。
- 最後の層は、
softmax
その層がクラスの出力に使用される確率です。
-
すべての隠れ層は
ReLU
活性化関数を使用します。
1.4 VGGニューラルネットワークの5つのグループ構造のパラメータ
最初の完全に接続された層のパラメータの数は次のとおりです。7x7x512x4096=1.02亿
したがって、ネットワークのパラメータのほとんどはこの層から取得されます。
通信網 | A、A-LRN | B | C | D | E |
---|---|---|---|---|---|
パラメータの数 | 1億1,300万 | 1億3,300万 | 1億3,400万 | 1億3,800万 | 1.44 |
1.5 VGG-11の実装
import torch.nn as nn
import torch
'''
原始VGG⽹络有5个卷积块,其中前两个块各有⼀个卷积层,后三个块各包含两个卷积层。
第⼀个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。
由于该⽹络使⽤8个卷积层和3个全连接层,因此它通常被称为VGG-11。
'''
class Vgg11Net(nn.Module):
def __init__(self):
super().__init__()
self.model = self.vgg()
def forward(self, X):
X = self.model(X)
return X
def vgg(self):
conv_blks = []
# 输入通道的数量,初始化为1
in_channels = 1
# 卷积层部分,一共有5个vgg块,其中前两个块各有⼀个卷积层,后三个块各包含两个卷积层
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
for (num_convs, out_channels) in conv_arch:
# 添加vgg块
conv_blks.append(self.vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blks,
nn.Flatten(),
# 全连接层部分,和AlexNet一致
# 第一个全连接层的参数数量为:7x7x512x4096=1.02亿,因此网络绝大部分参数来自于该层
nn.Linear(512 * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 10)
)
def vgg_block(self,num_convs,in_channels,out_channels):
"""
:param num_convs: 卷积层的数量
:param in_channels: 输⼊通道的数量
:param out_channels: 输出通道的数量
:return: vgg块
"""
layers = []
for _ in range(num_convs):
# 卷积层
layers.append(
# 填充方式:填充卷积层的输入,使得卷积前后保持同样的空间分辨率
nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1)
)
layers.append(nn.ReLU())
in_channels = out_channels
# 汇聚层
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
return nn.Sequential(*layers)
if __name__ == '__main__':
net = Vgg11Net()
# 测试神经网络是否可运行
# inputs = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
# outputs = net(inputs)
# print(outputs.shape)
# 查看每一层输出的shape
X = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
for layer in net.model:
X = layer(X)
print(layer.__class__.__name__, 'output shape:', X.shape)
# 1、5个卷积块,其中前两个块各有⼀个卷积层,后三个块各包含两个卷积层。
# 第⼀个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。
Sequential output shape: torch.Size([1, 64, 112, 112])
Sequential output shape: torch.Size([1, 128, 56, 56])
Sequential output shape: torch.Size([1, 256, 28, 28])
Sequential output shape: torch.Size([1, 512, 14, 14])
Sequential output shape: torch.Size([1, 512, 7, 7])
# 2、和AlexNet一样的3个全连接层
Flatten output shape: torch.Size([1, 25088])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 10])
2 VGG論文の革新点
論文のダウンロード アドレスは次のとおりです: https://arxiv.org/pdf/1409.1556.pdf
2.1 重みの初期化
ネットワークは深いため、ネットワークの重みの初期化は重要であり、初期化の設計が不十分だと学習が妨げられる可能性があります。
- この論文の重みの初期化スキームは次のとおりです: 最初に構造をトレーニングします
A
。より深い構成をトレーニングする場合、A
ネットワークはアーキテクチャの最初の 4 つの畳み込み層と最後の 3 つの完全に接続された層で初期化され、ネットワークの他の層はランダムに初期化されます。 - 著者らは後に、事前トレーニングを行わずに
Xavier
均一な。
2.2 ローカル応答正規化層 LRN
- 分類誤差は、ネットワークの深さが増すにつれて減少します。
A-LRN
とA
の比較から、局所応答正規化層ではLRN
モデルが改善されないことがわかります。
2.3 チャネルピクセルゼロ平均
- まず、トレーニング セット内のすべてのサンプルのチャネル平均をカウントします。つまり、すべての赤チャネルのピクセル平均 a、すべての緑チャネルのピクセル平均 b、およびすべての青チャネルのピクセル平均 c
- 各サンプルについて、赤チャネルの各ピクセル値から a を減算し、緑チャネルの各ピクセル値から b を減算し、青チャネルの各ピクセル値から c を減算します。
論文には他にも内容がありますので多尺度训练、多尺度测试
、興味のある方は原文をお読みください。
3 Fashion-MNIST データセットへの VGG-11 の適用例
3.1 VGG-11 ネットワーク モデルの作成
注意:由于VGG-11⽐AlexNet计算量更⼤,因此我们构建了⼀个通道数较少的⽹络,⾜够⽤于训练Fashion-MNIST数据集。
import torch.nn as nn
import torch
'''
原始VGG⽹络有5个卷积块,其中前两个块各有⼀个卷积层,后三个块各包含两个卷积层。
第⼀个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。
由于该⽹络使⽤8个卷积层和3个全连接层,因此它通常被称为VGG-11。
'''
class Vgg11Net(nn.Module):
def __init__(self):
super().__init__()
self.model = self.vgg()
def forward(self, X):
X = self.model(X)
return X
def vgg(self):
conv_blks = []
# 输入通道的数量,初始化为1
in_channels = 1
# 卷积层部分,一共有5个vgg块,其中前两个块各有⼀个卷积层,后三个块各包含两个卷积层
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
# 1、由于VGG-11⽐AlexNet计算量更⼤,因此我们构建了⼀个通道数较少的⽹络,⾜够⽤于训练Fashion-MNIST数据集。
small_conv_arch = [(pair[0], pair[1] // 4) for pair in conv_arch]
for (num_convs, out_channels) in small_conv_arch:
# 添加vgg块
conv_blks.append(self.vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blks,
nn.Flatten(),
# 全连接层部分,和AlexNet一致
# 2、注意,这里从512改为128
nn.Linear(128 * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 10)
)
def vgg_block(self,num_convs,in_channels,out_channels):
"""
:param num_convs: 卷积层的数量
:param in_channels: 输⼊通道的数量
:param out_channels: 输出通道的数量
:return: vgg块
"""
layers = []
for _ in range(num_convs):
# 卷积层
layers.append(
nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1)
)
layers.append(nn.ReLU())
in_channels = out_channels
# 汇聚层
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
return nn.Sequential(*layers)
if __name__ == '__main__':
net = Vgg11Net()
# 测试神经网络是否可运行
# inputs = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
# outputs = net(inputs)
# print(outputs.shape)
# 查看每一层输出的shape
X = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
for layer in net.model:
X = layer(X)
print(layer.__class__.__name__, 'output shape:', X.shape)
3.2 Fashion-MNIST データセットを読む
他のすべての関数は、古典的なニューラル ネットワーク (1) LeNet および Fashion-MNIST データセット上のそのアプリケーションとまったく同じです。
'''
Fashion-MNIST图像的分辨率(28×28像素)低于ImageNet图像。为了解决这个问题,增加到224×224
'''
batch_size = 128
train_iter,test_iter = get_mnist_data(batch_size,resize=224)
3.3 GPU でのモデルのトレーニング
from _03_Vgg11Net import Vgg11Net
# 初始化模型
net = Vgg11Net()
lr, num_epochs = 0.05, 10
train_ch(net, train_iter, test_iter, num_epochs, lr, try_gpu())
注:Vgg-Net用GPU才能跑,如果自己电脑没有合适的GPU,可以参考下面文章进行租借