对于许多刚开始接触深度学习的人来说,残差网络(ResNet)可能看起来既庞大又复杂,但一旦理解了其背后的核心概念,就能发挥出巨大的潜力。本文将探讨以下内容:
ResNet,即残差网络,是一种特殊的卷积神经网络(CNN),用于图像识别等任务。ResNet最初由Kaiming He等人在2015年提出,并在他们的论文《Deep Residual Learning for Image Recognition》中进行了详细阐述。
基于网络深度的不同,可以开发出不同类型的ResNet,如ResNet-50或ResNet-152。ResNet后面的数字表示网络的层数或深度。可以使用ResNet的基本构建块设计出任意深度的ResNet。
ResNet可以看作是VGG架构的升级版,两者的主要区别在于ResNet中使用了跳跃连接(skip connections)。下图展示了VGG和34层ResNet的架构。
在早期的CNN架构中,随着网络层数的增加,模型性能开始下降,这是因为梯度消失问题。跳跃连接的引入解决了这一问题,允许构建更深的网络而不受梯度消失的影响。
下图展示了跳跃连接的工作原理,它跳过某些层的训练,直接将输出连接到网络的更深层。
恒等块和卷积块是ResNet中的两种基本块。恒等块直接将残差添加到输出,而卷积块在添加残差之前先对残差进行卷积和批量归一化处理。
恒等块的结构如下:
X_skip = 输入
卷积层(3X3)(Padding='same') (Filters = f) →(输入)
批量归一化 →(输入)
ReLU激活 →(输入)
卷积层(3X3)(Padding = 'same') (Filters = f) →(输入)
批量归一化 →(输入)
添加残差(输入 + X_skip)
ReLU激活
使用'same'作为所有卷积层的填充方式,以保持输入的形状,直到将其添加到残差。
卷积块的结构如下:
X_skip = 输入
卷积层(3X3)(Strides = 2) (Filters = f) (Padding = 'same') →(输入)
批量归一化 →(输入)
ReLU激活 →(输入)
卷积层(3X3)(Filters = f) (Padding = 'same') →(输入)
批量归一化 →(输入)
卷积层(1X1)(Filters = f) (Strides = 2) →(X_skip)
添加残差(输入 + X_skip)
ReLU激活
def ResNet34(shape = (32, 32, 3), classes = 10):
# 输入层设置
x_input = tf.keras.layers.Input(shape)
# 初始卷积层和最大池化层
x = tf.keras.layers.Conv2D(64, kernel_size=7, strides=2, padding='same')(x_input)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Activation('relu')(x)
x = tf.keras.layers.MaxPool2D(pool_size=3, strides=2, padding='same')(x)
# 定义子块的大小和初始过滤器大小
block_layers = [3, 4, 6, 3]
filter_size = 64
# 添加ResNet块
for i in range(4):
if i == 0:
for j in range(block_layers[i]):
x = identity_block(x, filter_size)
else:
filter_size = filter_size*2
x = convolutional_block(x, filter_size)
for j in range(block_layers[i] - 1):
x = identity_block(x, filter_size)
# 网络末端
x = tf.keras.layers.AveragePooling2D((2,2), padding = 'same')(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(512, activation = 'relu')(x)
x = tf.keras.layers.Dense(classes, activation = 'softmax')(x)
model = tf.keras.models.Model(inputs = x_input, outputs = x, name = "ResNet34")
return model