ResNet的pytorch实现与解析

  • Post author:
  • Post category:其他


恒等快,若x和H(x)的维度相等

在这里插入图片描述

恒等快,若x和H(x)的维度不相等,需要将x卷积bn,relu在送入H(x)

在这里插入图片描述

自适应池化操作

在这里插入图片描述

inplanes 是提供给block的通道数,planes表示block的输出通道。大家知道,在做残差相加的时候,我们必须保证残差的维度与真正输出的维度相等(注意这里维度是宽高以及深度)这样我们才能把它们堆到一起,所以程序中出现了降采样操作。

if stride != 1 or self.inplanes != planes * block.expansion:大家注意到这个if语句,它存在两种条件使他为真。第一就是stride != 1,我们以下图为例,输入56×56×256输出为28×28×512,显然stride=2(resnet没有pooling)这时我们满足第一个条件,所以进入降采样操作,令stride=2,这样我的残差输出就变成了28×28。

再看第二个条件 self.inplanes != planes * block.expansion,这是self.inplanes=256,而planes =512(这里因为basic block,block.expansion=1),所以第二个条件满足,那么进行降采样用1×1卷积改变通道数。

总之,这个步骤就是为了匹配维度。

在这里插入图片描述

resnet结构如图

在这里插入图片描述

pytorch代码如下`

# -*- coding: utf-8 -*-
# @Time    : 2020/11/24 18:05
# @Author  : Refrain_ouc
# @FileName: resnet_ouc.py
# @Software: PyCharm

import torch
import torch.nn as nn
import torch.nn.functional as F

class BasicBlock(nn.Module):
    expansion =1
    def __init__(self,in_planes,planes,stride=1):
        self.conv1=nn.Sequential(
            nn.Conv2d(in_planes,planes,kernel_size=3,stride=stride,padding=1),
            nn.BatchNorm2d(planes),
            nn.ReLU(True)
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(planes,planes*self.expansion,kernel_size=3,stride=1,padding=1),
            nn.BatchNorm2d(planes*self.expansion),

        )
        self.shortcut=nn.Sequential()

        if stride!=1 or in_planes!=planes*self.expansion:
            self.shortcut=nn.Sequential(
                nn.Conv2d(in_planes,planes*self.expansion,kernel_size=1,stride=stride),
                nn.BatchNorm2d(planes*self.expansion)
            )

    def forward(self,input):
        output=self.conv1(input)
        output=self.conv2(output)
        output=output+self.shortcut
        output=F.relu(output)
        return output

class BottleBolck(nn.Module):
    expansion=4
    def __init__(self,in_planes,planes,stride=1):
        self.conv1=nn.Sequential(
            nn.Conv2d(in_planes,planes,kernel_size=1,stride=stride),
            nn.BatchNorm2d(planes),
            nn.ReLU(True)
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(planes,planes,kernel_size=3,stride=1,padding=1),
            nn.BatchNorm2d(planes),
            nn.ReLU(True)
        )
        self.conv3=nn.Sequential(
            nn.Conv2d(planes,planes*self.expansion,kernel_size=1,stride=1),
            nn.BatchNorm2d(planes*self.expansion)
        )
        self.shortcut=nn.Sequential()

        if stride!=1 or in_planes!=planes*self.expansion:
            self.shortcut=nn.Sequential(
                nn.Conv2d(in_planes,planes*self.expansion,kernel_size=1,stride=1),
                nn.BatchNorm2d(planes*self.expansion)
            )

    def forward(self,input):
        output=self.conv1(input)
        output=self.conv2(output)
        output=self.conv3(output)
        output=output+self.shortcut
        output=F.relu((output))
        return  output

class Resnet(nn.Module):
    def __init__(self,block,num_layer,num_class=10):
        self.in_planes=64
        self.conv=nn.Sequential(
            nn.Conv2d(3,64,kernel_size=7,stride=2,padding=3),
            nn.BatchNorm2d(64),
            nn.ReLU(True),
            nn.MaxPool2d(kernel_size=3,stride=2,padding=1),
        )
        self.conv1=self.make_layer(block=block,planes=64,num_layer=num_layer[0],stride=1)
        self.conv2=self.make_layer(block=block,planes=128,num_layer=num_layer[1],stride=2)
        self.conv3=self.make_layer(block=block,planes=256,num_layer=num_layer[2],stride=2)
        self.conv4=self.make_layer(block=block,planes=512,num_layer=num_layer[3],stride=2)

        self.aver_pool=nn.AdaptiveAvgPool2d((1,1))
        self.linera=nn.Linear(512*block.expansion,num_class)

    def forward(self,x):
        output=self.conv(x)
        output=self.conv1(output)
        output=self.conv2(output)
        output=self.conv3(output)
        output=self.conv4(output)
        output=self.aver_pool(output)
        #output.size(channel,h,w)
        output=output.view(output.size(0),-1)
        output=self.linera(output)
        return output



    def make_layer(self,block,planes,num_layer,stride):
        layer=[]
        strides=[stride]+[1]*(num_layer-1)
        for stride in strides:
            layer.append(block(self.in_planes,planes,stride))
            self.in_plances=planes*block.expansion
        return nn.Sequential(*layer)



版权声明:本文为qq_41333847原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。