您的位置:

ResNet原文详解

一、ResNet论文

ResNet是由何凯明等人于2015年提出的深度残差网络。在深度学习研究中,神经网络的数量一般为几层到十几层,增加网络深度可以提高网络识别能力,但同时网络也容易出现梯度消失问题,训练网络变得困难。ResNet通过加入残差模块,使得网络在进行浅层学习的同时,能够以更快的速度学习更深层的信息,提高了网络的识别能力。

这篇论文提出的ResNet模型完全由卷积神经网络组成,没有任何全连接层。除了池化操作和卷积层之外,每个残差模块中均包含两层卷积层,并对输入信号做一个恒等映射,将其与输出信号相加,得到残差项。模型最后通过全局池化和softmax分类器得到预测结果。

二、ResNet模型

ResNet在原论文中提出了两个模型:ResNet-18和ResNet-34,它们分别有18层和34层。2016年,何凯明等人提出的ResNet-101和ResNet-152更深,网络有101和152层。随着网络层数的加深,网络的性能得到了显著提升。

三、ResNet怎么读

ResNet的全称是“残差网络”(Residual Network),我们可以直接读作“residual network”,或者简写成“ResNet”,这两种读法都是可以的。

四、ResNet网络结构

在ResNet中,一个基本的残差块通常包含两个卷积层。假设输入信号是$x$,第一个卷积层在输出$x$之前将其转换为$F(x)$。第二个卷积层将$F(x)$转换为输出$H(x)$。残差块将$H(x)$和输入信号$x$相加,得到残差$R(x)$。即:

$$H(x) = F(x) + x$$
$$R(x) = H(x) - x = F(x)$$

如果残差项非常小,或者接近于0,那么同样可以通过将恒等映射作为残差项来提高网络性能。在ResNet中,每隔一段网络距离,会在其中增加一个附加层,即“shortcut connection”。

五、ResNet论文原文

ResNet论文原文可以在以下网址中获取:https://arxiv.org/pdf/1512.03385.pdf

六、ResNet发明人

ResNet的发明人为何凯明(Kaiming He)等人,他们是2016年ImageNet图像识别比赛的冠军小组,也是计算机视觉领域的知名学者之一。

七、ResNet论文详解

ResNet通过加入残差模块,较之一般网络,在网络深度增加的情况下使得网络顶部的准确率不再下降,尤其在超过100层的时候,相比于其他网络,ResNet的性能表现非常优异,而且训练时间也不会过长。具体来说,ResNet引入残差模块解决梯度消失问题,使用全局平均池化代替全连接层,减少模型参数等特点。

下面展示ResNet的一个代码实例:

import tensorflow as tf

# input tensor
inputs = tf.keras.Input(shape=(32, 32, 3))

# ResNet-18 network architecture
def res_block(inputs, filters, kernel_size, strides):
    x = tf.keras.layers.Conv2D(filters, kernel_size, strides=strides, padding='same')(inputs)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.layers.Activation('relu')(x)
    x = tf.keras.layers.Conv2D(filters, kernel_size, strides=1, padding='same')(x)
    x = tf.keras.layers.BatchNormalization()(x)
    shortcut = tf.keras.layers.Conv2D(filters, 1, strides=strides, padding='same')(inputs)
    shortcut = tf.keras.layers.BatchNormalization()(shortcut)
    x = tf.keras.layers.add([shortcut, x])
    output = tf.keras.layers.Activation('relu')(x)
    return output

x = tf.keras.layers.Conv2D(64, 3, strides=1, padding='same')(inputs)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Activation('relu')(x)

# ResNet Block1
x = res_block(x, filters=64, kernel_size=3, strides=1)
x = res_block(x, filters=64, kernel_size=3, strides=1)
x = res_block(x, filters=64, kernel_size=3, strides=1)

# ResNet Block2
x = res_block(x, filters=128, kernel_size=3, strides=2)
x = res_block(x, filters=128, kernel_size=3, strides=1)
x = res_block(x, filters=128, kernel_size=3, strides=1)

# ResNet Block3
x = res_block(x, filters=256, kernel_size=3, strides=2)
x = res_block(x, filters=256, kernel_size=3, strides=1)
x = res_block(x, filters=256, kernel_size=3, strides=1)

# ResNet Block4
x = res_block(x, filters=512, kernel_size=3, strides=2)
x = res_block(x, filters=512, kernel_size=3, strides=1)
x = res_block(x, filters=512, kernel_size=3, strides=1)

x = tf.keras.layers.GlobalAveragePooling2D()(x)
outputs = tf.keras.layers.Dense(10, activation='softmax')(x)

resnet = tf.keras.Model(inputs=inputs, outputs=outputs)
resnet.summary()