resnet,inception等网络核心单元代码实现

1、resnet残差网络
(1)较深的网络比较浅的网络性能更差。 一个创新的想法:如果什么也没学到,那就比以前更糟:因此提出了identity map(也称为shortcut连接)。 H(x)= x + F(x),F(x)= H(x)-x,称为残差。

(2)ResNet的深度各不相同,从18层到34、50、101到非常深的152层。

(3)不同的快捷方式,如果不更改尺寸,则可以使用identity映射。 但是在实践中,尺寸更改因此会产生“瓶颈”。 (这在基线后记中很流行,因为它可以保存参数。)

残差单元:

在这里插入图片描述

跨层连接:要求输入x:feature map的shape与输出F(x):feature map 的shape一样。

可能存在的情况:

①输入x与输出F(x) 的shape一样直接相加

②输入x输出F(x) 的feature map数量及feature map尺寸不一样

如:输入x:[1, 64, 224, 224]输出F(x) :[1, 128, 112, 112]

需要对输入x通过卷积层各参数调整,确保与F(x)一致

相邻的x 与F(x)通道不一致,fp也相差一倍

import torch.nn as nn
import torch
 
 
#残差单元
class Block(nn.Module):
    def __init__(self,inch,outch,stride):
        super(Block, self).__init__()
 
        self.con1=nn.Conv2d(inch,outch,3,stride,1)
        self.con2=nn.Conv2d(outch,outch,3,1,1)
        self.relu=nn.ReLU()
        self.bn=nn.BatchNorm2d(outch)
 
        if inch!=outch:
            self.downsample=nn.Conv2d(inch,outch,1,stride)#输入与输出通道不一致,调整通道并通过步长调整特征图
        else:
            self.downsample=None
 
    def forward(self,x):
        pre=x
        out=self.con1(x)
        out=self.relu(out)
        out=self.bn(out)
        out=self.con2(out)
        out = self.bn(out)
 
        if self.downsample is not None:#
            pre=self.downsample(x)
 
        out+=pre#跨层连接相加:x+F(x)
        out = self.relu(out)
        return out
 
 
class mynet(nn.Module):
    def __init__(self,Block):
        super(mynet, self).__init__()
 
        self.layer1=nn.Sequential(nn.Conv2d(3,64,3,1,1),
                                  nn.BatchNorm2d(64),
                                  nn.MaxPool2d(2))#64,224
 
        self.layer2=self.layer(Block,64,64,3,1)
 
        self.layer3 = self.layer(Block, 64, 128,4, 2)#连续有4个残差单元除了第一个要增加通道,后面保持与上个一样
        self.layer4 = self.layer(Block, 128, 256, 6,2)
        self.layer5 = self.layer(Block, 256, 512, 3, 2)
 
    def layer(self,Block,inch,outch,blocknum,stride):
        layers=[]
        layers.append(Block(inch,outch,stride))#主要负责调整每个block的特征图及通道
        for i in range(blocknum-1):
            layers.append(Block(outch,outch,1))#普通的卷积操作并且通道一致
 
        return nn.Sequential(*layers)#以列表形式放在序列化中
 
 
 
    def forward(self,x):
        x1=self.layer1(x)
        print(x1.shape)
        x2 = self.layer2(x1)
        print(x2.shape)
        x3 = self.layer3(x2)
        print(x3.shape)
        x4 = self.layer4(x3)
        print(x4.shape)
        x5 = self.layer5(x4)
        print(x5.shape)
        return x1,x2
 
 
 
 
x=torch.randn(1,3,448,448)
model=mynet(Block)
y1,y2=model(x)
# print(y1.shape,y2.shape)

2、Googlenet中inception单元
(1)除了增加网络深度之外(对于googlenet v1为22层),还会增加网络的宽度

(2)引入较小的内核,1 * 1卷积,减小尺寸并保存参数。 参数:AlexNet ~ 12 GoogLeNet, VGG ~ 3 AlexNet

(3)初始模块很容易添加或删除,它是模仿人的大脑以建立稀疏连接。
在这里插入图片描述

import torch
import torch.nn as nn
 
 
 
class inception(nn.Module):
    def __init__(self,inch,outch):
        super(inception, self).__init__()
        self.con1=nn.Conv2d(inch,outch,1,1)
        self.con2=nn.Conv2d(inch,outch,3,1,1)
        self.con3=nn.Conv2d(inch,outch,5,1,2)
        self.maxpool=nn.MaxPool2d(3,1,1)
 
    def forward(self,x):
        out1=self.con1(x)
        out2=self.con2(x)
        out3=self.con3(x)
        out4=self.maxpool(x)
        out=torch.cat((out1,out2,out3,out4),dim=1)#特征融合
        return out
 
 
 
 
 
 
