2014年,牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一块儿研发出了新的深度卷积神经网络:VGGNet,并取得了ILSVRC2014比赛分类项目的第二名(第一名是GoogLeNet,也是同年提出的).论文下载 Very Deep Convolutional Networks for Large-Scale Image Recognition。论文主要针对卷积神经网络的深度对大规模图像集识别精度的影响,主要贡献是使用很小的卷积核($3\times3$)构建各类深度的卷积神经网络结构,并对这些网络结构进行了评估,最终证实16-19层的网络深度,可以取得较好的识别精度。 这也就是经常使用来提取图像特征的VGG-16和VGG-19。html
VGG能够当作是加深版的AlexNet,整个网络由卷积层和全链接层叠加而成,和AlexNet不一样的是,VGG中使用的都是小尺寸的卷积核($3\times3$)。python
对比,前文介绍的AlexNet的网络结构图,是否是有种赏心悦目的感受。整个结构只有$3\times3$的卷积层,连续的卷积层后使用池化层隔开。虽然层数不少,可是很简洁。网络
例如$7 \times 7 \times 512$的层要跟4096个神经元的层作全链接,则替换为对$7 \times 7 \times 512$的层做通道数为409六、卷积核为$1 \times 1$卷积。 这个“全链接转卷积”的思路是VGG做者参考了OverFeat的工做思路,例以下图是OverFeat将全链接换成卷积后,则能够来处理任意分辨率(在整张图)上计算卷积,这就是无需对原图作从新缩放处理的优点。 架构
VGG网络相比AlexNet层数多了很多,可是其结构却简单很多。函数
VGG论文主要是研究网络的深度对其分类精度的影响,因此按照上面的描述设计规则,做者实验的了不一样深度的网络结构 性能
全部网络结构都听从上面提到的设计规则,而且仅是深度不一样,也就是卷积层的个数不一样:从网络A中的11个加权层(8个卷积层和3个FC层)到网络E中的19个加权层(16个卷积层和3个FC层)。卷积层的宽度(通道数)至关小,从第一层中的64开始,而后在每一个最大池化层以后增长2倍,直到达到512。 上图给出了各个深度的卷积层使用的卷积核大小以及通道的个数。最后的D,E网络就是大名鼎鼎的VGG-16和VGG-19了。 AlexNet仅仅只有8层,其可训练的参数就达到了60M,VGG系列的参数就更恐怖了,以下图(单位是百万) 学习
因为参数大多数集中在后面三个全链接层,因此虽然网络的深度不一样,全链接层确实相同的,其参数区别倒不是特别的大。测试
论文首先将训练图像缩放到最小边长度的方形,设缩放后的训练图像的尺寸为$S \times S$。网络训练时对训练图像进行随机裁剪,裁剪尺寸为网络的输入尺寸$224 \times 224$。若是$S =224$,则输入网络的图像就是整个训练图像;若是$S > 224$,则随机裁剪训练图像包含目标的部分。ui
对于训练集图像的尺寸设置,论文中使用了两种方法:es5
单尺度评估,测试图像固定尺度。结果以下表 经过评估结果,能够看出:
多尺度评估,测试图像的尺度抖动对性能的影响 对同一张测试图像,将其缩放到不一样的尺寸进行测试,而后取这几个测试结果的平均值,做为最终的结果(有点像集成学习,所不一样的是,这里是测试图像的尺寸不一样)。使用了三种尺寸的测试图像:$Q$表示测试图像,$S$表示训练是图像尺寸:$Q = S - 32$,$Q = S + 32$,前面两种是针对训练图像是固定大小的,对于训练时图像尺寸在必定范围内抖动的,则可使用更大的测试图像尺寸。$Q = {S_{min},0.5(S_{min} + S_{max}),S_{max}}$. 评估结果以下: 评估结果代表,训练图像尺度抖动优于使用固定最小边S。
稠密和多裁剪图像评估 Dense(密集评估),即指全链接层替换为卷积层(第一FC层转换到7×7卷积层,最后两个FC层转换到1×1卷积层),最后得出一个预测的score map,再对结果求平均。 multi-crop,即对图像进行多样本的随机裁剪,将获得多张裁剪获得的图像输入到网络中,最终对全部结果平均 从上图能够看出,多裁剪的结果是好于密集估计的。并且这两种方法确实是互补的,由于它们的组合优于其中的每一种。 因为不一样的卷积边界条件,多裁剪图像评估是密集评估的补充:当将ConvNet应用于裁剪图像时,卷积特征图用零填充,而在密集评估的状况下,相同裁剪图像的填充天然会来自于图像的相邻部分(因为卷积和空间池化),这大大增长了整个网络的感觉野,所以捕获了更多的图像内容信息。
依照VGG的设计原则,只使用小尺寸的$3\times3$卷积核以及$2 \times 2$的池化单元,实现一个小型的网络模型。
class MiniVGGNet: @staticmethod def build(width,height,depth,classes): model = Sequential() inputShape = (height,width,depth) chanDim = -1 if K.image_data_format() == "channels_first": inputShape = (depth,height,width) chanDim = 1 model.add(Conv2D(32,(3,3),padding="same",input_shape=inputShape)) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(32,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Conv2D(64,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(64,(3,3),padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation("relu")) model.add(BatchNormalization()) model.add(Dropout(0.25)) model.add(Dense(classes)) model.add(Activation("softmax")) return model
最终输出10分类,应用于CIFAR10,表现以下: