目录
网络结构
残差块(Residual Block)
ResNet网络结构示意图
残差块(Residual Block)细节
基本残差块(ResNet-18/34)
Bottleneck残差块(ResNet-50/101/152)
残差连接类型对比
变体网络层数对比
关键设计总结
ResNet旨在解决深度神经网络中的梯度消失和退化问题。随着网络层数的增加,深层网络的性能反而可能下降,ResNet通过引入残差学习有效缓解了这一问题。
残差相当于‘短路网络’,在ResNet网络结构中,每个前置输入X除了正常的正向传播还会跨两层的直接传到激活函数的节点上
问题:为什么残差网络的层数可以更深(50层+),如何应对梯度消失问题?
‘短路’的设计+relu作为激活函数,使得在深层的网络甚至是输出层都带有原始的数据特征,加之relu的特性非1即0,梯度在连乘的过程中也可以得到较好的保留
网络结构
残差块(Residual Block)
ResNet的核心是残差块,其结构如下:
- 输入:x
- 输出:F(x)+x
其中:
- F(x) 是残差函数,通常由几层卷积层组成。
- x 是输入的直接映射(shortcut connection)。
ResNet网络结构示意图
整体架构(以ResNet-50为例)
残差块(Residual Block)细节
基本残差块(ResNet-18/34)
Bottleneck残差块(ResNet-50/101/152)
残差连接类型对比
类型 | 输入输出维度 | 实现方式 |
Identity Mapping | 相同 | 直接相加(无额外操作) |
Projection Shortcut | 不同 | 通过1x1卷积调整通道和尺寸 |
变体网络层数对比
网络名称 | 总层数 | 残差块组成(Bottleneck数量) |
ResNet-18 | 18 | [2, 2, 2, 2] |
ResNet-34 | 34 | [3, 4, 6, 3] |
ResNet-50 | 50 | [3, 4, 6, 3](Bottleneck) |
ResNet-101 | 101 | [3, 4, 23, 3] |
ResNet-152 | 152 | [3, 8, 36, 3] |
关键设计总结
- 跳跃连接:解决梯度消失,允许直接传递原始信号。
- Bottleneck结构:通过1x1卷积压缩和扩展通道数,减少计算量。
- 分阶段降采样:通过步幅2的卷积逐步缩小特征图尺寸,扩大感受野。
- 全局平均池化:替代全连接层,减少参数量,防止过拟合。
反向传播时跟loss比较接近的层通过残差的设计可以更好地传回前面,对参数进行调整
残差单元:先用1*1的卷积核提取特征让3*3的卷积核需要学习的参数减少,最后再用1*1的卷积核升维(增加卷积核的数量--增加通道数)
问题:keras框架中,DenseNet网络中参数‘growth_rate’的含义?
在Keras的DenseNet中,`growth_rate` 是一个关键超参数,用于控制网络的特征扩展速度和模型复杂度。
`growth_rate` 的定义:
`growth_rate`(通常记为 `k`)表示每个密集层(Dense Layer) 输出的特征图(Channel)数量。
每个密集层会生成 `k` 个新特征图,并通过通道拼接(Concatenation) 与之前所有层的特征图合并,作为下一层的输入。
`growth_rate` 的作用:
1. 特征复用与扩展
DenseNet中,每个密集层的输入是前面所有层输出的拼接。
若当前层是第 `l` 层,输入通道数为 `m + k*(l-1)`(`m` 为初始输入通道数),输出通道数增加 `k`。
`growth_rate` 控制每一层新增的特征图数量,直接影响网络的宽度。
2. 计算效率与模型复杂度
较小的 `k`(如 `k=12`)会限制特征图增长,降低计算量,但可能损失表达能力。
较大的 `k`(如 `k=32`)会增加模型容量,但计算成本和内存占用也会显著上升。
3. Bottleneck层设计
在用户提供的代码中,`1x1卷积`(输出通道为 `4*k`)用于压缩特征图,减少后续 `3x3卷积` 的计算量(输出通道为 `k`)。
这是DenseNet-B(Bottleneck版本)的典型设计,通过 `growth_rate` 控制Bottleneck结构的压缩比例。
DenseNet中的一个密集块(Dense Block) 的实现:
# 输入x经过BN→ReLU→1x1卷积(压缩到4*k通道)→BN→ReLU→3x3卷积(输出k通道)
x1 = layers.Conv2D(4 * growth_rate, 1, ...)(x1) # Bottleneck压缩
x1 = layers.Conv2D(growth_rate, 3, ...)(x1) # 生成k个特征图
x = layers.Concatenate()([x, x1]) # 通道拼接
`growth_rate` 决定了最终输出的特征图数量(`k`)。
每个密集层通过拼接操作,使得特征图数量逐层增长 `k`,形成密集连接。
典型取值与影响