Pytorch 目标检测学习 Day 4

里程碑之ResNet

出现问题:一方面会产生梯度消失现象;另一方面越深的网络返回的梯度相关性会越来越差,接近于白噪声,导致梯度更新也接近于随机扰动。

ResNet(Residual Network,残差网络)较好地解决了这个问题,此后的分类、检测、分割等任务也大规模使用ResNet作为网络骨架。

ResNet的思想在于引入了一个深度残差框架来解决梯度消失问题,即让卷积网络去学习残差映射,而不是期望每一个堆叠层的网络都完整地拟合潜在的映射(拟合函数)。

通过引入一个shortcut(捷径)分支,将需要拟合的映射变为残差F(x):H(x)-x。ResNet给出的假设是:相较于直接优化潜在映射H(x),优化残差映射F(x)是更为容易的。

在ResNet中,上述的一个残差模块称为Bottleneck。ResNet有不同网络层数的版本,如18层、34层、50层、101层和152层,这里以常用的50层来讲解。

ResNet-50的网络架构

由于F(x)+x是逐通道进行相加,因此根据两者是否通道数相同,存在两种Bottleneck结构。对于通道数不同的情况,比如每个卷积组的第一个Bottleneck,需要利用1×1卷积对x进行Downsample操作,将通道数变为相同,再进行加操作。对于相同的情况下,两者可以直接进行相加。

利用PyTorch实现一个带有Downsample操作的Bottleneck

import torch.nn as nn 
import torch
class Bottleneck(nn.Module):
    def __init__(self,in_dim,out_dim,stride=1):
        super(Bottleneck,self).__init__()
        # 网络堆叠层是由1x1,3x3,1x1 这三个卷积组成,中间包包含BN层
        self.bottleneck = nn.Sequential(
            #卷积+BN
            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)
        #Downsample部分是由一个包含BN层的1x1卷积组成
        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)
        #将x 恒等映射,进过ReLU 输出
        out += identity
        out = self.relu(out)
        return out

 #实例化
if __name__ == "__main__":
    bottleneck_1_1 = Bottleneck(64,256)
    print(bottleneck_1_1)
    inputs  = torch.randn(1,64,56,56)
    output = bottleneck_1_1(inputs)
    print(inputs.size())
    print(output.size())

结果

Bottleneck(
  (bottleneck): Sequential(
    (0): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
    (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
    (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (5): ReLU(inplace=True)
    (6): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  )
  (relu): ReLU(inplace=True)
  (downsample): Sequential(
    (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
    (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  )
)
torch.Size([1, 64, 56, 56])
torch.Size([1, 256, 56, 56])

相比输入,输出的特征图分辨率没变,而通道数变成了4倍,变的更厚了

 

 

おすすめ

転載: blog.csdn.net/abc123mma/article/details/112151798
おすすめ