class mynet(nn.Module):
    def __init__(self,inception):
        super(mynet, self).__init__()
        self.layer1=nn.Sequential(
            nn.Conv2d(3, 64, 3, 1, 1),
            nn.MaxPool2d(2)
        )
 
        self.layer2=inception(64,64)
    def forward(self,x):
        x=self.layer1(x)
        x=self.layer2(x)
 
        return x
 
 
 
x=torch.randn(1,3,448,448)
model=mynet(inception)
y=model(x)
print(y.shape)

3、Yolov3
①无yolo层的darknet53 主干网络backbone:
在这里插入图片描述

import torch
import torch.nn as nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
    def __init__(self,inch,outch):
        super(ResidualBlock, self).__init__()
 
        self.conv1=nn.Sequential(nn.Conv2d(inch,outch,1,1),
                                 nn.BatchNorm2d(outch),
                                 nn.LeakyReLU())
        self.conv2=nn.Sequential(nn.Conv2d(outch,inch,3,1,1),
                                nn.BatchNorm2d(inch),
                                nn.LeakyReLU())
 
    def forward(self, x):
        identity=x
        out=self.conv1(x)
        out=self.conv2(out)
 
        out+=identity
        return out
 
class Darknet53(nn.Module):
    def __init__(self,ResidualBlock):
        super(Darknet53, self).__init__()
        self.firstblock=nn.Sequential(nn.Conv2d(3,32,3,1,1),
                                      nn.BatchNorm2d(32),
                                      nn.LeakyReLU()
                                      )
        self.conv1 = nn.Conv2d(32, 64, 3, 2, 1)
        self.resblock1=self.block(ResidualBlock,32,64,1)
        self.conv2 = nn.Conv2d(64, 128, 3, 2, 1)
        self.resblock2 = self.block(ResidualBlock, 64, 128, 2)
        self.conv3 = nn.Conv2d(128, 256, 3, 2, 1)
        self.resblock3 = self.block(ResidualBlock, 128, 256, 8)
        self.conv4 = nn.Conv2d(256, 512, 3, 2, 1)
        self.resblock4 = self.block(ResidualBlock, 256, 512, 8)
        self.conv5 = nn.Conv2d(512, 1024, 3, 2, 1)
        self.resblock5 = self.block(ResidualBlock, 512, 1024, 4)
 
    def block(self,ResidualBlock,inch, outch, numblock):
 
        layers=[]
        # layers.append(nn.Conv2d(inch,outch,3,2,1))
        for i in range(numblock - 1):
            layers.append(ResidualBlock(outch,inch))
        return nn.Sequential(*layers)
 
 
 
 
    def forward(self,x):
        out=self.firstblock(x)
 
        out=self.conv1(out)
        out=self.resblock1(out)
 
        out = self.conv2(out)
        out = self.resblock2(out)
 
        out = self.conv3(out)
        fp_52 = self.resblock3(out)
 
        out = self.conv4(fp_52)
        fp_26 = self.resblock4(out)
 
        out = self.conv5(fp_26)
        fp_13 = self.resblock5(out)
 
 
        return fp_52,fp_26,fp_13
 
 
inputs=torch.randn(1,3,416,416)
model=Darknet53(ResidualBlock)
sc1,sc2,sc3=model(inputs)
print(sc1.shape,sc2.shape,sc3.shape) 

②含有YOLO层的网络
在这里插入图片描述
将输出调整为:(batch,3*(x,y,w,h,conf,cls1…cls20),fp,fp)

这里20类加上两个坐标点,宽高,置信度共25,fp为 feature map的大小。

import torch
import torch.nn as nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
    def __init__(self,inch,outch):
        super(ResidualBlock, self).__init__()
        self.conv1=nn.Sequential(nn.Conv2d(inch,outch,1,1),
                                 nn.BatchNorm2d(outch),
                                 nn.LeakyReLU())
        self.conv2=nn.Sequential(nn.Conv2d(outch,inch,3,1,1),
                                nn.BatchNorm2d(inch),
                                nn.LeakyReLU())
    def forward(self, x):
        identity=x
        out=self.conv1(x)
        out=self.conv2(out)
        out+=identity
        return out
