引言
随着计算能力的提升和海量数据的积累,深度学习在计算机视觉领域取得了显著进展。2014 年,Google 团队提出了 GoogLeNet 模型,并在 ILSVRC-2014 中取得了冠军。该模型的创新设计不仅提升了准确率,还显著减少了计算资源的消耗。GoogLeNet吸收了NiN中串联网络的思想,并在此基础上做了改进。
1. GoogLeNet 简介
GoogLeNet 是一种深度卷积神经网络,包含 22 层,因其使用了一种名为 Inception
的模块而闻名。与传统的卷积网络不同,GoogLeNet 在提高准确性的同时有效降低了计算成本。
2. GoogLeNet 架构解析
GoogLeNet 的核心在于其 Inception 模块。每个模块通过并行的卷积操作来捕获不同尺度的特征。Inception 模块包含:
- 1x1 卷积:用于减少特征图的维度。
- 3x3 卷积:捕获中尺度特征。
- 5x5 卷积:捕获大尺度特征。
- 3x3 最大池化:通过池化操作保留关键信息。
通过堆叠多个 Inception 模块,GoogLeNet 能够在较深的网络中高效提取不同层次的特征。
2.1 Inception块
GoogLeNet中最重要的是Inception块,在这个块中抽取了不同的通道,不同的通道有不同的设计,如下图所示,Inception块通过四条路经从不同的层面抽取信息,然后在输出通道维合并: 前三条路径使用窗口大小为1 * 1、3 * 3、5 * 5的卷积层,从不同的空间大小中提取信息 中间两条路径在输入上执行1 * 1卷积,以减少通道数,从而降低模型的复杂性 第四条路经使用3 * 3最大汇聚层,然后使用1 * 1卷积层来改变通道数 四条路径都是用合适的填充来使输入和输出的高宽一致 最后每条线路的输出在通道维度上连结,得到Inception块的输出 在Inception块中,通常调整的超参数是每层输出通道数
① 白色的卷积用来改变通道数,蓝色的卷积用来抽取信息。
② 最左边一条1X1卷积是用来抽取通道信息,其他的3X3卷积用来抽取空间信息。
具体过程:
首先,输入被复制成了四块(之前所遇到的都是一条路直接到最后):
- 第一条路先进入一个1 *1的卷积层再输出
- 第二条路先通过一个1 * 1的卷积层对通道做变换,再通过一个pad为1的3 * 3的卷积层,使得输入和输出的高宽相同
- 第三条路先通过一个1 * 1的卷积层对通道数做变换,不改变高宽,但是再通过一个pad为2的5 * 5的卷积层提取空间信息特征,输入和输出还是等高等宽的
- 第四条路先通过一个pad为1的3 * 3的最大池化层,再通过一个1 * 1的卷积层 因为这四条路都没有改变高宽,最后用一个contact的操作将它们的输出合并起来(不是将四张图片放在一起形成一张更大的图片,而是在输出的通道数上做合并,最终的输出和输入等同高宽,但是输出的通道数更多,因为是四条路输出的通道数合并在一起的),因此,输出的高宽是不变的,改变的只有它的通道数
在这个结构中,基本上各种形状的卷积层和最大池化层等都有了,所以就不用过多地纠结于卷积层尺寸的选择
2.2 最好的卷积层超参数?
2.3 网络层次结构
GoogLeNet的整体结构如下:
- 输入层
- 9个Inception模块
- 全局平均池化层
- 全连接层
- Softmax输出层
GoogLeNet的总深度为22层,其中包括多个Inception模块和辅助分类器,辅助分类器的目的是增强梯度传播,帮助网络更快收敛。
3. 关键创新点
- Inception 模块: 通过并行路径设计,实现了多尺度的特征提取。
- 1x1 卷积: 用于维度减少和计算效率提升。
- 全局平均池化: 替代传统的全连接层,减少参数,防止过拟合。
4. GoogLeNet的优点
- 参数效率:通过1x1卷积减少参数数量,提高了模型的计算效率。
- 多尺度特征提取:不同大小的卷积核能够捕捉不同层次的特征,使得模型具有更强的表达能力。
- 深度与宽度:通过堆叠多个Inception模块,GoogLeNet在保持深度的同时,能够有效增加网络的宽度。
5. 实验与结果
在 ILSVRC-2014 中,GoogLeNet 以 6.67% 的 top-5 错误率赢得比赛,相比于传统模型,其参数量仅为 AlexNet 的 1/12,但精度更高。
6. 示例代码
接下来,我们将通过TensorFlow和Keras实现一个简单的GoogLeNet模型,用于图像分类任务。
6.1 数据准备
我们将使用CIFAR-10数据集作为示例数据集,该数据集包含10个类别的32x32彩色图像。
import tensorflow as tf
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.utils import to_categorical
# 加载CIFAR-10数据集
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
# 数据归一化
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# 类别标签转为one-hot编码
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
6.2 模型构建
下面是GoogLeNet模型的实现,包含Inception模块的定义。
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, AveragePooling2D, Flatten, Dense, Dropout, Concatenate
from tensorflow.keras.models import Model
def inception_module(x, filters):
# 1x1卷积
conv1x1 = Conv2D(filters[0], (1, 1), padding='same', activation='relu')(x)
# 1x1卷积 + 3x3卷积
conv3x3 = Conv2D(filters[1], (1, 1), padding='same', activation='relu')(x)
conv3x3 = Conv2D(filters[2], (3, 3), padding='same', activation='relu')(conv3x3)
# 1x1卷积 + 5x5卷积
conv5x5 = Conv2D(filters[3], (1, 1), padding='same', activation='relu')(x)
conv5x5 = Conv2D(filters[4], (5, 5), padding='same', activation='relu')(conv5x5)
# 3x3最大池化 + 1x1卷积
maxpool = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(x)
maxpool = Conv2D(filters[5], (1, 1), padding='same', activation='relu')(maxpool)
# 拼接所有卷积结果
return Concatenate(axis=-1)([conv1x1, conv3x3, conv5x5, maxpool])
# 构建GoogLeNet模型
def build_googlenet(input_shape=(32, 32, 3)):
inputs = Input(shape=input_shape)
# 初始卷积层
x = Conv2D(32, (3, 3), padding='same', activation='relu')(inputs)
x = Conv2D(32, (3, 3), padding='same', activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(64, (3, 3), padding='same', activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
# Inception模块
x = inception_module(x, [32, 32, 32, 16, 16, 32])
x = inception_module(x, [32, 32, 32, 16, 16, 32])
# 全局平均池化
x = AveragePooling2D(pool_size=(8, 8))(x)
x = Flatten()(x)
x = Dense(10, activation='softmax')(x)
return Model(inputs, x)
model = build_googlenet()
model.summary()
6.3 模型训练
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 训练模型
model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, batch_size=64)
6.4 评估模型
# 评估模型
test_loss, test_accuracy = model.evaluate(x_test, y_test)
print(f'Test Accuracy: {test_accuracy:.4f}')
7. 总结
GoogLeNet 的成功在于其创新的架构设计,通过 Inception
模块实现了计算效率与模型性能的平衡。它引领了深度神经网络的发展方向,影响了后续一系列网络架构的设计。
参考: 含并行连结的网络(GoogLeNet)