VGG網絡是Oxford的Visual Geometry Group組提出的,VGG網絡是實驗室名字的縮寫。VGG論文闡述了其在ImageNet 2014挑戰賽上的一些發現,提出了可以通過重複使用基礎塊(Block)來構造深度模型。
VGG塊一般地,構建CNN基礎塊的規律是:
VGG論文中提出的方法是:連續使用數個相同的填充為1、窗口形狀為3 × 3的卷積層後緊接一個步幅為2、窗口形狀為2 × 2的最大池化層。卷積層保持輸入和輸出的高和寬不變,而池化層對輸入的尺寸減半。
對於給定的感受野(與輸出有關的輸入圖片的局部大小),採用堆積的小卷積核優於採用大的卷積核,因為增加網絡深度可以保證網絡能學習到更複雜的模式,而且整個模型的參數更少,代價還比較小。
我們使用vgg_block()方法來實現這個基礎的VGG塊,這個方法有幾個參數:該塊中卷積層的數量、輸入輸出通道數。
def vgg_block(num_convs, in_channels, out_channels):
'''
Returns a block of convolutional neural network
Parameters:
num_convs (int): number of convolutional layers this block has
in_channels (int): input channel number of this block
out_channels (int): output channel number of this block
Returns:
a nn.Sequential network:
'''
layers=[]
for _ in range(num_convs):
# (input_shape - 3 + 2 + 1) / 1 = input_shape
layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
layers.append(nn.ReLU())
in_channels = out_channels
# (input_shape - 2 + 2) / 2 = input_shape / 2
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
return nn.Sequential(*layers)
VGG網絡VGG與AlexNet、LeNet類似,VGG網絡分為兩大部分,前半部分是卷積層和池化層模塊,後半部分是全連接層模塊。
從AlexNet到VGG:使用基礎塊構建深度神經網絡卷積層和池化層模塊由多個基礎塊連接組成,即vgg_block()方法返回的基礎塊,我們只需要給vgg_block()方法提供:該塊中包含的卷積層數,該塊的輸入和輸出通道數。我們定義變量conv_arch,該變量是一個列表,列表中每個元素為元組(a list of tuples)。conv_arch定了每個VGG塊裡卷積層個數和輸入輸出通道數。全連接層模塊則跟AlexNet中的一樣。下面的vgg()方法會返回整個VGG網絡,輸入參數是conv_arch。
def vgg(conv_arch):
'''
Returns the VGG network
Parameters:
conv_arch ([(int, int)]): a list which contains vgg block info.
the first element is the number of convolution layers this block have.
the latter element is the output channel number of this block.
Returns:
a nn.Sequential network:
'''
# The convolutional part
conv_blks=[]
in_channels=1
for (num_convs, out_channels) in conv_arch:
conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blks, nn.Flatten(),
# The fully-connected part
nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 10))現在我們構造一個VGG網絡。它有5個卷積塊,前2塊使用單卷積層,而後3塊使用雙卷積層。第一塊的輸入輸出通道分別是1和64,第一塊的輸入通道數根據所使用的數據集而定,Fashion-MNIST數據的通道數為1,對於ImageNet等數據集,輸入通道數一般為3。之後每次對輸出通道數翻倍,直到變為512。因為這個網絡使用了8個卷積層和3個全連接層,所以經常被稱為VGG-11。
在代碼層面,定義變量conv_arch,中間包含多個元組,每個元組第一個元素為該塊的卷積層個數,第二個元素為輸出通道數。
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
net = vgg(conv_arch)模型的訓練過程與之前分享的LeNet、AlexNet基本相似。原始碼已經發布到了GitHub:https://github.com/luweizheng/machine-learning-notes/blob/master/neural-network/cnn/pytorch/vgg-fashionmnist.py
小結VGG通過多個基礎卷積塊來構造網絡。基礎塊需要定義卷積層個數和輸入輸出通道數。VGG論文認為,更小(例如3 × 3)的卷積層比更大的卷積層效率更高,因為可以增加更多的層,同時參數又不至於過多。參考資料
Simonyan, K., & Zisserman, A. (2014). Very deep convolutional networks for large-scale image recognition.http://d2l.ai/chapter_convolutional-modern/vgg.html