ResNet简介
残差网络结构
残差网络(ResNet)是由何凯明等人在2015年提出的,它极大地提高了深度神经网络的训练效果,尤其是非常深的网络。ResNet的核心思想是引入“残差块”(Residual Block),通过跳跃连接(Shortcut Connection)解决深层网络的梯度消失和梯度爆炸问题。
结构示意图:
- 输入层
- 一系列的卷积层(Conv Layers)
- 残差块(Residual Blocks)
- 全连接层(Fully Connected Layer)
- 输出层
在传统的卷积神经网络中,每一层都会对输入的特征进行某种变换,比如卷积操作,然后直接输出这些变换后的结果到下一层。可以把这种变换看作是对输入进行处理和提取新的特征。
y l = F l ( x l ) \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) yl=Fl(xl)
而ResNet通过增加一条跳跃连接,使得每个残差块输出的是“变换后的特征+原始输入特征”,即:
y = F ( x , { W i } ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x} y=F(x,{Wi})+x
其中, F ( x , { W i } ) \mathcal{F}(\mathbf{x}, \{W_i\}) F(x,{Wi}) 表示通过多层卷积、激活等操作后的特征, x \mathbf{x} x 表示原始输入特征。
什么是跳跃连接?
跳跃连接(Shortcut Connection),又称为“短路连接”或“直连”,是一种直接将输入信号传递到输出信号的技术。具体来说,就是在每个残差块中,除了正常的变换路径外,还增加了一条直接连接输入和输出的路径。
为什么要使用跳跃连接?
在深层网络中,随着层数的增加,梯度可能会逐渐消失或者爆炸,这会导致网络很难训练。而跳跃连接的引入可以缓解这个问题,因为它允许梯度直接传递到前面的层,确保梯度不会消失。
跳跃连接如何缓解梯度消失和梯度爆炸问题
为了理解跳跃连接如何缓解梯度消失和梯度爆炸问题,我们需要从反向传播(Backpropagation)的角度分析梯度传递过程。
在传统的深层网络中,假设某一层的输入是 x l \mathbf{x}_l xl ,输出是 y l \mathbf{y}_l yl 。每层的变换函数记为 F l \mathcal{F}_l Fl,那么:
y l = F l ( x l ) \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) yl=Fl(xl)
而在ResNet中,增加了跳跃连接后,输出变为:
y l = F l ( x l ) + x l \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) + \mathbf{x}_l yl=Fl(xl)+xl
在反向传播中,我们需要计算每层的梯度。对于传统的深层网络,第 l l l 层的梯度计算如下:
∂ L ∂ x l = ∂ L ∂ y l ⋅ ∂ y l ∂ x l = ∂ L ∂ y l ⋅ ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{L}}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \frac{\partial \mathbf{y}_l}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} ∂xl∂L=∂yl∂L⋅∂xl∂yl=∂yl∂L⋅∂xl∂Fl(xl)
而在ResNet中,由于增加了跳跃连接,梯度的计算变为:
∂ L ∂ x l = ∂ L ∂ y l ⋅ ( ∂ F l ( x l ) ∂ x l + I ) \frac{\partial \mathcal{L}}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \left( \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} + \mathbf{I} \right) ∂xl∂L=∂yl∂L⋅(∂xl∂Fl(xl)+I)
这里, I \mathbf{I} I 是单位矩阵,表示跳跃连接的梯度。
梯度分析
在ResNet中,由于跳跃连接的存在,梯度不仅传递了变换部分( ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} ∂xl∂Fl(xl) ),还传递了输入部分( I \mathbf{I} I ),这意味着即使在深层网络中,梯度也能有效地通过跳跃连接传递到前面的层,而不会完全依赖于 ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} ∂xl∂Fl(xl) 。
具体来说,如果 ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} ∂xl∂Fl(xl) 在深层网络中趋近于0(梯度消失)或趋近于无穷大(梯度爆炸),跳跃连接的单位矩阵 I \mathbf{I} I 确保了梯度至少能通过 I \mathbf{I} I 进行传递,缓解了梯度消失或爆炸的问题。
总结
- 跳跃连接的引入:在每个残差块中,除了对输入特征进行卷积、归一化和激活等操作外,还增加了一条直接传递输入特征到输出的路径。
- 公式中的体现:输出特征不仅包含变换后的特征,还加上了输入特征,即 y = F ( x ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x} y=F(x)+x 。
- 缓解梯度问题:跳跃连接确保了梯度在反向传播过程中,即使变换部分的梯度消失或爆炸,输入特征的梯度(\mathbf{I})也能直接传递,避免梯度完全消失或爆炸。
残差块的组成及功能
残差块是ResNet的基本单元,每个残差块中包含了两个主要部分:
- 变换路径:对输入进行卷积、批量归一化和激活操作。
- 跳跃连接(Shortcut Connection):直接将输入传递到输出,不进行任何变换,只是将输入特征原样添加到经过变换后的特征上。
详细组成:
- 卷积层(Convolutional Layer):提取特征。
- 批量归一化层(Batch Normalization Layer):加速训练,稳定输入。
- ReLU激活函数(ReLU Activation Function):引入非线性,提高网络表达能力。
- 跳跃连接(Shortcut Connection):将输入直接加到输出上。
具体的操作流程如下:
- 输入特征 x \mathbf{x} x 通过卷积层和批量归一化层,得到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 。
- 变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 与输入特征 x \mathbf{x} x 相加,得到输出特征 y \mathbf{y} y:
y = F ( x , { W i } ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x} y=F(x,{Wi})+x
这里, x \mathbf{x} x 直接通过跳跃连接加到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 上。
- 输出特征 y \mathbf{y} y 再经过ReLU激活函数:
y = ReLU ( y ) \mathbf{y} = \text{ReLU}(\mathbf{y}) y=ReLU(y)
这种设计可以确保即使在深层网络中,梯度也能有效传播,避免梯度消失或爆炸。
ResNet的输出计算
在ResNet中,每一层的输出不仅仅取决于当前层的输入,还包括了前面层的输入,这种设计使得网络能够更有效地学习。
详细的数学推导:
假设一个简单的ResNet包含L个残差块,每个残差块输出为 y l \mathbf{y}_l yl ,输入为 x l \mathbf{x}_l xl ,则有:
y l = F l ( x l ) + x l \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) + \mathbf{x}_l yl=Fl(xl)+xl
其中 F l ( x l ) \mathcal{F}_l(\mathbf{x}_l) Fl(xl) 表示第l个残差块中的变换函数(例如两层卷积和ReLU激活函数)。
整个网络的输入为 x 0 \mathbf{x}_0 x0 ,输出为 y L \mathbf{y}_L yL,即:
y L = F L ( y L − 1 ) + y L − 1 \mathbf{y}_L = \mathcal{F}_L(\mathbf{y}_{L-1}) + \mathbf{y}_{L-1} yL=FL(yL−1)+yL−1
y L − 1 = F L − 1 ( y L − 2 ) + y L − 2 \mathbf{y}_{L-1} = \mathcal{F}_{L-1}(\mathbf{y}_{L-2}) + \mathbf{y}_{L-2} yL−1=FL−1(yL−2)+yL−2
⋮ \vdots ⋮
y 1 = F 1 ( x 0 ) + x 0 \mathbf{y}_1 = \mathcal{F}_1(\mathbf{x}_0) + \mathbf{x}_0 y1=F1(x0)+x0
逐层递推,我们可以得到最终的输出:
y L = x 0 + ∑ l = 1 L F l ( x l ) \mathbf{y}_L = \mathbf{x}_0 + \sum_{l=1}^{L} \mathcal{F}_l(\mathbf{x}_l) yL=x0+l=1∑LFl(xl)
这种设计可以看作是对输入的逐层增强,每层不仅仅是对输入的简单变换,更是对前面所有层次特征的累积。
总结
- 残差网络结构:ResNet引入了残差块,每个残差块中有一条跳跃连接直接将输入加到输出上,这样即使网络很深,信息也能有效传递。
- 残差块的组成及功能:每个残差块由卷积、批量归一化、ReLU激活和跳跃连接组成,确保输入信息能够直接加到输出上。
- ResNet的输出计算:通过逐层递推,每一层的输出都是对输入和变换后特征的累积,使得网络能够更有效地学习深层特征。
具体实现:残差块的工作原理
- 输入特征(原始输入特征):假设输入特征是 x \mathbf{x} x。
- 变换路径:输入特征 x \mathbf{x} x 经过一系列的卷积操作、批量归一化和激活函数后,得到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 。
- 跳跃连接:在变换路径之外,直接将输入特征 x \mathbf{x} x 加到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x)上,得到输出特征 y \mathbf{y} y:
y = F ( x ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x} y=F(x)+x
这里, F ( x ) \mathcal{F}(\mathbf{x}) F(x) 是通过卷积和激活操作后的特征, x \mathbf{x} x 是原始输入特征。这样,每个残差块的输出就是“变换后的特征+原始输入特征”。