ResNet(Residual Network)是微软研究院在2015年提出的一种深度卷积神经网络架构,它在2015年的ImageNet竞赛中取得了优异的成绩。ResNet的关键创新是引入了残差学习(Residual Learning)机制,使得网络能够更深,并且训练变得更加容易。
ResNet 的关键特点
-
残差学习(Residual Learning)
- 残差块(Residual Block):ResNet 的核心思想是通过引入残差连接(skip connections)来解决深度网络训练中的梯度消失和退化问题。每个残差块通过一个恒等映射将输入直接传递到块的输出,这样可以避免深层网络训练时的性能下降。
- 公式:在传统卷积神经网络中,输出 ( H(x) ) 由卷积操作计算;而在 ResNet 中,网络的输出 ( F(x) ) 实际上是通过 ( F(x) + x ) 计算的,其中 ( F(x) ) 是残差学习的部分。
-
深度网络
- ResNet 的设计使得网络可以非常深,比如常见的 ResNet-18、ResNet-34、ResNet-50、ResNet-101、ResNet-152,甚至更深。尽管网络很深,但通过残差学习的方式,训练过程和性能得到了有效保障。
-
瓶颈结构
- 瓶颈层:在更深的 ResNet 版本中(如 ResNet-50 及更深的网络),使用了瓶颈结构,即先通过 1x1 卷积降低通道数,再使用 3x3 卷积进行特征提取,最后通过 1x1 卷积恢复通道数。这样的设计可以减少计算量和参数量。
-
网络结构
- ResNet 通常由多个残差块堆叠而成,这些块通过跨层连接(skip connections)进行连接。不同的 ResNet 变种(如 ResNet-18、ResNet-34、ResNet-50)在残差块的数量和具体结构上有所不同。
ResNet 的结构
以下是 ResNet 的简化结构示意图:
-
输入层
- 输入图像尺寸为 224x224x3。
-
初始卷积层
- 使用 7x7 卷积,步幅为 2,后跟 3x3 最大池化层。
-
残差块(Residual Blocks)
- 一系列的残差块堆叠,如:
- Stage 1: 具有多个残差块。
- Stage 2: 具有多个残差块,通道数增加,步幅为 2 的卷积层进行下采样。
- Stage 3: 更深的残差块层,进一步增加通道数。
- Stage 4: 最深的残差块层。
- 一系列的残差块堆叠,如:
-
全局平均池化
- 用于减少特征图的维度,并生成最终的分类特征。
-
输出层
- 使用 Softmax 激活函数进行分类。
ResNet 实现示例(使用 TensorFlow/Keras)
以下是使用 TensorFlow/Keras 实现 ResNet-50 的示例代码:
import tensorflow as tf
from tensorflow.keras import layers, models
def residual_block(x, filters, kernel_size=3, stride=1):
# Shortcut
shortcut = x
# First convolution
x = layers.Conv2D(filters, kernel_size=kernel_size, strides=stride, padding='same', activation='relu')(x)
x = layers.BatchNormalization()(x)
# Second convolution
x = layers.Conv2D(filters, kernel_size=kernel_size, strides=stride, padding='same')(x)
x = layers.BatchNormalization()(x)
# Add shortcut to the output
x = layers.add([x, shortcut])
x = layers.Activation('relu')(x)
return x
def resnet50(input_shape, num_classes):
input_layer = layers.Input(shape=input_shape)
# Initial Conv Layer
x = layers.Conv2D(64, (7, 7), strides=(2, 2), padding='same', activation='relu')(input_layer)
x = layers.BatchNormalization()(x)
x = layers.MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
# Residual Blocks
for filters in [64, 128, 256, 512]:
x = residual_block(x, filters)
x = residual_block(x, filters)
x = residual_block(x, filters)
# Global Average Pooling
x = layers.GlobalAveragePooling2D()(x)
# Output Layer
output_layer = layers.Dense(num_classes, activation='softmax')(x)
# Create Model
model = models.Model(inputs=input_layer, outputs=output_layer)
return model
# Create and compile model
model = resnet50(input_shape=(224, 224, 3), num_classes=1000) # 假设有 1000 个类别
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 打印模型概况
model.summary()
总结
ResNet 的引入通过残差学习解决了深度神经网络训练中的梯度消失问题,使得深度网络训练变得更加可行。它的残差块设计不仅提高了训练效果,还大幅度提高了模型的性能。ResNet 是一种高效的网络架构,被广泛应用于计算机视觉任务。