pytorch 图像分类

Posted 东东就是我

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytorch 图像分类相关的知识,希望对你有一定的参考价值。

1.DenseNet

再一个block内,每次操作层的输入都是前面所有层的结果的结合

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchsummary import summary
class BN_Conv2d(nn.Module):
    def __init__(self,in_channels,out_channels,kernel_size,stride,padding,dilation=1,groups=1,bias=False):
        super(BN_Conv2d, self).__init__()
        self.seq=nn.Sequential(
            nn.Conv2d(in_channels,out_channels,kernel_size=kernel_size,stride=stride,padding=padding,dilation=dilation,groups=groups,bias=bias),
            nn.BatchNorm2d(out_channels)

        )

    def forward(self,x):
        return F.relu(self.seq(x))

class DenseBlock(nn.Module):
    def __init__(self,in_channels,num_layers,growth_rate):
        super(DenseBlock, self).__init__()
        self.num_layers=num_layers
        self.k0=in_channels
        self.k=growth_rate
        self.layers=self._make_layers()

    def _make_layers(self):
        layer_list=[]
        for i in range(self.num_layers):
            layer_list.append(nn.Sequential(
                BN_Conv2d(self.k0+i*self.k,4*self.k,1,1,0),
                BN_Conv2d(4*self.k,self.k,3,1,1)
            ))
        return layer_list

    def forward(self,x):
        feature=self.layers[0](x)
        out=torch.cat((x,feature),1)
        for i in range(1,len(self.layers)):
            feature=self.layers[i](out)
            out=torch.cat((feature,out),1)
        return out


class DenseNet(nn.Module):
    def __init__(self,layers,k,theta,num_class):
        super(DenseNet, self).__init__()
        self.layers=layers
        self.k=k
        self.theta=theta
        self.conv=BN_Conv2d(3,2*k,7,2,3)
        self.blocks,patches=self._make_blocks(2*k)
        self.fc=nn.Linear(patches,num_class)

    def _make_transition(self,in_chls):
        out_chls=int(self.theta*in_chls)
        return nn.Sequential(
            BN_Conv2d(in_chls,out_chls,1,1,0),
            nn.AvgPool2d(2)
        ),out_chls

    def __make_blocks(self, k0):
        """
        make block-transition structures
        :param k0:
        :return:
        """
        layers_list = []
        patches = 0
        for i in range(len(self.layers)):
            layers_list.append(DenseBlock(k0, self.layers[i], self.k))
            patches = k0 + self.layers[i] * self.k  # output feature patches from Dense Block
            if i != len(self.layers) - 1:
                transition, k0 = self.__make_transition(patches)
                layers_list.append(transition)
        return nn.Sequential(*layers_list), patches

    def forward(self, x):
        out = self.conv(x)
        out = F.max_pool2d(out, 3, 2, 1)
        # print(out.shape)
        out = self.blocks(out)
        # print(out.shape)
        out = F.avg_pool2d(out, 7)
        # print(out.shape)
        out = out.view(out.size(0), -1)
        out = F.softmax(self.fc(out))
        return out

def densenet_121(num_classes=1000):
    return DenseNet([6, 12, 24, 16], k=32, theta=0.5, num_classes=num_classes)


def densenet_169(num_classes=1000):
    return DenseNet([6, 12, 32, 32], k=32, theta=0.5, num_classes=num_classes)


def densenet_201(num_classes=1000):
    return DenseNet([6, 12, 48, 32], k=32, theta=0.5, num_classes=num_classes)


def densenet_264(num_classes=1000):
    return DenseNet([6, 12, 64, 48], k=32, theta=0.5, num_classes=num_classes)


def test():
    net = densenet_264()
    summary(net, (3, 224, 224))
    x = torch.randn((2, 3, 224, 224))
    y = net(x)
    print(y.shape)

test()

2.SENet

首先把特征图压缩成一个通道向量,然后通过降采样和上采样过滤出通道的权重,(有点像opencv里的开运算:先腐蚀再膨胀,用来消除小物体)

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

