文章目录
- 一、Inception Network简介
- 二、CNN的痛点
- 三、Inception Network
- 1. 1x1卷积核
- 1.1 升维/降维:
- 1.2. 调节参数数量:
- 1.3. 增加非线性特性:
- 2. Inception原始模型
- 3. Inception Module
- 4. Inception Network
- 四、代码示例
一、Inception Network简介
Inception Network又称GoogleNet,是2014年Christian Szegedy提出的一种全新的深度学习结构,并在当年的ILSVRC比赛中获得第一名的成绩。相比于传统CNN模型通过不断增加神经网络的深度来提升训练表现,Inception Network另辟蹊径,通过Inception model的设计和运用,在有限的网络深度下,大大提高了模型的训练速度(即减少了训练参数)和准确率,是一个CNN历史上里程碑式的进步。
二、CNN的痛点
在Inception Network出现之前,很多CNN模型(如VGG等)在图像识别上都取得了令人惊叹的成果,但是他们都面临着共同的痛点:
1. 由于模型深度过大,导致计算量飙升,对算力的需求近乎无限增加;
2. 过深的神经网络容易产生过拟合;
3. 由于图像信息的多样性,合适的卷积核大小的选择变得更加困难(不同大小的卷积核感受野不同,提取的图像信息侧重点不同);
为了解决以上问题,Inception Network的设计者对“过滤器使用固定大小卷积核”提出了质疑,并给出“要更宽,而不是更深(wider rather than deeper)”的思路(即过滤器使用多个大小不同的卷积核),为CNN的设计提供了一种更好的方案。
三、Inception Network
1. 1x1卷积核
1x1卷积核是CNN网络中常见的组成部分,它的主要作用有如下三点:
1.1 升维/降维:
1x1的卷积核由于大小只有1x1,所以并不需要考虑像素跟周边像素的关系,它主要用于调节通道数,对不同的通道上的像素点进行线性组合,然后进行非线性化计算,可以完成升维和降维的功能,如下图所示,输入的WHD特征图矩阵与1个1x1大小的卷积核卷积后,输出的特征图的深度(通道数)将会从D变成1,从而实现了降维的作用。而升维只需要增加卷积核的数量即可,原理相同。
1.2. 调节参数数量:
前面所说的降维,其实也是减少了参数,因为特征图的通道数小了,参数也自然跟着就减少,相当于在特征图的通道数上进行卷积,压缩特征图,二次提取特征,使得新特征图的特征表达更佳。
&esmp;&esmp;如下图,28x28x192的输入特征图,与32个5x5的卷积核做卷积计算,产生24x24x32的输出,此过程涉及的计算量为28x28x32x(5x5x192)=120.422 million ops。
而经过1x1卷积核降维后,整个过程分成了两步,第一步的计算量是28x28x16x(1x1x192)=2.4 million ops。第二部的计算量是28x28x32x(5x5x16)=10 million ops。
合计12.4 million ops。可见经过1x1卷积核降维后,神经网络的计算量大大降低,即需要训练的参数量大幅度减少(同时一定程度上减少了过拟合)。
1.3. 增加非线性特性:
使用1x1卷积核的网络更深,而每一层网络后都会用Relu激活函数做计算,这样就增加了一层非线性特征。
2. Inception原始模型
为了验证“wider rather than deeper”的理论,Inception network的作者设计了如下Inception原始模型。
我们都知道不同大小的卷积核具有不同的感受野,在输入特征图上用 3 个不同的卷积核(1x1,3x3,5x5)实施卷积操作,相当于同时提取了不同的尺度的特征,冗余信息更少,训练效率更高。最后执行了最大池化操作(max pooling),被连接(concatenated)后,送往下一层 inception 模块。
3. Inception Module
然而在Inception原始模型中,由于3x3和5x5的卷积核涉及的参数量过大,计算代价过于昂贵,作者便充分利用了1x1卷积核的特性,在过大的卷积核之前增加1x1卷积核,大幅减少了参数数量,提高了训练效率,这就是Inception Module,如下图。
4. Inception Network
利用上述Inception module,一个22层的神经网络被构建完成,如下图,这就是Inception Network V1。
Inception Network线性堆叠了 9 个Inception Module,它有 22 层深(如果包括池化层,则为 27 层),在最后它使用了全局平均池化操作。
注意这里除了Inception Module外,还多了几个分支。所以这些分支有什么用呢?在网络的最后几层,通常是全连接层然后softmax来做出预测。图中分支就是通过隐藏层来做出预测,所以其实是一个softmax输出,它确保了即便是隐藏单元和中间层也参与了特征计算和图片分类,起到一种调整的效果并且防止网络发生过拟合。
四、代码示例
下面是基于Inception V3的transfer learning模型构建代码:
# 下载已训练好的模型weights
weights_url = "https://storage.googleapis.com/mledu-datasets/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5"
weights_file = "inception_v3.h5"
urllib.request.urlretrieve(weights_url, weights_file)
# 加载InceptionV3 from tensorflow.keras.applications.inception_v3 import InceptionV3
# 其中include_top表示顶部Flatten和Dense层,FALSE为不加载这部分
pre_trained_model = InceptionV3(input_shape=(150, 150, 3),
include_top=False,
weights=None)
# 加载weights
pre_trained_model.load_weights(weights_file)
# 冻结所有layers
for layer in pre_trained_model.layers:
layer.trainable = False
# pre_trained_model.summary()
last_layer = pre_trained_model.get_layer('mixed7')
last_output = last_layer.output
# 将Inception的输出传入自定义的layer,用于处理自定义的分类
x = layers.Flatten()(last_output)
x = layers.Dense(1024, activation='relu')(x)
# 二分类
x = layers.Dense(1, activation='sigmoid')(x)
# 模型定义
model = Model(pre_trained_model.input, x)
# 编译
model.compile(optimizer=RMSprop(lr=0.0001),
loss='binary_crossentropy',
metrics=['acc'])
# 训练
history = model.fit(
train_generator,
validation_data=validation_generator,
epochs=2,
verbose=1)
注:Keras的ImageDataGenerator提供了强大的图片处理能力,用法如下:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
TRAINING_DIR = "/tmp/cats-v-dogs/training/"
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
train_generator = train_datagen.flow_from_directory(TRAINING_DIR,
batch_size=100,
class_mode='binary',
target_size=(150, 150))
VALIDATION_DIR = "/tmp/cats-v-dogs/testing/"
validation_datagen = ImageDataGenerator(rescale=1./255)
validation_generator = validation_datagen.flow_from_directory(VALIDATION_DIR,
batch_size=100,
class_mode='binary',
target_size=(150, 150))