VGGNet
VGG-16 一些性质:
VGG 是一个很经典的卷积神经网络结构,是由 AlexNet 改进的,相比于 AlexNet,主要的改变有两个地方:
使用 3 x 3 卷积核代替 AlexNet 中的大卷积核
使用 2 x 2 池化核代替 AlexNet 的 3 x 3 池化核
VGGNet 有很多类型,论文中提出了 4 种不同层次的网络结构(从 11 层到 19 层)
VGG 有很多优点,最本质的特点就是用小的卷积核(3x3)代替大的卷积核,2个 3x3 卷积堆叠等于1个 5x5 卷积,3 个 3x3 堆叠等于1个 7x7 卷积,感受野大小不变。
可以想象一下,在步长 s 为 1,填充 padding 为 0 时,2 个 3x3 卷积后的图像 size 为 (((N-3)/1+1)-3)/1+1 = ((N-3+1)-3+1) = N-4 = (N-5)/1+1。且做卷积后,得到的特征,都是从原图像上相同的像素点提取的(原图像每 5x5 的空域像素点对应一个新的特征),因此感受野大小不变。故 2 个 3x3 的卷积核与 5x5 的卷积核等价。
关于LeNet和VGG的一些总结
1). 网络结构
LeNet和VGG这些传统的卷积神经网络的结构一般都是卷积层+全连接层,而卷积层则一般包括卷积(nn.conv2d
)、激活(nn.ReLU(True
))和池化(一般为最大池化nn.MaxPool2d(ksize,stride)
),在卷积之后也可以加入批归一化(nn.BatchNorm2d(out_channel)
)。全连接一般有两-三层,第一层的输入为卷积层最终的输出,大小为卷积层最终输出的数据拉伸为一维向量的大小。
2). 代码结构
代码结构基本相同,基本分为以下几部分:
导入各种包
定义超参数
下载数据集
定义网络模型
定义损失函数和优化方式
训练模型
1). 初始化loss和accuracy
2). 前向传播
3). 反向传播
4). 测试模型
5). 打印每个epoch的loss和acc
保存模型
不同的地方就是网络模型的定义部分,以及定义损失函数和优化方式的定义也有可能不同。对于不同的网络,其结构必然不同,需要重新定义,但其实也是大同小异。
3). 遇到的问题和解决
从LeNet到VGG,一直以来进入了一个误区,一直以为数据图像的大小要匹配/适应网络的输入大小。在LeNet中,网络输入大小为32x32,而MNIST数据集中的图像大小为28x28,当时认为要使两者的大小匹配,将padding设置为2即解决了这个问题。然而,当用VGG训练CIFAR10数据集时,网络输入大小为224x224,而数据大小是32x32,这两者该怎么匹配呢?试过将32用padding的方法填充到224x224,但是运行之后显示内存不足(笑哭.jpg)。也百度到将数据图像resize成224x224。这个问题一直困扰了好久,看着代码里没有改动数据尺寸和网络的尺寸,不知道是怎么解决的这个匹配/适应的问题。最后一步步调试才发现在第一个全连接处报错,全连接的输入尺寸和设定的尺寸不一致,再回过头去一步步推数据的尺寸变化,发现原来的VGG网络输入是224x224的,由于卷积层不改变图像的大小,只有池化层才使图像大小缩小一半,所以经过5层卷积池化之后,图像大小缩小为原来的1/32。卷积层的最终输出是7x7x512=25088,所以全连接层的输入设为25088。当输入图像大小为32x32时,经过5层卷积之后,图像大小缩小为1x1x512,全连接的输入大小就变为了512,所以不匹配的地方在这里,而不是网络的输入处。所以输入的训练图像的大小不必要与网络原始的输入大小一致,只需要计算经过卷积池化后最终的输出(也即全连接层的输入),然后改以下全连接的输入即可。