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)