机器学习:分类任务(图片分类)

1.如何做分类输出的

在这的y尖代表真实值,y一撇代表预测的值,然后真实值使用的是独热编码(One-hot),注意最大值的下标就是他的类别

2.图片分类

        2.1 输出

图片分类也是和回归任务一样,要输入数据取模型当中,但是这里的图片必须是要相同的大小的

回归任务和分类的区别:回归是输出一个数然后和真实值做loss,而分类是输出的不是一个值虽和真实值做loss但是两个任务的loss的求法不同,回归的是mseloss而分类的是交叉相乘的loss(Cross entropy)

        2.2 输入

首先如果用全连接linear的话参数会非常的的大(3*224*224*1000+1000)会导致模型过拟合,所以这图片分类任务当中我们使用的卷积神经网络来实现的,这里的3是因为图片是3通道的RGB

举例:使用第二图的方法判断是否有,并且数值越大,图越像

当看一张图片的时候:我们的目标就是如何卷积核变得像我们想要的 最后得到一个有意义的特征图,这个过程就是通过训练得到的

1.可以在原来的卷积核旁边加一圈0

2.用更大的或者更多的卷积核层数来实现

2.2手算卷积神经网络

这的卷积核大小为2就是2*2的 padding为1就是补一圈0 为2就是补两圈0

其实就是这样计算的(1 2行列的和卷积核相乘得到第一个数字)

第三个先加一个padding的话原本的4*4就变为了6*6所以再来乘3*3的就变为4*4

第四个是三个三个的卷积然后到98的时候 98 99 100可以卷但是到99的话就不可以了因为只有99和100,所以卷积出来就是98*98 第五个类似

所以得出公式:卷出来的大小=原有的特征图大小 - 卷积核大小 + 1

第三个开始就有了厚度3 所以卷积核也必须是3通道的然后再说大小 padding为1后就变为了3 6 6 然后卷出来时 1 4 4 所以大小是为3 3 然后通道为3 所以这一套卷积核大小为 3 3 3 然后参数量就为3*3*3=27个

第四个 卷积核数量为7 但是我们知道每一个卷积核都可以卷出来一张特征图 所以这里是7 4 4

五和四类似

第六个的卷积核参数量为128个64*3*3这么多

2.3 使特征图变小

扩大步长

卷积尺寸计算公式

池化pooling

Pooling(2)的意思是两个格子变为一个 而 AdaptiveAvgPool(7)是无论怎么变最后都变为7

手搓卷积神经网络

卷积到全连接

分类的loss

3.一个基本的分类神经网络

3.1经典的图片数据集

3.2 经典的模型(Sota模型)

3.3 AlexNet

归一化:

import torchvision.models as models


# mymodel = models.alexnet()
#
# print(mymodel)
import torch.nn as nn

class myAlexNet(nn.Module):
    def __init__(self, out_dim):
        super(myAlexNet, self).__init__()
        #初始的时候是3*224*224
                     #参数依次是输入特征图数量、输出特征图数量、卷积核大小、步长、padding
        self.conv1 = nn.Conv2d(3,64,11,4,2) #后变为64*55*55   (224-11+2*2)/ 4 + 1 = 55 向下取整
                    #Pool(3,2)的意思是9个数据一起算然后计算下一个的时候是移动2个
        self.pool1 = nn.MaxPool2d(3, 2) #变为64*27*27

        self.conv2 = nn.Conv2d(64,192,5,1,2) #变为192*27*27
        self.pool2 = nn.MaxPool2d(3, 2) #变为192*13*13

        self.conv3 = nn.Conv2d(192,384,3,1,1) #变为384*13*13
        self.conv4 = nn.Conv2d(384, 256, 3, 1, 1)#变为256*13*13
        self.conv5 = nn.Conv2d(256, 256, 3, 1, 1)#变为256*13*13

        self.pool3 = nn.MaxPool2d(3, 2) #变为256*6*6
        self.pool4 = nn.AdaptiveAvgPool2d(6) #256*6*6 AdaptiveAvgPool2d(6)的意思是无论怎么变都变为6*6

        self.fc1 = nn.Linear(9216, 4096)  #这里的9216是自己算的 是256*6*6得来的
        self.fc2 = nn.Linear(4096, 4096)
        self.fc3 = nn.Linear(4096, out_dim) #最后全连接变为自己的类别数

    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)

        x = x.view(x.size()[0], -1)  #拉直。 batch
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x

model = myAlexNet(1000)

import torch
# a = torch.ones((4,3,224,224))   #batch, 3, 224,224
# pred = model(a)

def get_parameter_number(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}

print(get_parameter_number(model.pool1))

3.4 VggNet

import torchvision.models as models
import torch.nn as nn


vgg = models.vgg13()
print(vgg)
#vgg模型 两个一pool
class vggLayer(nn.Module):
    def __init__(self,in_cha, mid_cha, out_cha):
        super(vggLayer, self).__init__()
        self.relu = nn.ReLU()

        self.conv1 = nn.Conv2d(in_cha, mid_cha, 3, 1, 1)
        self.conv2 = nn.Conv2d(mid_cha, out_cha, 3, 1, 1)
        self.pool = nn.MaxPool2d(2)


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