class SE(nn.Module):
    def __init__(self,in_chnls,ratio):
        super(SE, self).__init__()
        self.squeeze=nn.AdaptiveAvgPool2d((1,1))
        self.compress=nn.Conv2d(in_chnls,in_chnls//ratio,1,1,0)
        self.excitation=nn.Conv2d(in_chnls//ratio,in_chnls,1,1,0)


    def forward(self,x):
        out=self.squeeze(x)
        out=self.compress(out)
        out=F.relu(out)
        out=self.excitation(out)
        return F.sigmoid(out)


3.DarkNet

和Resnet差不多,不过resnet是一个bottleneck 先是1x1,然后3x3 最后1x1 ,darknet就两部1x1 然后3x3

import  torch.nn as nn
from torchsummary import summary
import torch.nn.functional as F
from  senet1 import  SE
class BN_Conv2d_Leaky(nn.Module):
    def __init__(self,in_channels,out_channels,kernel_size,stride,padding,dilation=1,groups=1,bias=False):
        super(BN_Conv2d_Leaky, self).__init__()
        self.seq=nn.Sequential(
            nn.Conv2d(in_channels,out_channels,kernel_size=kernel_size,stride=stride,padding=padding,dilation=dilation, groups=groups, bias=bias),
            nn.BatchNorm2d(out_channels)
        )

    def forward(self,x):
        return F.leaky_relu(self.seq(x))

class BN_Conv2d(nn.Module):
    def __init__(self,in_channels,out_channels,kernel_size,stride,padding,dilation=1,groups=1,bias=False):
        super(BN_Conv2d, self).__init__()
        self.seq=nn.Sequential(
            nn.Conv2d(in_channels,out_channels,kernel_size=kernel_size,stride=stride,padding=padding,dilation=dilation, groups=groups, bias=bias),
            nn.BatchNorm2d(out_channels)
        )

    def forward(self,x):
        return self.seq(x)

class Dark_block(nn.Module):
    def __init__(self,channels,is_se=False,inner_channnels=None):
        super(Dark_block, self).__init__()
        self.is_se=is_se
        if inner_channnels is None:
            inner_channnels=channels//2

        self.conv1=BN_Conv2d_Leaky(channels,inner_channnels,1,1,0)
        self.conv2=nn.Conv2d(inner_channnels,channels,3,1,1)
        self.bn=nn.BatchNorm2d(channels)
        if self.is_se:
            self.se=SE(channels,16)

    def forward(self,x):
        out=self.conv1(x)
        out=self.conv2(out)
        out=self.bn(out)
        if self.is_se:
            coefficient=self.se(out)
            out*=coefficient
        out+=x
        return F.leaky_relu(out)


class DarkNet(nn.Module):
    def __init__(self,layers,num_class,is_se=False):
        super(DarkNet, self).__init__()
        self.is_se=is_se
        filters=[64,128,256,512,1024]

        self.conv1 = BN_Conv2d(3, 32, 3, 1, 1)
        self.redu1 = BN_Conv2d(32, 64, 3, 2, 1)
        self.conv2=self._make_layers(filters[0],layers[0])
        self.redu2 = BN_Conv2d(filters[0], filters[1], 3, 2, 1)
        self.conv3 = self.__make_layers(filters[1], layers[1])
        self.redu3 = BN_Conv2d(filters[1], filters[2], 3, 2, 1)
        self.conv4 = self.__make_layers(filters[2], layers[2])
        self.redu4 = BN_Conv2d(filters[2], filters[3], 3, 2, 1)
        self.conv5 = self.__make_layers(filters[3], layers[3])
        self.redu5 = BN_Conv2d(filters[3], filters[4], 3, 2, 1)
        self.conv6 = self.__make_layers(filters[4], layers[4])
        self.global_pool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(filters[4], num_class)


    def _make_layers(self,num_filter,num_layers):
        layers=[]
        for _ in range(num_layers):
            layers.append(Dark_block(num_filter,self.is_se))
        return nn.Sequential(*layers)

    def forward(self, x):
        out = self.conv1(x)
        out = self.redu1(out)
        out = self.conv2(out)
        out = self.redu2(out)
        out = self.conv3(out)
        out = self.redu3(out)
        out = self.conv4(out)
        out = self.redu4(out)
        out = self.conv5(out)
        out = self.redu5(out)
        out = self.conv6(out)
        out = self.global_pool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return F.softmax(out)

def darknet_53(num_classes=1000):
    return DarkNet([1, 2, 8, 8, 4], num_classes)


net = darknet_53()
summary(net, (3, 256, 256))

4.CSPDenseNet

和DenseNet的DenseBlock差不多,不过把输入的通道砍了一半,然后经过block后再组合一起

import torch
import  torch.nn as nn
from torchsummary import summary
import torch.nn.functional as F
from  senet1 import  SE

class BN_Conv2d(nn.Module):
    def __init__(self,in_channles,out_channels,kernels_size,stride,padding,dilation=1,groups=1,bias=False):
        super(BN_Conv2d, self).__init__()
        self.seq=nn.Sequential(
            nn.Conv2d(in_channles,out_channels,kernel_size=kernels_size,stride=stride,padding=padding,dilation=dilation,groups=groups,bias=bias),
            nn.BatchNorm2d(out_channels)
        )
    def forward(self,x):
        return self.seq(x)

class DenseBlock(nn.Module):
    def __init__(self,input_channels,num_layers,grouwth_rate):
        super(DenseBlock, self).__init__()
        self.num_layers=num_layers
        self.k0=input_channels
        self.k=grouwth_rate
        self.layers=self.__make_layers()

    def __make_layers(self):
        layer_list=[]
        for i in range(self.num_layers):
            layer_list.append(nn.Sequential(
                BN_Conv2d(self.k0+i*self.k,4*self.k,1,1,0),
                BN_Conv2d(4*self.k,self.k,3,1,1)
            ))
        return layer_list

    def forward(self,x):
        feature=self.layers[0](x)
        out=torch.cat((x,feature),1)
        for i in range(1,len(self.layers)):
            feature=self4. 使用预训练的PyTorch网络进行图像分类

4. 使用预训练的PyTorch网络进行图像分类

使用Pytorch框架自己制作做数据集进行图像分类

Pytorch CIFAR10图像分类 工具函数utils篇

Pytorch加载模型并进行图像分类预测

PyTorch 完全入门指南!从线性回归逻辑回归到图像分类