深度残差网络(ResNet)原理与Keras实现详解

深度残差网络(ResNet)原理与Keras实现详解

deep-learning-coursera Deep Learning Specialization by Andrew Ng on Coursera. deep-learning-coursera 项目地址: https://gitcode.com/gh_mirrors/de/deep-learning-coursera

1. 深度神经网络的梯度消失问题

在深度学习领域,网络深度对于模型性能至关重要。理论上,更深的网络可以表示更复杂的函数,并能学习从底层边缘特征到高层语义特征的多层次抽象表示。然而在实践中,随着网络深度增加,我们会遇到一个关键问题——梯度消失。

梯度消失现象表现为:在反向传播过程中,随着梯度从输出层向输入层传递,梯度信号会呈指数级衰减。这导致网络的前几层参数几乎无法得到有效更新,训练过程变得极其缓慢。从数学角度看,这是因为在反向传播链式法则中,梯度是各层权重矩阵的连乘积,当这些权重值较小时,梯度会迅速趋近于零。

2. 残差网络的核心思想

残差网络(ResNet)通过引入"跳跃连接"(skip connection)的创新设计,有效解决了深度网络训练难题。其核心思想是:让网络层学习残差映射而非直接映射。

2.1 残差块结构解析

残差块有两种基本形式:

  1. 恒等块(Identity Block):当输入输出维度相同时使用
  2. 卷积块(Convolutional Block):当需要改变特征图维度时使用

两种结构都包含一个"主路径"和一个"捷径"。主路径通常由2-3个卷积层组成,捷径则可能包含一个1×1卷积用于维度匹配。

3. 恒等块实现详解

恒等块是ResNet的基础构建模块,其Keras实现如下:

def identity_block(X, f, filters, stage, block):
    # 定义命名基础
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'
    
    F1, F2, F3 = filters
    X_shortcut = X  # 保存输入值
    
    # 主路径第一组件
    X = Conv2D(F1, (1,1), name=conv_name_base+'2a')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2a')(X)
    X = Activation('relu')(X)
    
    # 主路径第二组件
    X = Conv2D(F2, (f,f), padding='same', name=conv_name_base+'2b')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2b')(X)
    X = Activation('relu')(X)
    
    # 主路径第三组件
    X = Conv2D(F3, (1,1), name=conv_name_base+'2c')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2c')(X)
    
    # 添加捷径值到主路径
    X = Add()([X, X_shortcut])
    X = Activation('relu')(X)
    
    return X

关键点说明:

  • 使用批量归一化(BatchNorm)加速训练
  • 每个卷积层后都跟随ReLU激活函数
  • 最后通过Add层合并主路径和捷径

4. 卷积块实现解析

当需要改变特征图维度时,使用卷积块:

def convolutional_block(X, f, filters, stage, block, s=2):
    # 定义命名基础
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'
    
    F1, F2, F3 = filters
    X_shortcut = X
    
    # 主路径第一组件
    X = Conv2D(F1, (1,1), strides=(s,s), name=conv_name_base+'2a')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2a')(X)
    X = Activation('relu')(X)
    
    # 主路径第二组件
    X = Conv2D(F2, (f,f), padding='same', name=conv_name_base+'2b')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2b')(X)
    X = Activation('relu')(X)
    
    # 主路径第三组件
    X = Conv2D(F3, (1,1), name=conv_name_base+'2c')(X)
    X = BatchNormalization(axis=3, name=bn_name_base+'2c')(X)
    
    # 捷径路径
    X_shortcut = Conv2D(F3, (1,1), strides=(s,s), name=conv_name_base+'1')(X_shortcut)
    X_shortcut = BatchNormalization(axis=3, name=bn_name_base+'1')(X_shortcut)
    
    # 合并路径
    X = Add()([X, X_shortcut])
    X = Activation('relu')(X)
    
    return X

与恒等块的主要区别:

  • 捷径路径增加了1×1卷积用于维度匹配
  • 主路径第一组件使用步长s进行下采样
  • 确保主路径和捷径的输出维度一致

5. ResNet训练技巧

  1. 权重初始化:使用Glorot均匀分布初始化
  2. 批量归一化:沿通道轴(axis=3)归一化
  3. 激活函数:ReLU用于引入非线性
  4. 残差连接:Add层直接相加而非拼接

6. 总结

残差网络通过引入跳跃连接,使梯度可以直接传播到浅层,有效解决了深度网络的训练难题。这种设计不仅缓解了梯度消失问题,还使网络能够轻松学习恒等映射,保证了增加深度不会降低模型性能。在实际应用中,ResNet已成为计算机视觉任务的基础架构之一。

deep-learning-coursera Deep Learning Specialization by Andrew Ng on Coursera. deep-learning-coursera 项目地址: https://gitcode.com/gh_mirrors/de/deep-learning-coursera

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霍曙柏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值