【ResNet笔记(2)】ResNet的 bottleneck 设计

右图是 bottleneck

图 两种ResNet设计

右图是 shortcut connection

“弯弯的弧线“这个就是”shortcut connection“,也是论文中提到identity mapping

两种结构统称building block

这两种结构分别针对ResNet34(左图)和ResNet50/101/152(右图),一般称整个结构为一个”building block“。

bottleneck design 降低参数量

其中右图又称为”bottleneck design”,目的一目了然,就是为了降低参数的数目,第一个1x1的卷积把256维channel降到64维,然后在最后通过1x1卷积恢复,整体上用的参数数目:1x1x256x64 + 3x3x64x64 + 1x1x64x256 = 69632,而不使用bottleneck的话就是两个3x3x256的卷积,参数数目: 3x3x256x256x2 = 1179648,差了16.94倍。

对于常规ResNet,可以用于34层或者更少的网络中,对于Bottleneck Design的ResNet通常用于更深的如101这样的网络中,目的是减少计算和参数量,减少训练时间(实用目的)。

bottleneck结构单元

在这里插入图片描述

一个是bottleneck中第二个1*1卷积的通道为什么是256维度;

  • 可理解为参数设置将最后一个卷积的通道设置为当前输入通道的4倍;

一个是左右两侧为相同的输入,为什么图右变为256维度的恒等映射;

  • 要想实现加运算,必须令输入通道数和11卷积核的输出通道数相同,所以需要对原始64通道的输入利用11卷积增加通道至256维。

参考:
https://blog.csdn.net/u011304078/article/details/80683985

### ResNet50 中的 Bottleneck 结构详解 #### 什么是Bottleneck结构 在ResNet架构中,为了进一步减少计算量并提高效率,在较深版本如ResNet50里采用了所谓的瓶颈层(Bottleneck Layer)。这种特殊的设计不仅能够有效降低参数数量,还能保持甚至提升模型的表现力。 #### 具体组成 对于ResNet50而言,其主要由多个堆叠起来的标准卷积模块构成。然而不同于浅层版本采用简单重复的基础单元形式,这里引入了更为复杂的三层组合方式作为基础构建块——即所谓"Bottleneck"单元[^2]: - **第一个1×1卷积**:负责降维操作,通常会将输入特征图通道数减半; - **最后一个1×1卷积**:用于恢复原始维度大小的同时也起到融合信息的作用。 此三步流程构成了完整的Bottleneck子模块,并且在整个网络内部被多次迭代使用以形成更深层次的整体框架。 #### PyTorch 实现示意代码 下面给出一段基于PyTorch框架下定义上述描述中的单个Bottleneck Unit实例化方法: ```python import torch.nn as nn class Bottleneck(nn.Module): expansion = 4 def __init__(self, inplanes, planes, stride=1, downsample=None): super(Bottleneck, self).__init__() # First Convolution (1x1) self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) self.bn1 = nn.BatchNorm2d(planes) # Second Convolution (3x3) self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(planes) # Third Convolution (1x1), expand back to original size with factor of 'expansion' self.conv3 = nn.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False) self.bn3 = nn.BatchNorm2d(planes * self.expansion) self.relu = nn.ReLU(inplace=True) self.downsample = downsample self.stride = stride def forward(self, x): residual = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.conv3(out) out = self.bn3(out) if self.downsample is not None: residual = self.downsample(x) out += residual out = self.relu(out) return out ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hali_Botebie

文中错误请不吝指正!!!!!!

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

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

打赏作者

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

抵扣说明:

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

余额充值