class MyVgg(nn.Module):
    def __init__(self):
        super(MyVgg, self).__init__()

        self.layer1 = vggLayer(3, 64, 64)

        self.layer2 = vggLayer(64, 128, 128)

        self.layer3 = vggLayer(128, 256, 256)

        self.layer4 = vggLayer(256, 512, 512)

        self.layer5 = vggLayer(512, 512, 512)
        self.adapool = nn.AdaptiveAvgPool2d(7)
        self.relu = nn.ReLU()
        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.adapool(x)

        x= self.adapool(x)
        x = x.view(x.size()[0], -1)

        x = self.fc1(x)
        x = self.relu(x)

        x = self.fc2(x)
        x = self.relu(x)

        x = self.fc3(x)
        x = self.relu(x)

        return x


import torch

myVgg = MyVgg()
#
img = torch.zeros((1, 3, 224,224))

out = myVgg(img)

print(out.size())

def get_parameter_number(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}


print(get_parameter_number(myVgg))
print(get_parameter_number(myVgg.layer1))
print(get_parameter_number(myVgg.layer1.conv1))
#
# print(get_parameter_number(vgg))

3.5 ResNet

1*1的目的是为了降维

为什么 ResNet 那么深?

ResNet(Residual Network)之所以能够设计得非常深(例如 ResNet-152 有 152 层),主要归功于其引入的 残差连接(Residual Connection)跳跃连接(Skip Connection)。残差连接解决了深度神经网络训练中的 梯度消失梯度爆炸 问题,使得非常深的网络能够有效地训练。

1. 梯度消失和梯度爆炸问题
  • 在深度神经网络中,随着网络层数的增加,梯度在反向传播过程中可能会逐渐消失(接近于 0)或爆炸(变得非常大),导致网络难以训练。

  • 这种问题在传统的深度卷积网络(如 VGGNet)中尤为明显,限制了网络的深度。

2. 残差连接的引入
  • 残差连接 的核心思想是:如果一个网络层难以学习到复杂的特征,那么它可以学习一个恒等映射(Identity Mapping),即将输入直接传递到输出。

  • 具体来说,残差连接将输入 x 直接加到输出 H(x) 上,形成 F(x)=H(x)−x。这样,网络只需要学习残差函数 F(x),而不是直接学习 H(x)。

  • 残差连接的公式为:

    y=F(x)+x

    其中 F(x) 是残差函数,x 是输入,y 是输出。

3. 残差连接的优势
  • 缓解梯度消失问题:残差连接提供了一条梯度直接传播的路径,使得梯度能够有效地反向传播到较浅的层。

  • 更容易优化:残差连接使得网络更容易学习到恒等映射,从而避免了网络退化的问题。

  • 允许更深的网络:由于残差连接的存在,ResNet 可以设计得非常深(如 152 层),而不会出现训练困难的问题。

VGGNet 和 ResNet 的区别

1. 网络结构
  • VGGNet

    • VGGNet 使用了非常均匀的结构,主要由多个卷积层(3x3 卷积核)和池化层(2x2 最大池化)组成。

    • VGGNet 的卷积层之间没有跳跃连接。

    • VGGNet 的深度相对较小,例如 VGG-16 有 16 层,VGG-19 有 19 层。

  • ResNet

    • ResNet 引入了残差连接,形成了残差块(Residual Block)。

    • 每个残差块包含两个或多个卷积层,输入通过残差连接直接加到输出。

    • ResNet 的深度可以非常大,例如 ResNet-50 有 50 层,ResNet-101 有 101 层,ResNet-152 有 152 层。

2. 残差连接
  • VGGNet:没有残差连接,网络层之间是顺序连接的。

  • ResNet:每个残差块都有残差连接,输入直接加到输出,形成跳跃连接。

3. 训练深度
  • VGGNet:由于没有残差连接,VGGNet 的深度有限,通常在 16 到 19 层之间。

  • ResNet:由于残差连接的存在,ResNet 可以设计得非常深,达到 152 层甚至更深。

4. 参数数量
  • VGGNet:VGGNet 的参数数量较多,尤其是全连接层部分。例如,VGG-16 有约 1.38 亿个参数。

  • ResNet:ResNet 的参数数量相对较少,尤其是较深的版本。例如,ResNet-50 有约 2560 万个参数,ResNet-152 有约 6020 万个参数。

5. 性能
  • VGGNet:VGGNet 在 ImageNet 数据集上取得了较好的性能,但随着网络深度的增加,训练变得困难。

  • ResNet:ResNet 由于引入了残差连接,能够在更深的网络中保持较好的性能,显著提高了分类准确率。

总结

  • VGGNet 是一种经典的深度卷积神经网络,结构简单但深度有限,适合较小规模的任务。

  • ResNet 通过引入残差连接,解决了深度网络训练中的梯度消失问题,能够设计得非常深,从而在大规模任务中表现出色。

  • ResNet 的残差连接是其核心创新,使得网络能够有效地训练和优化,成为深度学习领域的重要里程碑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Haooog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值