VGG16 -19 — CV 中表现最好的 ConvNet 模型

从先进的计算机视觉出现的 Alexnet 开始,人们开始尝试不同的架构。牛津大学工程科学系的 Karen simonyan 和 Andrew Zisserman 在对 ImageNet Challenge 2014 的数据集进行了一些实验后提出了非常深的卷积网络:VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION

引言

VGG16 是一种 CNN(卷积神经网络),被认为是迄今为止最好的计算机视觉模型之一。该模型的创建者评估了网络结构并使用具有非常小 (3 × 3) 卷积滤波器的架构增加了深度,这显示出对现有技术配置的显著改进。他们将深度推到了 16-19 个权重层,使其大约有“1.38 亿”个可训练参数。VGG16 可用于目标检测和分类,能够对 1000 个不同类别的图像进行分类,且易于与迁移学习搭配使用。

VGG-16 的架构

834f51cd0deb6acc94201babcf7b7842.png

  • VGG16中的16指的是有16的带权重的层。在 VGG16 中有 13 个卷积层、5 个 Max Pooling 层和 3 个 Dense 层,总计 21 个层,但它只有 16 层有权重,即可学习参数层。

  • VGG16 将输入图像大小设置为 224、244 和 3 个 RGB 通道

  • VGG16 最独特的地方在于,他们没有使用大量的超参数,而是专注于具有非常小尺寸(stride 为 1 - 3*3 滤波器)的卷积层,并且始终使用stride 为2 - 2*2 滤波器进行“SAME”填充和最大池化操作。

  • Conv-1 层有 64 个滤波器,Conv-2 有 128 个滤波器,Conv-3 有 256 个滤波器,Conv 4 和 Conv 5 有 512 个滤波器。

  • 三个全连接 (FC) 层跟在一堆卷积层之后:前两个层各有 4096 个通道;第三个执行 1000 个 ILSVRC 类别分类,因此包含 1000 个通道(每个类一个);最后一层是 softmax 层。

  • 在每一层之后,他们添加了 ReLU 激活函数,该函数“负责”避免梯度消失,因为它不会同时激活所有神经元。

原始研究论文中的表格

随着更多层的添加(添加的层以粗体显示),配置的深度从左 (A) 到右 (E) 增加。卷积层参数表示为“convhreceptive field sizei-hnumber of channelsi”。为简洁起见,未写出 ReLU 激活函数。

8458678a51d5e13a208b62022d17a96a.png

24f84e9638ac56a49362e8d54aaa4b6e.png

参数数量(百万)

下面是我在 FER 2013 数据集上基于 VGG-16 的项目 ——“面部情绪检测”,输入图像的大小为 48*48*1 ,将其分类为 7 类(情绪)。

