【CV面试必会】深度学习网络之Resnet以及其对应pytorch代码

Resnet是He 等人在2015年提出的网络。用来解决在之前的一些网络,在网络层数增多时,反而其在训练集上error表现下降的现象。这种现象并不是由于过拟合导致的,因为在过拟合的时候,应该是train效果很好,test的效果很差。

 

下图即为Resnet的两个核心结构,左边的图是在Resnet18/34使用的短路结构,这时的Resnet block使用两个3*3卷积,并add输入X。

右图为在Resnet50/101/152时的Resnet block,这时block由1*1卷积先降低输入的维度,在进行3*3卷积,之后再用1*1卷积来提高维度,并与输入X 完成add。这时有两种情况,第一种情况是X维度与F(x)维度一致,这样可以直接相加;第二种情况就是X维度与F(x)维度不一致,这时就需要改变输入的维度在与F(x)相加。

在右边的block图中为什么不像 左边的block一样,直接使用两个3*3卷积呢,是因为此时输入通道数较高,如果直接使用两个3*3卷积,计算参数量很大,咱们可以来算一下:

1.两个3*3 卷积 3*3*256*256*2 = 1,179,648

2.一个3*3卷积和两个1*1卷积 3*3*64*64+1*1*256*64*2 = 69,632‬

可以看到第一种方式是第二种方式参数的16.9倍

 

接下来就解析两种不同的方式,因为输入和输出的通道可能是不同的,所以就有了这两种方式,先放一下论文里面的图。

如在Resnet50时,conv3_x最后一个block传入conv4_x第一个block的时候,就会产生上述这种问题。所以在每个卷积层的第一个block需要改变输入的通道。

下面我们看看在pytorch代码中这两种block方式对应的。

class Residual(nn.Module):
  
  def __init__(self,input_channels, num_channels, use_1x1conv=False, strides=1, **kwargs):
    super(Residual, self).__init__(**kwargs)
    self.conv1 = nn.Conv2d(input_channels, num_channels,kernel_size=3, padding=1, stride=strides)
    self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1)
    if use_1x1conv://是否需要改变输入的通道
      self.conv3 = nn.Conv2d(input_channels, num_channels, kernel_size=1, stride=strides)
    else:
      self.conv3 = None
    self.bn1 = nn.BatchNorm2d(num_channels)
    self.bn2 = nn.BatchNorm2d(num_channels)
    self.relu = nn.ReLU(inplace=True)
  
  def forward(self, X):
    
    Y = self.relu(self.bn1(self.conv1(X)))
    Y = self.bn2(self.conv2(Y))
    if self.conv3://改变输入的通道
      X = self.conv3(X)
    Y += X
    Y =self.relu(Y)
    return Y

def resnet_block(input_channels, num_channels, num_residuals, first_block=False):
  blk = []
  for i in range(num_residuals):
    if i == 0 and not first_block://在每一个CONV_x的第一个block添加需要变换输入的block
      blk.append(Residual(input_channels, num_channels, use_1x1conv=True, strides=2))
    else:
      blk.append(Residual(num_channels, num_channels))
  return blk

在残差块的传入参数中都加入一个变量use_1x1conv,来判断是否为conv_x的第一个block,如果是,就在该block中新加一个1*1卷积,来变换输入,保证输入与输出的通道一致,这样才可以让两者相加。

 

面试遇到的问题:参考了该blog

1.为什么之前的网络不能训练深层的网络,ResNet就可以了呢?

解答:神经网络越来越深的时候,反传回来的梯度之间的相关性会越来越差,最后接近白噪声。因为图像是具备局部相关性的,那其实可以认为梯度也应该具备类似的相关性,这样更新的梯度才有意义,如果梯度接近白噪声,那梯度更新可能根本就是在做随机扰动。

 

2.为什么短路连接可以帮助梯度更好的回传?

解答:ResNet block至少保持梯度不会退化,因为学习那个恒等印射,至少完成了模型不退化,因为输出有着一部分与输入一样为X。这样就提高了梯度相关性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值