本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Backbone 之 ResNet:里程碑
背景:
由于随着网络的层数不断加深,网络训练变得越发地困难,一方面会产生梯度消失的现象,另一方面月神的网络返回的梯度相关性会越来越差,越接近白噪声,导致梯度更新也接近于随机扰动。由此ResNet应运而生。
思路:
引入一个深度残差框架来解决梯度消失问题,即让卷积网络去学习残差映射,而不是期望每一个堆叠层的网络都完整的拟合潜在的映射(拟合函数)。
结构图:
在ResNet中,上述的一个残差模块被称之为Bottleneck,其中ResNet有不同的网络层版本,比如:18,34,52,101和152层,较为常用的为50。
ResNet-50结构:
由图中可以看出:中间经历了4个大的卷积组,而这4个大卷积组分别包含了3,4,6这3个Bottleneck模块,在最后经历了一个全局平均池化是的特征图变为1*1,然后进行1000维的全连接,最后经过Softmax输出分类得分。
由于
是逐通道相加的,因此根据两者的通道是否相同分为两种Bottleneck情况,对于通道数不同时,需要利用1*1卷积对x进行下采样,将通道数变为相同,在进行加操作,若对于通道数相同时则可以直接相加。
代码如下:
import torch.nn as nn
class Bottleneck(nn.Module):
def __init__(self, in_dim, out_dim, stride=1):
super(Bottleneck, self).__init__()
###网络堆叠层是1*1,3*3,1*1这三个卷积块组成,中间包括BN层
self.bottleneck = nn.Sequential(
nn.Conv2d(in_dim, in_dim, 1, bias=False),
nn.BatchNorm2d(in_dim),
nn.ReLU(inplace=True),
nn.Conv2d(in_dim, in_dim, 3, stride, 1, bias=False),
nn.BatchNorm2d(in_dim),
nn.ReLU(inplace=True),
nn.Conv2d(in_dim, out_dim, 1, bias=False),
nn.BatchNorm2d(out_dim),
)
self.relu = nn.ReLU(inplace=True)
###下采样是一个包含BN层的1*1卷积组成
self.downsample = nn.Sequential(
nn.Conv2d(in_dim, out_dim, 1, 1),
nn.BatchNorm2d(out_dim),
)
def forward(self, x):
identity = x
out = self.bottleneck(x)
identity = self.downsample(x)
##将identity(恒等映射)与网络堆叠层输出进行相加,并经过ReLU后输出
##
out += identity
out = self.relu(out)
return out