pytorch 图像分类
1.VGG
https://arxiv.org/pdf/1409.1556v6.pdf
import torch.nn as nn
cfg = {
'A' : [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'B' : [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'D' : [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'E' : [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M']
}
class VGG(nn.Module):
def __init__(self,features,num_class=100):
super().__init__()
self.features=features
self.classifier=nn.Sequential(
nn.Linear(512,4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096,4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096,num_class)
)
def forward(self,x):
output=self.features(x)
output=output.view(output.size()[0],-1)
output=self.classifier(output)
return output
def make_layers(cfg,batch_norm=False):
layers=[]
input_channel=3
for l in cfg:
if l=='M':
layers+=[nn.MaxPool2d(kernel_size=2,stride=2)]
continue
layers+=[nn.Conv2d(input_channel,l,kernel_size=3,padding=1)]
if batch_norm:
layers+=[nn.BatchNorm2d(l)]
layers+=[nn.ReLU(inplace=True)]
input_channel=l
return nn.Sequential(*layers)
def vgg11_bn():
return VGG(make_layers(cfg['A'], batch_norm=True))
def vgg13_bn():
return VGG(make_layers(cfg['B'], batch_norm=True))
def vgg16_bn():
return VGG(make_layers(cfg['D'], batch_norm=True))
def vgg19_bn():
return VGG(make_layers(cfg['E'], batch_norm=True))
1.bn层计算
https://blog.csdn.net/ChaoFeiLi/article/details/108950522
我理解就是把一个batch中数据归一化,使得训练的数据符合相同的分布。
求数据的均值和方差,然后对每个通道的数据计算后,使得数据满足均值为0方差为1的分布。
但是如果一个batch中每个数据都一样,这样不能代表所有数据的分布,会产生误差。比如batch很小的情况(图像分割)
好处就是:使数据远离激活函数的饱和区,加快速度
batch norm的作用: BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。
2.relu层
https://zhuanlan.zhihu.com/p/46255482
ReLU输出就很稳定,因为他z>0区间就是一个线性函数!不存在sigmoid的梯度消失的问题。
另一个ReLU很给力的地方就是稀疏度问题。就是我们希望每个神经元都能最大化的发挥它筛选的作用,符合某一个特征的中间值,使劲儿放大;不符合的,一刀切掉。
2.Googlenet
https://arxiv.org/pdf/1409.4842v1.pdf
import torch.nn as nn
import torch
class Inception(nn.Module):
def __init__(self,input_channels,n1x1,n3x3_reduce,n3x3,n5x5_reduce,n5x5,pool_proj):
super(Inception, self).__init__()
#1x1conv branch
self.b1=nn.Sequential(
nn.Conv2d(input_channels,n1x1,kernel_size=1),
nn.BatchNorm2d(n1x1),
nn.ReLU(inplace=True)
)
#1x1 ->3x3
self.b2=nn.Sequential(
nn.Conv2d(input_channels,n3x3_reduce,kernel_size=1),
nn.BatchNorm2d(n3x3_reduce),
nn.ReLU(inplace=True),
nn.Conv2d(n3x3_reduce,n3x3,kernel_size=3),
nn.BatchNorm2d(n3x3),
nn.ReLU(inplace=True)
)
# #1x1->5x5
# self.b3=nn.Sequential(
# nn.Conv2d(input_channels,n5x5_reduce,kernel_size=1),
# nn.BatchNorm2d(n5x5_reduce),
# nn.ReLU(inplace=True),
# nn.Conv2d(n5x5_reduce,n5x5,kernel_size=5),
# nn.BatchNorm2d(n5x5),
# nn.ReLU(inplace=True)
# )
#1x1->5x5 使用2个3x3
self.b3=nn.Sequential(
nn.Conv2d(input_channels,n5x5_reduce,kernel_size=1),
nn.BatchNorm2d(n5x5_reduce),
nn.ReLU(inplace=True),
nn.Conv2d(n5x5_reduce,n5x5,kernel_size=3,padding=1),
nn.BatchNorm2d(n5x5,n5x5),
nn.ReLU(inplace=True),
nn.Conv2d(n5x5,n5x5,kernel_size=3,padding=1),
nn.BatchNorm2d(n5x5),
nn.ReLU(inplace=True),
)
self.b4=nn.Sequential(
nn.MaxPool2d(3,stride=1,padding=1),
nn.Conv2d(input_channels,pool_proj,kernel_size=1),
nn.BatchNorm2d(pool_proj),
nn.ReLU(inplace=True)
)
def forward(self,x):
return torch.cat([self.b1(x),self.b2(x),self.b3(x),self.b4(x)],dim=1)
class GoogleNet(nn.Module):
def __init__(self,num_class=100):
super(GoogleNet, self).__init__()
self.prelayer=nn.Sequential(
nn.Conv2d(3,64,kernel_size=3,padding=1,bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64,64,kernel_size=3,padding=1,bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64,192,kernel_size=3,padding=1,bias=False),
nn.BatchNorm2d(192),
nn.ReLU(inplace=True),
)
self.a3=Inception(192,64,96,128,16,32,32)
self.b3=Inception(256,128,128,192,32,96,64)
self.maxpool=nn.MaxPool2d(3,stride=2,padding=1)
self.a4=Inception(480,192,96,208,16,48,64)
self.b4=Inception(512,160,112,224,24,64,64)
self.c4=Inception(512,128,128,256,24,64,64)
self.d4=Inception(512,112,144,288,32,64,64)
self.e4=Inception(528,256,160,320,32,128,128)
self.a5=Inception(832,256,160,320,32,128,128)
self.b5=Inception(832,384,192,384,48,128,128)
#input feature size 8*8*1024
self.avgpool=nn.AdaptiveAvgPool2d((1,1))
self.dropout=nn.Dropout2d(p=0.4)
self.linear=nn.Linear(1024,num_class)
def forward(self,x):
x=self.prelayer(x)
x=self.maxpool(x)
x=self.a3(x)
x=self.b3(x)
x=self.maxpool(x)
x=self.a4(x)
x=self.b4(x)
x=self.c4(x)
x=self.d4(x)
x=self.e4(x)
x=self.maxpool(x)
x=self.a5(x)
x=self.b5(x)
x=self.avgpool(x)
x=self.dropout(x)
x=x.view(x.size()[0],-1)
x=self.linear(x)
return x
def googlenet():
return GoogleNet()
print(googlenet())
1.nn.AdaptiveAvgPool2d
只用给出输出数据的大小,自适应的给出核的大小和步长。
3.InceptionV3
https://arxiv.org/pdf/1512.00567v3.pdf
import torch
import torch.nn as nn
class BasicConv2d(nn.Module):
def __init__(self, input_channels, output_channels, **kwargs):
super(BasicConv2d, self).__init__()
self.conv = nn.Conv2d(input_channels, output_channels, bias=False, **kwargs)
self.bn = nn.BatchNorm2d(output_channels)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.conv(x)
x = self.bn(x)
x = self.relu(x)
return x
class InceptionA(nn.Module):
def __init__(self, input_channels, pool_features):
super(InceptionA, self).__init__()
self.branch1x1 = BasicConv2d(input_channels, 64, kernel_size=1)
self.branch3x3 = nn.Sequential(
BasicConv2d(input_channels, 64, kernel_size=1),
BasicConv2d(64, 96, kernel_size=3, padding=1),
BasicConv2d(96, 96, kernel_size=3, padding=1),
)
self.branch5x5 = nn.Sequential(
BasicConv2d(input_channels, 48, kernel_size=1),
BasicConv2d(48, 64, kernel_size=5, padding=2)
)
self.branchpool = nn.Sequential(
nn.AvgPool2d(kernel_size=3, stride=1, padding=1),
BasicConv2d(input_channels, pool_features, kernel_size=1) # todo size大小改变
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5(x)
branch3x3 = self.branch3x3(x)
branchpool = self.branchpool(x)
outputs = [branch1x1, branch5x5, branch3x3, branchpool]
return torch.cat(outputs, 1)
class InceptionB(nn.Module):
def __init__(self, input_channels):
super(InceptionB, self).__init__()
self.branch3x3 = BasicConv2d(input_channels, 384, kernel_size=3, stride=2)
self.branch3x3stack = nn.Sequential(
BasicConv2d(input_channels, 64, kernel_size=1),
BasicConv2d(64, 96, kernel_size=3, padding=1),
BasicConv2d(96, 96, kernel_size=3, stride=2)
)
self.branchpool = nn.MaxPool2d(kernel_size=3, stride=2)
def forward(self, x):
branch3x3 = self.branch3x3(x)
branch3x3stack = self.branch3x3stack(x)
branchpool = self.branchpool(x)
outputs = [branch3x3, branch3x3stack, branchpool]
return torch.cat(outputs, 1)
class InceptionC(nn.Module):
def __init__(self, input_channels, channels_7x7):
super(InceptionC, self).__init__()
self.branch1x1 = BasicConv2d(input_channels, 192, kernel_size=1)
c7 = channels_7x7
self.branch7x7 = nn.Sequential(
BasicConv2d(input_channels, c7, kernel_size=1),
BasicConv2d(c7, 192, kernel_size=(1, 7), padding=(0, 3)), # todo 顺序改变
BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0)),
)
self.branch7x7stack = nn.Sequential(
BasicConv2d(input_channels, c7, kernel_size=1),
BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0)),
BasicConv2d(c7, c7, kernel_size=(1, 7), padding=(0, 3)),
BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0)),
BasicConv2d(c7, 192, kernel_size=(1, 7), padding=(0, 3))
)
self.branch_pool = nn.Sequential(
nn.AvgPool2d(kernel_size=3, stride=1, padding=1),
BasicConv2d(input_channels, 192, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch7x7 = self.branch7x7(x)
branch7x7stack = self.branch7x7stack(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch7x7, branch7x7stack, branch_pool]
return torch.cat(outputs, 1)
class InceptionD(nn.Module):
def __init__(self, input_channels):
super(InceptionD, self).__init__()
self.brchan3x3 = nn.Sequential(
BasicConv2d(input_channels, 192, kernel_size=1),
BasicConv2d(192, 320, kernel_size=3, stride=2)
)
self.brchan7x7 = nn.Sequential(
BasicConv2d(input_channels, 192, kernel_size=1),
BasicConv2d(192, 192, kernel_size=(1, 7), padding=(0, 3)),
BasicConv2d(192, 192, kernel_size=(7, 1), padding=(3, 0)),
BasicConv2d(192, 192, kernel_size=3, stride=2)
)
self.brchan_pool = nn.MaxPool2d(kernel_size=3, stride=2) # todo avg
def forward(self, x):
branch3x3 = self.brchan3x3(x)
branch7x7 = self.brchan7x7(x)
branch_pool = self.brchan_pool(x)
outputs = [branch3x3, branch7x7, branch_pool]
return torch.cat(outputs, 1)
class InceptionE(nn.Module):
def __init__(self, input_channels):
super(InceptionE, self).__init__()
self.branch1x1 = BasicConv2d(input_channels, 320, kernel_size=1)
self.branch3x3_1 = BasicConv2d(input_channels, 384, kernel_size=1)
self.branch3x3_2a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))
self.branch3x3_2b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))
self.branch3x3stack_1 = BasicConv2d(input_channels, 448, kernel_size=1)
self.branch3x3stack_2 = BasicConv2d(448, 384, kernel_size=3)
self.branch3x3stack_3a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))
self.branch3x3stack_3b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))
self.branch_pool = nn.Sequential(
nn.AvgPool2d(kernel_size=3, stride=1, padding=1),
BasicConv2d(input_channels, 192, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3_1(x)
branch3x3 = [
self.branch3x3_2a(branch3x3),
self.branch3x3_2b(branch3x3)
]
branch3x3 = torch.cat(branch3x3, 1)
branch3x3stack = self.branch3x3stack_1(x)
branch3x3stack = self.branch3x3stack_2(branch3x3stack)
branch3x3stack = [
self.branch3x3stack_3a(branch3x3stack),
self.branch3x3stack_3b(branch3x3stack)
]
branch3x3stack = torch.cat(branch3x3stack, 1)
branchpool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch3x3stack, branchpool]
return torch.cat(outputs, 1)
class InceptionV3(nn.Module):
def __init__(self, num_classes=100):
super(InceptionV3, self).__init__()
self.Conv2d_1a_3x3 = BasicConv2d(3, 32, kernel_size=3, stride=2) # todo stride=1
self.Conv2d_2a_3x3 = BasicConv2d(32, 32, kernel_size=3, padding=1)
self.Conv2d_2b_3x3 = BasicConv2d(32, 64, kernel_size=3, padding=1)
self.Maxpool_3x3 = nn.MaxPool2d(kernel_size=3, stride=2)
self.Conv2d_3b_1x1 = BasicConv2d(64, 80, kernel_size=1)
self.Conv2d_4a_3x3 = BasicConv2d(80, 192, kernel_size=3)
# naive inception module
self.Mixed_5b = InceptionA(192, pool_features=32)
self.Mixed_5c = InceptionA(256, pool_features=64)
self.Mixed_5d = InceptionA(288, pool_features=64)
# downsample
self.Mixed_6a = InceptionB(288)
self.Mixed_6b = InceptionC(768, channels_7x7=128)
self.Mixed_6c = InceptionC(768, channels_7x7=160)
self.Mixed_6d = InceptionC(768, channels_7x7=160)
self.Mixed_6e = InceptionC(768, channels_7x7=192)
# downsample
self.Mixed_7a = InceptionD(768)
self.Mixed_7b = InceptionE(1280)
self.Mixed_7c = InceptionE(2048)
# 6*6 feature size
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.dropout = nn.Dropout2d()
self.linear = nn.Linear(2048, num_classes)
def forward(self, x):
# 32 -> 30
x = self.Conv2d_1a_3x3(x)
x = self.Conv2d_2a_3x3(x)
x = self.Conv2d_2b_3x3(x)
x = self.Maxpool_3x3(x)
x = self.Conv2d_3b_1x1(x)
x = self.Conv2d_4a_3x3(x)
x = self.Maxpool_3x3(x)
# 30 -> 30
x = self.Mixed_5b(x)
x = self.Mixed_5c(x)
x = self.Mixed_5d(x)
# 30 -> 14
# Efficient Grid Size Reduction to avoid representation
# bottleneck
x = self.Mixed_6a(x)
# 14 -> 14
# """In practice, we have found that employing this factorization does not
# work well on early layers, but it gives very good results on medium
# grid-sizes (On m × m feature maps, where m ranges between 12 and 20).
# On that level, very good results can be achieved by using 1 × 7 convolutions
# followed by 7 × 1 convolutions."""
x = self.Mixed_6b(x)
x = self.Mixed_6c(x)
x = self.Mixed_6d(x)
x = self.Mixed_6e(x)
# 14 -> 6
# Efficient Grid Size Reduction
x = self.Mixed_7a(x)
# 6 -> 6
# We are using this solution only on the coarsest grid,
# since that is the place where producing high dimensional
# sparse representation is the most critical as the ratio of
# local processing (by 1 × 1 convolutions) is increased compared
# to the spatial aggregation."""
x = self.Mixed_7b(x)
x = self.Mixed_7c(x)
# 6 -> 1
x = self.avgpool(x)
x = self.dropout(x)
x = x.view(x.size(0), -1)
x = self.linear(x)
return x
def inceptionv3():
return InceptionV3()
print(inceptionv3())
1.inceptionV3参考资料
https://blog.csdn.net/Student_PAN/article/details/105246485?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-1&spm=1001.2101.3001.4242
B1model1、model2、model3 是InceptionA
B2model1 是InceptionB
B2model2、model3、model4、model5 是 InceptionC
B3model1 是InceptionD
B3model2、model3 是InceptionE
4.InceptionV4、Inception_resnet_v2
https://arxiv.org/pdf/1602.07261.pdf
https://blog.csdn.net/zzc15806/article/details/83504130
import torch.nn as nn
import torch
class BasicConv2d(nn.Module):
def __init__(self,input_channels,output_channels,**kwargs):
super(BasicConv2d, self).__init__()
self.conv=nn.Conv2d(input_channels,output_channels,bias=False,**kwargs)
self.bn=nn.BatchNorm2d(output_channels)
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
x=self.conv(x)
x=self.bn(x)
x=self.relu(x)
return x
class Inception_Stem(nn.Module):
# figure3
def __init__(self,input_channels):
super(Inception_Stem, self).__init__()
self.conv1=nn.Sequential(
BasicConv2d(input_channels,32,kernel_size=3,stride=2),
BasicConv2d(32,32,kernel_size=3),
BasicConv2d(32,64,kernel_size=3)
)
self.branch3x3_conv=BasicConv2d(64,96,kernel_size=3,stride=2)
self.branch3x3_maxpool=nn.MaxPool2d(kernel_size=3,stride=2)
self.branch7x7a=nn.Sequential(
BasicConv2d(160,64,kernel_size=1),
BasicConv2d(64,64,kernel_size=(7,1)),
BasicConv2d(64,64,kernel_size=(1,7)),
BasicConv2d(64,96,kernel_size=3)
)
self.branch7x7b=nn.Sequential(
BasicConv2d(160,64,kernel_size=1),
BasicConv2d(64,96,kernel_size=3)
)
self.branchpool=nn.MaxPool2d(kernel_size=3,stride=2)
self.branchconv=BasicConv2d(192,192,kernel_size=3)
def forward(self,x):
x=self.conv1(x)
x=[
self.branch3x3_conv(x),
self.branch3x3_maxpool(x)
]
x=torch.cat(x,1)
x=[
self.branch7x7a(x),
self.branch7x7b(x)
]
x=torch.cat(x,1)
x=[
self.branchpool(x),
self.branchconv(x)
]
x=torch.cat(x,1)
return x
class InceptionA(nn.Module):
#figure 4
def __init__(self,input_channels):
super(InceptionA, self).__init__()
self.branchpool=nn.Sequential(
nn.AvgPool2d(kernel_size=3,stride=1,padding=1),
BasicConv2d(input_channels,96,kernel_size=1)
)
self.branch1x1=BasicConv2d(input_channels,96,kernel_size=1)
self.branch3x3=nn.Sequential(
BasicConv2d(input_channels,64,kernel_size=1),
BasicConv2d(64,96,kernel_size=3)
)
self.branch3x3stack=nn.Sequential(
BasicConv2d(input_channels,64,kernel_size=1),
BasicConv2d(64,96,kernel_size=3),
BasicConv2d(96,96,kernel_size=3)
)
def forward(self,x):
x=[
self.branchpool(x),
self.branch1x1(x),
self.branch3x3(x),
self.branch3x3stack(x)
]
return torch.cat(x,1)
class ReductionA(nn.Module):
#Figure 7
def __init__(self,input_channels,k,l,m,n):
super(ReductionA, self).__init__()
self.branch3x3stack=nn.Sequential(
BasicConv2d(input_channels,k,kernel_size=1),
BasicConv2d(k,l,kernel_size=3),
BasicConv2d(l,m,kernel_size=3,stride=2)
)
self.branch3x3=BasicConv2d(input_channels,n,kernel_size=3,stride=2)
self.branchpool=nn.MaxPool2d(kernel_size=3,stride=2)
self.output_channels=input_channels+n+m
def forward(self,x):
x=[
self.branchpool(x),
self.branch3x3(x),
self.branch3x3stack(x)
]
return torch.cat(x,1)
class InceptionB(nn.Module):
def __init__(self,input_channels):
super(InceptionB, self).__init__()
self.branchpool=nn.Sequential(
nn.AvgPool2d(3,stride=1,padding=1),
BasicConv2d(input_channels,128,kernel_size=1)
)
self.branch1x1=BasicConv2d(input_channels,384,kernel_size=1)
self.branch7x7=nn.Sequential(
BasicConv2d(input_channels,192,kernel_size=1),
BasicConv2d(192,224,kernel_size=(1,7)),
BasicConv2d(224,256,kernel_size=(1,7))
)
self.branch7x7stack=nn.Sequential(
BasicConv2d(input_channels,192,kernel_size=1),
BasicConv2d(192,192,kernel_size=(1,7)),
BasicConv2d(192,224,kernel_size=(7,1)),
BasicConv2d(224,224,kernel_size=(1,7)),
BasicConv2d(224,256,kernel_size=(7,1))
)
def forward(self,x):
x=[
self.branchpool(x),
self.branch1x1(x),
self.branch7x7(x),
self.branch7x7stack(x)
]
return torch.cat(x,1)
class ReductionB(nn.Module):
#fig8
def __init__(self,input_channels):
super(ReductionB, self).__init__()
self.branchpool=nn.MaxPool2d(kernel_size=3,stride=2)
self.branch3x3=nn.Sequential(
BasicConv2d(input_channels,192,kernel_size=1),
BasicConv2d(192,192,kernel_size=3,stride=2)
)
self.branch3x3stack=nn.Sequential(
BasicConv2d(input_channels,256,kernel_size=1),
BasicConv2d(256,256,kernel_size=(1,7)),
BasicConv2d(256,320,kernel_size=(7,1)),
BasicConv2d(320,320,kernel_size=3,stride=2)
)
def forward(self,x):
x=[
self.branchpool(x),
self.branch3x3(x),
self.branch3x3stack(x)
]
return torch.cat(x,1)
class InceptionC(nn.Module):
def __init__(self, input_channels):
#"""Figure 6. The schema for 8×8 grid modules of the pure
#Inceptionv4 network. This is the Inception-C block of Figure 9."""
super(InceptionC, self).__init__()
self.branchpool=nn.Sequential(
nn.AvgPool2d(kernel_size=3,stride=1,padding=1),
BasicConv2d(input_channels,256,kernel_size=1)
)
self.branch1x1=BasicConv2d(input_channels,256,kernel_size=1)
self.branch3x3=BasicConv2d(input_channels,384,kernel_size=1)
self.branch3x3a=BasicConv2d(384,256,kernel_size=(1,3))
self.branch3x3b=BasicConv2d(384,256,kernel_size=(3,1))
self.branch3x3stack=nn.Sequential(
BasicConv2d(input_channels,384,kernel_size=1),
BasicConv2d(384,448,kernel_size=(1,3)),
BasicConv2d(448,512,kernel_size=(3,1)),
)
self.branch3x3stacka=BasicConv2d(512,256,kernel_size=(3,1))
self.branch3x3stackb=BasicConv2d(512,256,kernel_size=(1,3))
def forward(self,x):
branchpool=self.branchpool(x)
branch1x1=self.branch1x1(x)
branch3x3_output=self.branch3x3(x)
branch3x3_output=[
self.branch3x3a(branch3x3_output),
self.branch3x3b(branch3x3_output)
]
branch3x3_output=torch.cat(branch3x3_output,1)
branch3x3stack_output=self.branch3x3stack(x)
branch3x3stack_output=[
self.branch3x3stacka(branch3x3stack_output),
self.branch3x3stackb(branch3x3stack_output)
]
branch3x3stack_output=torch.cat(branch3x3stack_output,1)
output=[
branchpool,
branch1x1,
branch3x3_output,
branch3x3stack_output
]
return torch.cat(output,1)
class InceptionV4(nn.Module):
def __init__(self, A, B, C, k=192, l=224, m=256, n=384, class_nums=100):
super(InceptionV4, self).__init__()
self.stem=Inception_Stem(3)
self.inception_a=self._generate_inception_module(384,384,A,InceptionA)
self.reduction_a=ReductionA(384,k,l,m,n)
output_channels = self.reduction_a.output_channels
self.inception_b=self._generate_inception_module(output_channels,1024,B,InceptionB)
self.reduction_b=ReductionB(1024)
self.inception_c=self._generate_inception_module(1536,1536,C,InceptionC)
self.avgpool=nn.AvgPool2d(7)
self.dropout=nn.Dropout2d(1-0.8)
self.linear=nn.Linear(1536,class_nums)
def forward(self, x):
x = self.stem(x)
x = self.inception_a(x)
x = self.reduction_a(x)
x = self.inception_b(x)
x = self.reduction_b(x)
x = self.inception_c(x)
x = self.avgpool(x)
x = self.dropout(x)
x = x.view(-1, 1536)
x = self.linear(x)
return x
@staticmethod
def _generate_inception_module(input_channels, output_channels, block_num, block):
layers=nn.Sequential()
for l in range(block_num):
layers.add_module("{}_{}".format(block.__name__,l),block(input_channels))
input_channels=output_channels
return layers
class InceptionResNetA(nn.Module):
def __init__(self,input_channels):
super(InceptionResNetA, self).__init__()
self.branch1x1=BasicConv2d(input_channels,32,kernel_size=1)
self.branch3x3=nn.Sequential(
BasicConv2d(input_channels,32,kernel_size=1),
BasicConv2d(32,32,kernel_size=3),
)
self.branch3x3stack=nn.Sequential(
BasicConv2d(input_channels,32,kernel_size=1),
BasicConv2d(32,48,kernel_size=3),
BasicConv2d(48,64,kernel_size=3),
)
self.reduction1x1=nn.Conv2d(128,384,kernel_size=1)
self.shortcut=nn.Conv2d(input_channels,384,kernel_size=1)
self.bn=nn.BatchNorm2d(384)
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
residual=[
self.branch1x1(x),
self.branch3x3(x),
self.branch3x3stack(x)
]
residual=torch.cat(residual,1)
residual=self.reduction1x1(residual)
shortcut=self.shortcut(x)
output=self.bn(shortcut+residual)
output=self.relu(output)
return output
class InceptionResNetB(nn.Module):
#FIG 17
def __init__(self,input_channels):
super(InceptionResNetB, self).__init__()
self.branch7x7=nn.Sequential(
BasicConv2d(input_channels,128,kernel_size=1),
BasicConv2d(128,160,kernel_size=(1,7)),
BasicConv2d(160,192,kernel_size=(7,1)),
)
self.branch1x1=BasicConv2d(input_channels,192,kernel_size=1)
self.reduction1x1=nn.Conv2d(384,1154,kernel_size=1)
self.shortcut=nn.Conv2d(input_channels,1154,kernel_size=1)
self.bn=nn.BatchNorm2d(1154)
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
residual=[
self.branch1x1(x),
self.branch7x7(x)
]
residual=torch.cat(residual,1)
residual=self.reduction1x1(residual)*0.1
shortcut=self.shortcut(x)
output=self.bn(residual+shortcut)
output=self.relu(output)
return output
class InceptionResNetC(nn.Module):
def __init__(self,input_channels):
super(InceptionResNetC, self).__init__()
self.branch3x3=nn.Sequential(
BasicConv2d(input_channels,192,kernel_size=1),
BasicConv2d(192,224,kernel_size=(1,3)),
BasicConv2d(224,256,kernel_size=(3,1))
)
self.branch1x1=BasicConv2d(input_channels,192,kernel_size=1)
self.reduction1x1=nn.Conv2d(448,2048,kernel_size=1)
self.shorcut=nn.Conv2d(input_channels,2048,kernel_size=1)
self.bn=nn.BatchNorm2d(2048)
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
residual=[
self.branch1x1(x),
self.branch3x3(x)
]
residual=torch.cat(residual,1)
residual=self.reduction1x1(residual)*0.1
shorcut=self.shorcut(x)
output=self.bn(shorcut+residual)
output=self.relu(output)
return output
class InceptionResNetReductionA(nn.Module):
#"""Figure 7. The schema for 35 × 35 to 17 × 17 reduction module.
#Different variants of this blocks (with various number of filters)
#are used in Figure 9, and 15 in each of the new Inception(-v4, - ResNet-v1,
#-ResNet-v2) variants presented in this paper. The k, l, m, n numbers
#represent filter bank sizes which can be looked up in Table 1.
def __init__(self, input_channels, k, l, m, n):
super().__init__()
self.branch3x3stack = nn.Sequential(
BasicConv2d(input_channels, k, kernel_size=1),
BasicConv2d(k, l, kernel_size=3, padding=1),
BasicConv2d(l, m, kernel_size=3, stride=2)
)
self.branch3x3 = BasicConv2d(input_channels, n, kernel_size=3, stride=2)
self.branchpool = nn.MaxPool2d(kernel_size=3, stride=2)
self.output_channels = input_channels + n + m
def forward(self, x):
x = [
self.branch3x3stack(x),
self.branch3x3(x),
self.branchpool(x)
]
return torch.cat(x, 1)
class InceptionResNetReductionB(nn.Module):
#"""Figure 18. The schema for 17 × 17 to 8 × 8 grid-reduction module.
#Reduction-B module used by the wider Inception-ResNet-v1 network in
#Figure 15."""
#I believe it was a typo(Inception-ResNet-v1 should be Inception-ResNet-v2)
def __init__(self, input_channels):
super().__init__()
self.branchpool = nn.MaxPool2d(3, stride=2)
self.branch3x3a = nn.Sequential(
BasicConv2d(input_channels, 256, kernel_size=1),
BasicConv2d(256, 384, kernel_size=3, stride=2)
)
self.branch3x3b = nn.Sequential(
BasicConv2d(input_channels, 256, kernel_size=1),
BasicConv2d(256, 288, kernel_size=3, stride=2)
)
self.branch3x3stack = nn.Sequential(
BasicConv2d(input_channels, 256, kernel_size=1),
BasicConv2d(256, 288, kernel_size=3, padding=1),
BasicConv2d(288, 320, kernel_size=3, stride=2)
)
def forward(self, x):
x = [
self.branch3x3a(x),
self.branch3x3b(x),
self.branch3x3stack(x),
self.branchpool(x)
]
x = torch.cat(x, 1)
return x
class InceptionResNetV2(nn.Module):
def __init__(self, A, B, C, k=256, l=256, m=384, n=384, class_nums=100):
super().__init__()
self.stem = Inception_Stem(3)
self.inception_resnet_a = self._generate_inception_module(384, 384, A, InceptionResNetA)
self.reduction_a = InceptionResNetReductionA(384, k, l, m, n)
output_channels = self.reduction_a.output_channels
self.inception_resnet_b = self._generate_inception_module(output_channels, 1154, B, InceptionResNetB)
self.reduction_b = InceptionResNetReductionB(1154)
self.inception_resnet_c = self._generate_inception_module(2146, 2048, C, InceptionResNetC)
#6x6 featuresize
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
#"""Dropout (keep 0.8)"""
self.dropout = nn.Dropout2d(1 - 0.8)
self.linear = nn.Linear(2048, class_nums)
def forward(self, x):
x = self.stem(x)
x = self.inception_resnet_a(x)
x = self.reduction_a(x)
x = self.inception_resnet_b(x)
x = self.reduction_b(x)
x = self.inception_resnet_c(x)
x = self.avgpool(x)
x = self.dropout(x)
x = x.view(-1, 2048)
x = self.linear(x)
return x
@staticmethod
def _generate_inception_module(input_channels, output_channels, block_num, block):
layers = nn.Sequential()
for l in range(block_num):
layers.add_module("{}_{}".format(block.__name__, l), block(input_channels))
input_channels = output_channels
return layers
def inceptionv4():
return InceptionV4(4, 7, 3)
def inception_resnet_v2():
return InceptionResNetV2(5, 10, 5)
print(inception_resnet_v2())
5.ResNet
import torch.nn as nn
import torch
class BasicBlock(nn.Module):
expansion = 1
def __init__(self,input_channels,out_channels, stride=1):
super(BasicBlock, self).__init__()
self.residual_function=nn.Sequential(
nn.Conv2d(input_channels,out_channels,kernel_size=3,stride=stride),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels,out_channels,kernel_size=3,stride=stride),
nn.BatchNorm2d(out_channels*BasicBlock.expansion)
)
self.shortcut=nn.Sequential()
if stride!=1 or input_channels!=BasicBlock.expansion*out_channels:
self.shortcut=nn.Sequential(
nn.Conv2d(input_channels,out_channels*BasicBlock.expansion,kernel_size=1,stride=stride),
nn.BatchNorm2d(out_channels*BasicBlock.expansion)
)
def forward(self,x):
return nn.ReLU(inplace=True)(self.residual_function(x)+self.shortcut(x))
class BottleNeck(nn.Module):
expansion=4
def __init__(self,input_channels,out_chaneels,stride=1):
super(BottleNeck, self).__init__()
self.residul_function=nn.Sequential(
nn.Conv2d(input_channels,out_chaneels,kernel_size=1,stride=stride),
nn.BatchNorm2d(out_chaneels),
nn.ReLU(inplace=True),
nn.Conv2d(out_chaneels,out_chaneels,kernel_size=3,stride=stride),
nn.BatchNorm2d(out_chaneels),
nn.ReLU(inplace=True),
nn.Conv2d(out_chaneels,out_chaneels*BottleNeck.expansion,kernel_size=1,stride=stride),
nn.BatchNorm2d(out_chaneels*BottleNeck.expansion)
)
self.shortcut=nn.Sequential()
if stride!=1 or input_channels!=out_chaneels*BottleNeck.expansion:
self.shortcut=nn.Sequential(
nn.Conv2d(input_channels,out_chaneels*BottleNeck.expansion,kernel_size=1,stride=stride),
nn.BatchNorm2d(out_chaneels*BottleNeck.expansion)
)
def forward(self,x):
return nn.ReLU(inplace=True)(self.residul_function(x)+self.shortcut(x))
class ResNet(nn.Module):
def __init__(self,block,num_block,num_classes=100):
super(ResNet, self).__init__()
self.in_channels=64
self.conv1=nn.Sequential(
nn.Conv2d(3,64,kernel_size=3,padding=1,bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True)
)
self.conv2_x = self._make_layer(block, 64, num_block[0], 1)
self.conv3_x = self._make_layer(block, 128, num_block[1], 2)
self.conv4_x = self._make_layer(block, 256, num_block[2], 2)
self.conv5_x = self._make_layer(block, 512, num_block[3], 2)
self.avg_pool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(512 * block.expansion, num_classes)
def _make_layer(self, block, out_channels, num_blocks, stride):
strides=[stride]+[1]*(num_blocks-1)
layers=[]
for stride in strides:
layers.append(block(self.in_channels,out_channels,stride))
self.in_channels=out_channels*block.expansion
return nn.Sequential(*layers)
def forward(self, x):
output = self.conv1(x)
output = self.conv2_x(output)
output = self.conv3_x(output)
output = self.conv4_x(output)
output = self.conv5_x(output)
output = self.avg_pool(output)
output = output.view(output.size(0), -1)
output = self.fc(output)
return output
def resnet18():
""" return a ResNet 18 object
"""
return ResNet(BasicBlock, [2, 2, 2, 2])
def resnet34():
""" return a ResNet 34 object
"""
return ResNet(BasicBlock, [3, 4, 6, 3])
def resnet50():
""" return a ResNet 50 object
"""
return ResNet(BottleNeck, [3, 4, 6, 3])
def resnet101():
""" return a ResNet 101 object
"""
return ResNet(BottleNeck, [3, 4, 23, 3])
def resnet152():
""" return a ResNet 152 object
"""
return ResNet(BottleNeck, [3, 8, 36, 3])
print(resnet152())
1.basicblock
2.bottleneck
https://arxiv.org/pdf/1512.03385v1.pdf