web123456

Introduction to ResNet18 and use it to classify CIFAR-10 datasets

  • import torch
  • import time
  • from torch import nn
  • # The initial convolution layer, process the input image into feature map
  • class Conv1():
  • def __init__(self,inp_channels,out_channels,stride = 2):
  • super(Conv1,self).__init__()
  • = (
  • nn.Conv2d(inp_channels,out_channels,kernel_size=7,stride=stride,padding=3,bias=False),# The result of convolution (i - k + 2*p)/s + 1, the image size is reduced by half at this time
  • nn.BatchNorm2d(out_channels),
  • (inplace=True),
  • nn.MaxPool2d(kernel_size=3,stride=2,padding=1)# According to the convolution formula, the feature map size becomes half of the original
  • )
  • def forward(self,x):
  • y = (x)
  • return y
  • class Simple_Res_Block():
  • def __init__(self,inp_channels,out_channels,stride=1,downsample = False,expansion_=False):
  • super(Simple_Res_Block,self).__init__()
  • = downsample
  • if expansion_:
  • = 4# Expand the dimension to expand times
  • else:
  • = 1
  • = (
  • nn.Conv2d(inp_channels,out_channels,kernel_size=3,stride=stride,padding=1),
  • nn.BatchNorm2d(out_channels),
  • (inplace=True),
  • nn.Conv2d(out_channels,out_channels*,kernel_size=3,padding=1),
  • nn.BatchNorm2d(out_channels*)
  • )
  • if :
  • = (
  • nn.Conv2d(inp_channels,out_channels*,kernel_size=1,stride=stride,bias=False),
  • nn.BatchNorm2d(out_channels*)
  • )
  • = (inplace=True)
  • def forward(self,input):
  • residual = input
  • x = (input)
  • if :
  • residual = (residual)# Make the dimensions of x and h the same
  • out = residual + x
  • out = (out)
  • return out
  • class Residual_Block():
  • def __init__(self,inp_channels,out_channels,stride=1,downsample = False,expansion_=False):
  • super(Residual_Block,self).__init__()
  • = downsample# Determine whether to downsample x so that the dimension number of x and the output value of the module are the same
  • if expansion_:
  • = 4# Expand the dimension to expand times
  • else:
  • = 1
  • #Module
  • self.conv1 = nn.Conv2d(inp_channels,out_channels,kernel_size=1,stride=1,bias=False)# Does not change the feature map size and play a mapping role
  • = (0.5)
  • self.BN1 = nn.BatchNorm2d(out_channels)
  • self.conv2 = nn.Conv2d(out_channels,out_channels,kernel_size=3,stride=stride,padding=1,bias=False)# At this time, the size of the convolution kernel and the fill size will not affect the size of the feature map, which is determined by the step size.
  • self.BN2 = nn.BatchNorm2d(out_channels)
  • self.conv3 = nn.Conv2d(out_channels,out_channels*,kernel_size=1,stride=1,bias=False)# Change the number of channels
  • self.BN3 = nn.BatchNorm2d(out_channels*)
  • = (inplace=True)
  • if :
  • = (
  • nn.Conv2d(inp_channels,out_channels*,kernel_size=1,stride=stride,bias=False),
  • nn.BatchNorm2d(out_channels*)
  • )
  • def forward(self,input):
  • residual = input
  • x = (self.BN1(self.conv1(input)))
  • x = (self.BN2(self.conv2(x)))
  • h = self.BN3(self.conv3(x))
  • if :
  • residual = (residual)# Make the dimensions of x and h the same
  • out = h + residual# Residual Part
  • out = (out)
  • return out
  • class Resnet():
  • def __init__(self,net_block,block,num_class = 1000,expansion_=False):
  • super(Resnet,self).__init__()
  • self.expansion_ = expansion_
  • if expansion_:
  • = 4# Expand the dimension to expand times
  • else:
  • = 1
  • # Convolution of the input initial image
  • # (3*64*64) --> (64*56*56)
  • = Conv1(3,64)
  • # Build modules
  • # (64*56*56) --> (256*56*56)
  • self.block1 = self.make_layer(net_block,block[0],64,64,expansion_=self.expansion_,stride=1)# stride is 1, and the size is not changed
  • # (256*56*56) --> (512*28*28)
  • self.block2 = self.make_layer(net_block,block[1],64*,128,expansion_=self.expansion_,stride=2)
  • # (512*28*28) --> (1024*14*14)
  • self.block3 = self.make_layer(net_block,block[2],128*,256,expansion_=self.expansion_,stride=2)
  • # (1024*14*14) --> (2048*7*7)
  • self.block4 = self.make_layer(net_block,block[3],256*,512,expansion_=self.expansion_,stride=2)
  • = nn.AvgPool2d(7,stride=1)# (2048*7*7) --> (2048*1*1) Through the average pooling layer, all pixels are fused and averaged
  • if expansion_:
  • length = 2048
  • else:
  • length = 512
  • = (length,num_class)
  • for m in ():
  • if isinstance(m, nn.Conv2d):
  • .kaiming_normal_(, mode='fan_out', nonlinearity='relu')
  • elif isinstance(m, nn.BatchNorm2d):
  • .constant_(, 1)
  • .constant_(, 0)
  • def make_layer(self,net_block,layers,inp_channels,out_channels,expansion_=False,stride = 1):
  • block = []
  • (net_block(inp_channels,out_channels,stride=stride,downsample=True,expansion_=expansion_))# First reduce the number of channels in the previous module to the number of channels required by the module
  • if expansion_:
  • = 4
  • else:
  • = 1
  • for i in range(1,layers):
  • (net_block(out_channels*,out_channels,expansion_=expansion_))
  • return (*block)
  • def forward(self,x):
  • x = (x)
  • x = self.block1(x)
  • x = self.block2(x)
  • x = self.block3(x)
  • x = self.block4(x)
  • # x = (x)
  • x = ([0],-1)
  • x = (x)
  • return x
  • def Resnet18():
  • return Resnet(Simple_Res_Block,[2,2,2,2],num_class=10,expansion_=False)# At this time, there are only two layers of convolution in each module
  • def Resnet34():
  • return Resnet(Simple_Res_Block,[3,4,6,3],num_class=10,expansion_=False)
  • def Resnet50():
  • return Resnet(Residual_Block,[3,4,6,3],expansion_=True)# Also called 50-layer resnet, this network has 16 modules, each module has three layers of convolution, and finally the initial convolution and the final fully connected layer are left, a total of 50 layers
  • def Resnet101():
  • return Resnet(Residual_Block,[3,4,23,3],expansion_=True)
  • def Resnet152():
  • return Resnet(Residual_Block,[3,8,36,3],expansion_=True)