一、概述
GoogleNet是2014年Google发布的深度神经网络,在ImageNet图像识别任务中表现优异。它是Inception系列模型的第一代,以其高效的参数和计算量成为当时最先进的模型。
GoogleNet并不是一般CNN的平铺式层次,而是通过并行的Inception模块十分复杂地组成。Inception模块通过采用1x1、3x3、5x5的卷积核,从不同感受野大小的采样中得到不同网络层的特征表达,通过concatenate
将特征图并串起来,从而获得更好的特征表达能力。
二、Inception模块
Inception模块最核心的思想是并行计算。在不同大小感受野下通过不同大小的卷积核得到的特征图,然后通过concatenate
并表达出完整的特征图,从而获得更高维的特征信息。
示例代码如下:
from keras.layers import Conv2D, MaxPooling2D, concatenate
def InceptionModule(x, nb_filter):
branch1x1 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch3x3 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch3x3 = Conv2D(nb_filter, (3, 3), padding='same', activation='relu')(branch3x3)
branch5x5 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch5x5 = Conv2D(nb_filter, (5, 5), padding='same', activation='relu')(branch5x5)
branch_MaxPooling = MaxPooling2D(pool_size=(3, 3), strides=(1, 1), padding='same')(x)
branch_MaxPooling = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(branch_MaxPooling)
branches = [branch1x1, branch3x3, branch5x5, branch_MaxPooling]
out = concatenate(branches, axis=-1)
return out
三、完整模型架构
GoogleNet共22层,前15层采用常规的卷积、池化和归一化层。其后的分类层采用了全局平均池化、dropout和softmax,使得提取的特征图更具鲁棒性。完整模型代码如下:
from keras.layers import Input, Dense, Dropout, Flatten, concatenate
from keras.layers.convolutional import Conv2D, MaxPooling2D, AveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Model
def InceptionModule(x, nb_filter):
branch1x1 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch3x3 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch3x3 = Conv2D(nb_filter, (3, 3), padding='same', activation='relu')(branch3x3)
branch5x5 = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(x)
branch5x5 = Conv2D(nb_filter, (5, 5), padding='same', activation='relu')(branch5x5)
branch_MaxPooling = MaxPooling2D(pool_size=(3, 3), strides=(1, 1), padding='same')(x)
branch_MaxPooling = Conv2D(nb_filter, (1, 1), padding='same', activation='relu')(branch_MaxPooling)
branches = [branch1x1, branch3x3, branch5x5, branch_MaxPooling]
out = concatenate(branches, axis=-1)
return out
inputs = Input(shape=(224, 224, 3))
x = Conv2D(64, (7, 7), strides=(2, 2), padding='same', activation='relu')(inputs)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
x = Conv2D(64, (1, 1), strides=(1, 1), padding='same', activation='relu')(x)
x = Conv2D(192, (3, 3), strides=(1, 1), padding='same', activation='relu')(x)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
x = InceptionModule(x, 64)
x = InceptionModule(x, 120)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
x = InceptionModule(x, 128)
x = InceptionModule(x, 128)
x = InceptionModule(x, 128)
x = InceptionModule(x, 132)
x = InceptionModule(x, 208)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
x = InceptionModule(x, 208)
x = InceptionModule(x, 256)
x = AveragePooling2D(pool_size=(7, 7), strides=(7, 7), padding='same')(x)
x = Dropout(0.4)(x)
x = Flatten()(x)
outputs = Dense(1000, activation='softmax')(x)
model = Model(inputs=inputs, outputs=outputs)
四、转移学习
在实际应用中,考虑到数据量和算力的问题,可通过利用已有训练好的模型进行微调,即转移学习。将已有模型的前N层冻结,只对模型后面几层进行微调,加速模型训练过程,提高模型准确率。代码如下:
from keras.applications.inception_v3 import InceptionV3
from keras.layers import Dense, GlobalAveragePooling2D
from keras.models import Model
from keras import backend as K
K.clear_session()
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(299, 299, 3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(1000, activation='softmax')(x)
# 冻结前面249层,只训练后面的层
for layer in base_model.layers[:249]:
layer.trainable = False
model = Model(inputs=base_model.input, outputs=predictions)
五、优化和预处理
在训练GoogleNet时,常用的优化器为SGD(随机梯度下降),使得模型参数更好的收敛。在预处理方面,ImageNet中的图像分为ILSVRC2014-train和ILSVRC2014-val两个数据集。在训练时,对于ILSVRC2014-train数据集中的图像,进行数据增强,如左右翻转、随机裁剪等预处理方式,以增强模型的鲁棒性和泛化能力。在预测时,对于图像进行中心化和大小正则化处理。
六、总结
GoogleNet以其高效的模型架构和并行计算Inception模块的特点,被广泛应用在图像识别领域。在实际应用中,通过微调已有的训练好的模型,可以有效提高模型的准确率和加速训练过程。