class UpsampleLayer(nn.Module):
    def __init__(self):
        super(UpsampleLayer, self).__init__()
    def forward(self, x):
        return F.interpolate(x, scale_factor=2, mode='nearest')
class ConvolutionalSetLayer(nn.Module):
    def __init__(self,inch,outch):
        super(ConvolutionalSetLayer, self).__init__()
        self.conv=nn.Sequential(
            nn.Conv2d(inch, outch, 1, 1),
            nn.Conv2d(outch, inch, 3, 1, 1),
            nn.Conv2d(inch, outch, 1, 1),
            nn.Conv2d(outch, inch, 3, 1, 1),
            nn.Conv2d(inch, outch, 1, 1)
        )
    def forward(self,x):
        return self.conv(x)
class Darknet53(nn.Module):
    def __init__(self,ResidualBlock):
        super(Darknet53, self).__init__()
        self.firstblock=nn.Sequential(nn.Conv2d(3,32,3,1,1),
                                      nn.BatchNorm2d(32),
                                      nn.LeakyReLU()
                                      )
        self.conv1 = nn.Conv2d(32, 64, 3, 2, 1)
        self.resblock1=self.block(ResidualBlock,32,64,1)
        self.conv2 = nn.Conv2d(64, 128, 3, 2, 1)
        self.resblock2 = self.block(ResidualBlock, 64, 128, 2)
        self.conv3 = nn.Conv2d(128, 256, 3, 2, 1)
        self.resblock3 = self.block(ResidualBlock, 128, 256, 8)
        self.conv4 = nn.Conv2d(256, 512, 3, 2, 1)
        self.resblock4 = self.block(ResidualBlock, 256, 512, 8)
        self.conv5 = nn.Conv2d(512, 1024, 3, 2, 1)
        self.resblock5 = self.block(ResidualBlock, 512, 1024, 4)
        self.conset13=nn.Sequential(ConvolutionalSetLayer(1024,512))
        self.conset26 = nn.Sequential(ConvolutionalSetLayer(768, 256))
        self.conset52 = nn.Sequential(ConvolutionalSetLayer(384, 128))
        self.yololy1=nn.Sequential(
            nn.Conv2d(512, 1024, 3, 1, 1),
            nn.BatchNorm2d(1024),
            nn.LeakyReLU(),
            nn.Conv2d(1024,75,1,1)
        )
        self.yololy2 = nn.Sequential(
            nn.Conv2d(256, 512, 3, 1, 1),
            nn.BatchNorm2d(512),
            nn.LeakyReLU(),
            nn.Conv2d(512, 75, 1, 1)
        )
        self.yololy3 = nn.Sequential(
            nn.Conv2d(128, 256, 3, 1, 1),
            nn.BatchNorm2d(256),
            nn.LeakyReLU(),
            nn.Conv2d(256, 75, 1, 1)
        )
        self.up1=nn.Sequential(
            nn.Conv2d(512, 256, 1, 1),
            UpsampleLayer()
        )
        self.up2 = nn.Sequential(
            nn.Conv2d(256, 128,1, 1),
            UpsampleLayer()
        )
    def block(self,ResidualBlock,inch, outch, numblock):
        layers=[]
        # layers.append(nn.Conv2d(inch,outch,3,2,1))
        for i in range(numblock - 1):
            layers.append(ResidualBlock(outch,inch))
        return nn.Sequential(*layers)
    def forward(self,x):
        out=self.firstblock(x)
        out=self.conv1(out)
        out=self.resblock1(out)
        out = self.conv2(out)
        out = self.resblock2(out)
        out = self.conv3(out)
        fp_52 = self.resblock3(out)
        out = self.conv4(fp_52)
        fp_26 = self.resblock4(out)
        out = self.conv5(fp_26)
        fp_13 = self.resblock5(out)
        convset13=self.conset13(fp_13)
        yoloout1=self.yololy1(convset13)
        up1=self.up1(convset13)
        route1=torch.cat((up1,fp_26),1)
        convset26=self.conset26(route1)
        yoloout2=self.yololy2(convset26)
        up2=self.up2(convset26)
        route2=torch.cat((up2,fp_52),1)
        convset52=self.conset52(route2)
        yoloout3=self.yololy3(convset52)
        return yoloout1,yoloout2,yoloout3
inputs=torch.randn(1,3,416,416)
model=Darknet53(ResidualBlock)
print(model)
sc1,sc2,sc3=model(inputs)
print(sc1.shape,sc2.shape,sc3.shape)

还有yolov4等网络结构,具体的见博客:传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值