卷积神经网络(Convolutional Neural Networks, CNNs)在计算机视觉领域取得了巨大成功,特别是在图像识别任务中。随着网络深度的增加,模型性能理论上应当逐步提升,然而实际上却面临训练困难、梯度消失或爆炸等问题。为解决这一问题,残差网络(Residual Networks, ResNets)应运而生,其通过引入残差连接(Skip Connections)极大地改善了深层网络的训练效果。
残差网络的核心在于其残差块(Residual Block)的设计。残差块通过添加一个直接连接(或称为恒等映射)来绕过一层或多层,使得网络的输入可以直接传递到后续层,与经过非线性变换后的输出相加。这一设计有效缓解了深层网络中的梯度消失问题。
假设一个残差块的输入为 \(x\),输出为 \(H(x)\),在传统的卷积神经网络中,希望学习到从 \(x\) 到 \(H(x)\) 的直接映射。而在残差网络中,残差块学习到的是 \(F(x) = H(x) - x\),即残差,然后输出为 \(H(x) = F(x) + x\)。这样,即使 \(F(x)\) 为零(即没有进行任何有效变换),\(H(x)\) 也能简单地等于 \(x\),保证了信息的有效传递。
ResNets 通常由多个残差块堆叠而成,这些残差块按照不同的配置分为不同的层级(如ResNet-18, ResNet-34, ResNet-50等)。每个残差块内部可能包含多个卷积层、批量归一化(Batch Normalization)和ReLU激活函数。
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, in_channels, out_channels, stride=1):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.downsample = None
if stride != 1 or in_channels != self.expansion*out_channels:
self.downsample = nn.Sequential(
nn.Conv2d(in_channels, self.expansion*out_channels, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(self.expansion*out_channels),
)
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
深层网络训练过程中,学习率的设置尤为关键。ResNets 通常采用逐步降低学习率的策略,如使用余弦衰减(Cosine Decay)或阶梯衰减(Step Decay)。
良好的权重初始化可以加速训练并减少梯度消失的风险。He初始化(He Initialization)是针对ReLU激活函数设计的一种有效初始化方法,广泛应用于ResNets。
图像识别任务中,数据增强技术如随机裁剪、水平翻转、旋转、颜色抖动等能有效提升模型的泛化能力。
为了防止过拟合,ResNets 在某些层后加入了dropout操作,并在训练过程中使用L2正则化。
残差网络通过引入残差连接,极大地提升了深层卷积神经网络的训练效率和性能,成为图像识别领域的重要里程碑。通过合理的网络构建和性能调优策略,ResNets 能够在复杂的图像识别任务中取得卓越的表现。随着研究的深入,残差网络的思想也被广泛应用于其他深度学习领域,展现了其强大的生命力和普适性。