分类理论

前面提到的回归可以理解为一个填空题,要求模型预测出一个值,而分类就相当于一个选择题,从已有的选项中选择一个答案

分类任务的输出

对于分类任务的输出,一般是输出一个维度为类别个数的向量,比如 猫 狗 人  那么就应该输出一个三维向量,对于标签值可以采用one-hot编码来实现。此例中:猫(1 0 0) 狗(0 1 0) 人(0 0 1),对于模型来说,输出的三维向量应该是三个不确定大小的值,因此我们需要把值映射到0-1的概率,如图:

将模型的输出经过softmax转为概率,因此最后的y撇表示,有0的概率是dog,有0.953的概率是cat,有0.047的概率是tree,当然在设计模型的时候最后不需要手动写softmax,因为softmax封装在了多分类任务的损失函数(nn.CrossEntroyloss)中,即 标签*log(概率),至此模型的输出讲完,介绍模型的输入

分类任务的输入

一个图片一般都是3*224*224,若直接把图片展平了送到线性全连接层中,参数量巨大,因此引入了卷积。卷积就是,一边卷动一边求积,用一个卷积核把一个原始图片进行卷积操作,得到图片的特征图

流程

首先先用卷积核来提取图片的特征,为了解决图片边缘特征丢失的问题,采用padding后再利用卷积核进行卷积

将6*6通过padding1变成8*8,这样子经过3*3的卷积核后就会使特征图的大小和原图保持一致

第二步,进行最大池化,意义是使得特征图的大小进一步缩小,以缩小参数量,为将来展平放入线性全连接层做准备,如图:

第三步,扁平化处理,池化后特征图变小,参数变少看,可以展平放入线性全连接层

最终流程如下:

补充知识:

原始图片经过多少个卷积核,就生成多少个特征图

批量归一化:

代码:

AlexNet代码:

import torch
import torch.nn as nn


# 获得模型参数量
def get_model_parameters(model):
    total_num = sum(p.numel() for p in model.parameters())
    trainable_num = sum(p.numel() for p in model.parameters() if p.requires_grad)
    return {'Total':total_num,'Trainable':trainable_num}


class MyModel(nn.Module):
    # class_num 最后分类的类别数量
    def __init__(self,class_num):
        super().__init__()

        '''
        输入特征图数量  输出特征图数量  卷积核大小  步长  padding
        '''
        self.conv1 = nn.Conv2d(3,64,11,4,2)
        self.pool1 = nn.MaxPool2d(3,2)

        self.conv2 = nn.Conv2d(64,192,5,1,2)
        self.pool2 = nn.MaxPool2d(3,2)

        self.conv3 = nn.Conv2d(192,384,3,1,1)
        self.conv4 = nn.Conv2d(384,256,3,1,1)
        self.conv5 = nn.Conv2d(256,256,3,1,1)

        self.pool3 = nn.MaxPool2d(3,2)
        self.pool4 = nn.AdaptiveAvgPool2d(6)

        # 三层全连接  256*6*6=9216
        self.fc1 = nn.Linear(9216,4096)
        self.fc2 = nn.Linear(4096,4096)
        self.fc3 = nn.Linear(4096,class_num)

    def forward(self,x):
        x = self.conv1(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = self.conv5(x)
        x = self.pool3(x)
        x = self.pool4(x)  #batch*256*6*6

        # 将x展平
        x = x.view(x.size()[0],-1)  # -1表示全部展到第二维上
        # 展平后送入线性层

        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)

        return x

if __name__ == '__main__':
    class_num = 1000
    data = torch.ones((4,3,224,224))  # 4个 3*224*224 的样本
    model = MyModel(class_num)
    pred = model(data)
    print(get_model_parameters(model))



vggNet代码:

import torch
import torch.nn as nn

# vgg模型层
class VggLayer(nn.Module):
    def __init__(self,in_feature,out_feature):
        super().__init__()

        self.conv1 = nn.Conv2d(in_feature,out_feature,3,1,1)
        self.conv2 = nn.Conv2d(out_feature,out_feature,3,1,1)
        self.pool = nn.MaxPool2d(2)

    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.pool(x)

        return x





#vgg模型
class myModel(nn.Module):
    def __init__(self):
        super().__init__()
        # 调用vgg模型层
        self.layer1 = VggLayer(3,64)
        self.layer2 = VggLayer(64,128)
        self.layer3 = VggLayer(128,256)
        self.layer4 = VggLayer(256,512)
        self.layer5 = VggLayer(512,512)

        self.pool = nn.AdaptiveAvgPool2d(7)

        self.fc1 = nn.Linear(25088,4096)
        self.fc2 = nn.Linear(4096,4096)
        self.fc3 = nn.Linear(4096,1000)

    def forward(self,x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        x = self.pool(x)

        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)

        return x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值