VGG 网络结构详解与复现

VGG 网络结构详解与复现

部分参考了Amusi的知乎ZHUAN专栏文章《一文读懂VGG网络》

前言

VGG = Visual Geometry Group, 是Oxford的同名视觉组提出的深度网络。论文中提出了VGG-11, VGG-13, VGG-16, VGG-19等网络。其中全连接层数量都为3层。

VGG 相比于AlexNet的一个重要改进是用连续的3x3卷积代替了AlexNet中较大的卷积核。

使得多次小规模卷积(e.g. 三次 3 x 3 卷积)之后得到特征图具有与单次大规模卷积(e.g. 一次 7 x 7卷积)相同的感受野。对于给定的感受野,采用堆积小卷积核的方式增加了非线性层的数量,使得神经网络能够学到更复杂的模式,同时付出更小的计算代价(参数量更少)

  • 参数量计算:

    对于一个三通道输入:

    • 7 x 7 卷积,共使用n组卷积核: 7 × 7 × n = 49 n 7 \times 7 \times n = 49n 7×7×n=49n
    • 3个3 x 3 卷积进行堆叠,共使用n组卷积核: 3 × 3 × 3 × n = 27 n 3 \times 3 \times 3 \times n = 27n 3×3×3×n=27n

什么是感受野?

感受野是CNN中的一个重要概念(同时也是基础中的基础)。所谓感受野即是卷积层输出的特征图上的某一个像素在输入图片上对应的区域。

我们来回顾一下感受野大小的计算公式:
r l = r l − 1 + ( k l − 1 ) × ∏ i = 0 l − 1 s i r_l = r_{l-1} + (k_l - 1) \times \prod_{i=0}^{l-1}s_i rl=rl1+(kl1)×i=0l1si
其中 r l r_l rl为第 l l l层特征图的感受野大小, k l k_l kl为卷积核的大小, s i s_i si为第 i i i层卷积核的步长。一般认为 r 0 r_0 r0等于1。

例如,第一层卷积网络使用了7 x 7的卷积核,步长为1, 则输出特征图的感受野大小为 1 + (7 - 1) x 1 = 7。

用连续3个3 x 3, 步长为1的卷积核代替一个7 x 7的卷积核,则输出的特征图感受野大小为:
r 1 = 1 + ( 3 − 1 ) × 1 = 3 r 2 = 3 + ( 3 − 1 ) × ( 1 × 1 ) = 5 r 3 = 5 + ( 3 − 1 ) × ( 1 × 1 × 1 ) = 7 r_1 = 1 + (3-1)\times1 = 3 \\ r_2 = 3 + (3-1)\times(1\times1) = 5 \\ r_3 = 5 + (3-1)\times(1\times1\times1) = 7 r1=1+(31)×1=3r2=3+(31)×(1×1)=5r3=5+(31)×(1×1×1)=7
由于步长为1,所以每一层的感受野增量相当于(k - 1)。因此两个3 x 3小卷积核相当于一个 5 x 5卷积核,三个小卷积核相当于一个 7 x 7卷积核。

VGG的主要贡献与优点

  • 主要贡献
    • 证明了神经网络层数的加深有助于提高模型性能
  • 优点
    • 模型简洁(整个网络都使用了同样大小的卷积核(3 x 3)和最大池化尺寸 (2 x 2))
    • 加深了网络,提升了性能

VGG 网络复现

VGG网络结构

VGG 网络结构详解与复现_第1张图片

关键代码

这里参照知乎Cai Yichao的专栏文章。

传送门: PyTorch实现VGG亲身实践 - 知乎 (zhihu.com)

这里用的代码和之前的AlexNet与LeNet的结构都有所不同,为了用相同的代码复现多种VGG网络,在构造类里面定义了__make_layer方法用于批量添加卷积层组成卷积block。

def __make_layer(self, channels, num):
	layers = []
	for i in range(num):
		layers.append(nn.Conv2d(self.in_channels, channels, 3, 1, 1))
		layers.append(nn.BatchNorm2d(channels))
		layers.append(nn.ReLU())
		self.in_channels = channels
	return nn.Sequential(*layers)

用于CIFAR10数据集训练

  • 由于CIFAR10数据集图像大小为32 x 32,和之前AlexNet复现一样,去除了最后一个卷积block的池化层。同时修改了全连接层的神经元数量

    FCC in out
    1 2 x 2 x 512 1024
    2 1024 512
    3 512 10
  • Accuracy

    Net Accuracy Final Loss
    AlexNet (with Dropout) 0.6443 0.3142
    VGG11 0.6825 0.4700
    VGG13 0.0911 2.3
    VGG16 0.0999 2.3
    VGG19 0.09999 2.3

    这里发现从VGG13开始,损失下不去了。猜测是出现了梯度消失。

    这里使用代码在训练过程中打印第一层卷积的梯度:

    for name, params in model.named_parameters():
    	if name == "conv3_64.0.weight":
    		print(f"{name} grad sum: {params.grad.sum()}")
    
    VGG_11与VGG_13梯度对比
    VGG_11 VGG_13
    epoch 1 -0.28 1.77e-3
    epoch 2 0.04 -5.67e-6
    epoch 3 -8.44 4.27e-4

    显然出现了梯度消失问题。

解决梯度消失

  • 引入BatchNorm (放在ReLU之后)

    With BatchNorm
    - Accuracy Final Loss Grad@last epoch
    VGG-11 0.7551 0.1153 -13.8918
    VGG-13 0.8269 0.0737 -1.7753
    VGG-16 0.8212 0.2799 -17.8578
    VGG-19 0.8060 0.2041 3.6782

你可能感兴趣的:(网络复现笔记,卷积神经网络,神经网络,机器学习,pytorch)