def FER_vgg16_model(input_shape=(48, 48, 1)):
   visible = Input(shape=input_shape, name='input')
   num_classes = 7


   # 1stblock with 2 conv
   conv1_1 = Conv2D(64, kernel_size=3, activation='relu',          padding='same', name='conv1_1')(visible)
   conv1_1 = BatchNormalization()(conv1_1)
   conv1_2 = Conv2D(64, kernel_size=3, activation='relu', padding='same', name='conv1_2')(conv1_1)
   conv1_2 = BatchNormalization()(conv1_2)
   pool1_1 = MaxPooling2D(pool_size=(2, 2), name='pool1_1')(conv1_2)
   drop1_1 = Dropout(0.3, name='drop1_1')(pool1_1)


   # the 2-nd block with 2 conv
   conv2_1 = Conv2D(128, kernel_size=3, activation='relu', padding='same', name='conv2_1')(drop1_1)
   conv2_1 = BatchNormalization()(conv2_1)
   conv2_2 = Conv2D(128, kernel_size=3, activation='relu', padding='same', name='conv2_2')(conv2_1)
   conv2_2 = BatchNormalization()(conv2_2)
   pool2_1 = MaxPooling2D(pool_size=(2, 2), name='pool2_1')(conv2_2)
   drop2_1 = Dropout(0.3, name='drop2_1')(pool2_1)


   # the 3-rd block with 3 conv
   conv3_1 = Conv2D(256, kernel_size=3, activation='relu', padding='same', name='conv3_1')(drop2_1)
   conv3_1 = BatchNormalization()(conv3_1)
   conv3_2 = Conv2D(256, kernel_size=3, activation='relu', padding='same', name='conv3_2')(conv3_1)
   conv3_2 = BatchNormalization()(conv3_2)
   conv3_3 = Conv2D(256, kernel_size=3, activation='relu', padding='same', name='conv3_3')(conv3_2)
   conv3_3 = BatchNormalization()(conv3_3)
   pool3_1 = MaxPooling2D(pool_size=(2, 2), name='pool3_1')(conv3_3)
   drop3_1 = Dropout(0.3, name='drop3_1')(pool3_1)


   # the 4-rd block with 3 conv
   conv4_1 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv4_1')(drop3_1)
   conv4_1 = BatchNormalization()(conv4_1)
   conv4_2 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv4_2')(conv4_1)
   conv4_2 = BatchNormalization()(conv4_2)
   conv4_3 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv4_3')(conv4_2)
   conv4_3 = BatchNormalization()(conv4_3)
   pool4_1 = MaxPooling2D(pool_size=(2, 2), name='pool4_1')(conv4_3)
   drop4_1 = Dropout(0.2, name='drop4_1')(pool4_1)


   # the 5-rd block with 3 conv
   conv5_1 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv5_1')(drop4_1)
   conv5_1 = BatchNormalization()(conv5_1)
   conv5_2 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv5_2')(conv5_1)
   conv5_2 = BatchNormalization()(conv5_2)
   conv5_3 = Conv2D(512, kernel_size=3, activation='relu', padding='same', name='conv5_3')(conv5_2)
   conv5_3 = BatchNormalization()(conv5_3)
   pool5_1 = MaxPooling2D(pool_size=(2, 2), name='pool5_1')(conv5_3)
   drop5_1 = Dropout(0.2, name='drop5_1')(pool5_1)


   # Flatten and output
   flatten = Flatten(name='flatten')(drop5_1)
   FC1 = Dense(4096, activation="relu", name='FullyConnected1')(flatten)
   drop6_1 = Dropout(0.1, name = 'drop6_1')(FC1)
   FC2 = Dense(4096, activation="relu", name='FullyConnected2')(drop6_1)
   drop7_1 = Dropout(0.1, name='drop7_1')(FC2)
   FC3 = Dense(1000, activation="relu", name='FullyConnected3')(drop7_1)
   drop8_1 = Dropout(0.1, name='drop8_1')(FC3)
   ouput = Dense(num_classes, activation='softmax', name='output')(drop8_1)


   # create model
   model = Model(inputs=visible, outputs=ouput)


   return model

对于每个卷积层:

Filter = 3*3

Stride = 1

Padding = same

对于每个最大池化层:

Filter = 2*2

Stride= 2

Alexnet 存在的问题

它的层数较少,因此无法提取比较深层的特征。此外,他们在每一层中选择固定滤波器的数目和步幅进行卷积和池化操作。

VGG-16 相对于 Alexnet 的优势

  • 在每个卷积层中,滤波器的 size 为 3*3,stride为 1,使用“same”的方式进行填充,最大池化层的 size 为2*2,stride 为2。

  • 由于 VGG-16 是相对比较深层的神经网络,它将从图像中提取更多特征,而且梯度消失的问题在 ReLU 激活函数的加入后得到了有效的解决。

  • VGG-16 是一个“系统的”神经网络,它具有相同的步长和滤波器,每个模块独立地进行卷积和池化操作。

  • vgg-16 和 vgg-19 之间的区别是 vgg-19 多了 3 个卷积层,这使得它的性能比 vgg16 好一些。

·  END  ·

HAPPY LIFE

af5887c48c602bd533c21c5aec1101d1.png

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇
下一篇>>