1. VGG 模型架构
VGG 由牛津大学视觉几何组(Visual Geometry Group)开发。包含两个版本:VGG16 和 VGG19,分别有16个层级和19个层级。本文只介绍 VGG16 。根据 arxiv.org 上公布的论文,VGG 的卷积核大小为 (3, 3),最大池化层核大小 (2, 2),隐藏层激活函数为 ReLu
, 输出层激活函数为 softmax
。如果我们能知道模型各层的输入输出 shape 及层叠顺序,就能使用 Keras 自己搭建一个 VGG 。幸运的是,我们不需要从晦涩难懂的论文中提炼出模型的这些参数细节,Keras 可以直接给到我们这个模型全部细节。
如下使用 Keras 直接创建一个 VGG16 模型,并加载在 ImageNet 上训练好的权重:
from keras.applications.vgg16 import VGG16
VGG16_model = VGG16(weights='imagenet')
Using TensorFlow backend.
既然这是一个 Keras 模型,是不是和自己搭建的模型一样可以使用 summary()
方法一览模型的架构呢?答案是可以的。
VGG16_model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________
有了以上信息,我们已经具备手动构建一个 VGG16 模型所有信息。SO,撸起袖子,说干咱就干!
2. 从零构建 VGG16
本文使用 Keras 函数式 API 构建,当然也可以使用序列化模型,读者可以自己尝试。
2.1 导入 Keras 模型和层
从上文打印出来的模型架构,可以看到,VGG16 用到了卷积层(Conv2D), 最大池化层(MaxPooling2D), 扁平层(Flatten), 全联接层(Dense)。因此,我们从 keras.layers 中导入这些层。
from keras.models import Model
from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense
2.2 设计模型层
VGG16 包含了 13 个卷积层,3个全连接层(最后1个是输出层),一共16个有参数的层,这也是 VGG16 中 16 的含义。当然还有 5 个最大池化层和 1 个扁平层,而这些层是没有参数或者权重的,因此,VGG 不把这些层计入总层数。
# 输入层
inputs = Input(shape=(224, 224, 3))
# 卷积层和最大池化层
conv1 = Conv2D