使用PyTorch解决多分类问题:构建、训练和评估深度学习模型

简介: 使用PyTorch解决多分类问题:构建、训练和评估深度学习模型

🍋引言

当处理多分类问题时,PyTorch是一种非常有用的深度学习框架。在这篇博客中,我们将讨论如何使用PyTorch来解决多分类问题。我们将介绍多分类问题的基本概念,构建一个简单的多分类神经网络模型,并演示如何准备数据、训练模型和评估结果。

🍋什么是多分类问题?

多分类问题是一种机器学习任务,其中目标是将输入数据分为多个不同的类别或标签。与二分类问题不同,多分类问题涉及到三个或更多类别的分类任务。例如,图像分类问题可以将图像分为不同的类别,如猫、狗、鸟等。

🍋处理步骤

  • 准备数据
    收集和准备数据集,确保每个样本都有相应的标签,以指明其所属类别。
    划分数据集为训练集、验证集和测试集,以便进行模型训练、调优和性能评估。
  • 数据预处理
    对数据进行预处理,例如归一化、标准化、缺失值处理或数据增强,以确保模型训练的稳定性和性能。
  • 选择模型架构
    选择适当的深度学习模型架构,通常包括卷积神经网络(CNN)、循环神经网络(RNN)、Transformer等,具体取决于问题的性质。
  • 定义损失函数
    为多分类问题选择适当的损失函数,通常是交叉熵损失(Cross-Entropy Loss)。
  • 选择优化器
    选择合适的优化算法,如随机梯度下降(SGD)、Adam、RMSprop等,以训练模型并调整权重。
  • 训练模型
    使用训练数据集来训练模型。在每个训练迭代中,通过前向传播和反向传播来更新模型参数,以减小损失函数的值。
  • 评估模型
    使用验证集来评估模型性能。常见的性能指标包括准确性、精确度、召回率、F1分数等。
  • 调优模型
    根据验证集的性能,对模型进行调优,可以尝试不同的超参数设置、模型架构变化或数据增强策略。
  • 测试模型
    最终,在独立的测试数据集上评估模型的性能,以获得最终性能评估。
  • 部署模型
    将训练好的模型部署到实际应用中,用于实时或批处理多分类任务。

🍋多分类问题

之前我们讨论的问题都是二分类居多,对于二分类问题,我们若求得p(0),南无p(1)=1-p(0),还是比较容易的,但是本节我们将引入多分类,那么我们所求得就转化为p(i)(i=1,2,3,4…),同时我们需要满足以上概率中每一个都大于0;且总和为1

处理多分类问题,这里我们新引入了一个称为Softmax Layer

接下来我们一起讨论一下Softmax Layer层

首先我们计算指数计算e的zi次幂,原因很简单e的指数函数恒大于0;分母就是e的z1次幂+e的z2次幂+e的z3次幂…求和,这样所有的概率和就为1了。


下图形象的展示了Softmax,Exponent这里指指数,和上面我们说的一样,先求指数,这样有了分子,再将所有指数求和,最后一一divide,得到了每一个概率。


接下来我们一起来看看损失函数

如果使用numpy进行实现,根据刘二大人的代码,可以进行如下的实现

import numpy as np
y = np.array([1,0,0])
z = np.array([0.2,0.1,-0.1])
y_pred = np.exp(z)/np.exp(z).sum()
loss = (-y * np.log(y_pred)).sum()
print(loss)

运行结果如下

注意:神经网络的最后一层不需要激活


pytorch

import torch
y = torch.LongTensor([0])  # 长整型
z = torch.Tensor([[0.2, 0.1, -0.1]])
criterion = torch.nn.CrossEntropyLoss() 
loss = criterion(z, y)
print(loss)

运行结果如下

下面根据一个例子进行演示

criterion = torch.nn.CrossEntropyLoss()
Y = torch.LongTensor([2,0,1])
Y_pred1 = torch.Tensor([[0.1, 0.2, 0.9], 
                        [1.1, 0.1, 0.2], 
                        [0.2, 2.1, 0.1]]) 
Y_pred2 = torch.Tensor([[0.8, 0.2, 0.3], 
                        [0.2, 0.3, 0.5], 
                        [0.2, 0.2, 0.5]])
l1 = criterion(Y_pred1, Y)
l2 = criterion(Y_pred2, Y)
print("Batch Loss1 = ", l1.data, "\nBatch Loss2=", l2.data)

运行结果如下

根据上面的代码可以看出第一个损失比第二个损失要小。原因很简单,想对于Y_pred1每一个预测的分类与Y是一致的,而Y_pred2则相差了一下,所以损失自然就大了些

🍋MNIST dataset的实现

首先第一步还是导包

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader 
import torch.nn.functional as F 
import torch.optim as optim

之后是数据的准备

batch_size = 64
# transform可以将其转化为0-1,形状的转换从28×28转换为,1×28×28
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307, ), (0.3081, ))   # 均值mean和标准差std
])
train_dataset = datasets.MNIST(root='../dataset/mnist/', 
                train=True,
                download=True,
                transform=transform)  
train_loader = DataLoader(train_dataset,
              shuffle=True,
              batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/', 
              train=False,
              download=True,
              transform=transform)
test_loader = DataLoader(test_dataset,
            shuffle=False,
            batch_size=batch_size)

接下来我们构建网络

class Net(torch.nn.Module):
  def __init__(self):
    super(Net, self).__init__()
    self.l1 = torch.nn.Linear(784, 512) 
    self.l2 = torch.nn.Linear(512, 256) 
    self.l3 = torch.nn.Linear(256, 128) 
    self.l4 = torch.nn.Linear(128, 64) 
    self.l5 = torch.nn.Linear(64, 10)
  def forward(self, x):
    x = x.view(-1, 784)
    x = F.relu(self.l1(x)) 
    x = F.relu(self.l2(x)) 
    x = F.relu(self.l3(x)) 
    x = F.relu(self.l4(x)) 
    return self.l5(x)  # 注意最后一层不做激活
model = Net()

之后定义损失和优化器

criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

接下来就进行训练了

def train(epoch):
  running_loss = 0.0
  for batch_idx, data in enumerate(train_loader, 0): 
    inputs, target = data
    optimizer.zero_grad()
    # forward + backward + update
    outputs = model(inputs)
    loss = criterion(outputs, target)
    loss.backward()
    optimizer.step()
    running_loss += loss.item()
  if batch_idx % 300 == 299:
    print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300)) 
    running_loss = 0.0
def test():
  correct = 0
  total = 0
  with torch.no_grad(): # 这里可以防止内嵌代码不会执行梯度
    for data in test_loader:
      images, labels = data
      outputs = model(images)
      _, predicted = torch.max(outputs.data, dim=1)
      total += labels.size(0)
      correct += (predicted == labels).sum().item()
  print('Accuracy on test set: %d %%' % (100 * correct / total))

最后调用执行

if __name__ == '__main__': 
  for epoch in range(10): 
    train(epoch)
    test()

🍋NLLLoss 和 CrossEntropyLoss

NLLLoss 和 CrossEntropyLoss(也称为交叉熵损失)是深度学习中常用的两种损失函数,用于测量模型的输出与真实标签之间的差距,通常用于分类任务。它们有一些相似之处,但也有一些不同之处。

相同点:

用途:两者都用于分类任务,评估模型的输出和真实标签之间的差异,以便进行模型的训练和优化。
数学基础:NLLLoss 和 CrossEntropyLoss 本质上都是交叉熵损失的不同变种,它们都以信息论的概念为基础,衡量两个概率分布之间的相似度。
输入格式:它们通常期望模型的输出是一个概率分布,表示各个类别的预测概率,以及真实的标签。

不同点:

输入格式:NLLLoss 通常期望输入是对数概率(log probabilities),而 CrossEntropyLoss 通常期望输入是未经对数化的概率。在实际应用中,CrossEntropyLoss 通常与softmax操作结合使用,将原始模型输出转化为概率分布,而NLLLoss可以直接使用对数概率。
对数化:NLLLoss 要求将模型输出的概率经过对数化(取对数)以获得对数概率,然后与真实标签的离散概率分布进行比较。CrossEntropyLoss 通常在 softmax 操作之后直接使用未对数化的概率值与真实标签比较。
输出维度:NLLLoss 更通用,可以用于多种情况,包括多类别分类和序列生成等任务,因此需要更多的灵活性。CrossEntropyLoss 通常用于多类别分类任务。

总之,NLLLoss 和 CrossEntropyLoss 都用于分类任务,但它们在输入格式和使用上存在一些差异。通常,选择哪个损失函数取决于你的模型输出的格式以及任务的性质。如果你的模型输出已经是对数概率形式,通常使用NLLLoss,否则通常使用CrossEntropyLoss

挑战与创造都是很痛苦的,但是很充实。

相关文章
|
2月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
353 2
|
17天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
35 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
1月前
|
并行计算 监控 搜索推荐
使用 PyTorch-BigGraph 构建和部署大规模图嵌入的完整教程
当处理大规模图数据时,复杂性难以避免。PyTorch-BigGraph (PBG) 是一款专为此设计的工具,能够高效处理数十亿节点和边的图数据。PBG通过多GPU或节点无缝扩展,利用高效的分区技术,生成准确的嵌入表示,适用于社交网络、推荐系统和知识图谱等领域。本文详细介绍PBG的设置、训练和优化方法,涵盖环境配置、数据准备、模型训练、性能优化和实际应用案例,帮助读者高效处理大规模图数据。
51 5
|
1月前
|
机器学习/深度学习 人工智能 PyTorch
使用Pytorch构建视觉语言模型(VLM)
视觉语言模型(Vision Language Model,VLM)正在改变计算机对视觉和文本信息的理解与交互方式。本文将介绍 VLM 的核心组件和实现细节,可以让你全面掌握这项前沿技术。我们的目标是理解并实现能够通过指令微调来执行有用任务的视觉语言模型。
41 2
|
1月前
|
机器学习/深度学习 监控 PyTorch
深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
48 7
|
2月前
|
机器学习/深度学习 算法 PyTorch
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
这篇文章详细介绍了多种用于目标检测任务中的边界框回归损失函数,包括IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU和WIOU,并提供了它们的Pytorch实现代码。
310 1
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
|
2月前
|
机器学习/深度学习 算法 数据可视化
如果你的PyTorch优化器效果欠佳,试试这4种深度学习中的高级优化技术吧
在深度学习领域,优化器的选择对模型性能至关重要。尽管PyTorch中的标准优化器如SGD、Adam和AdamW被广泛应用,但在某些复杂优化问题中,这些方法未必是最优选择。本文介绍了四种高级优化技术:序列最小二乘规划(SLSQP)、粒子群优化(PSO)、协方差矩阵自适应进化策略(CMA-ES)和模拟退火(SA)。这些方法具备无梯度优化、仅需前向传播及全局优化能力等优点,尤其适合非可微操作和参数数量较少的情况。通过实验对比发现,对于特定问题,非传统优化方法可能比标准梯度下降算法表现更好。文章详细描述了这些优化技术的实现过程及结果分析,并提出了未来的研究方向。
35 1
|
2月前
|
机器学习/深度学习 vr&ar
深度学习笔记(十):深度学习评估指标
关于深度学习评估指标的全面介绍,涵盖了专业术语解释、一级和二级指标,以及各种深度学习模型的性能评估方法。
50 0
深度学习笔记(十):深度学习评估指标
|
2月前
|
机器学习/深度学习 自然语言处理 监控
利用 PyTorch Lightning 搭建一个文本分类模型
利用 PyTorch Lightning 搭建一个文本分类模型
68 8
利用 PyTorch Lightning 搭建一个文本分类模型
|
2月前
|
机器学习/深度学习 自然语言处理 数据建模
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
本文深入探讨了Transformer模型中的三种关键注意力机制:自注意力、交叉注意力和因果自注意力,这些机制是GPT-4、Llama等大型语言模型的核心。文章不仅讲解了理论概念,还通过Python和PyTorch从零开始实现这些机制,帮助读者深入理解其内部工作原理。自注意力机制通过整合上下文信息增强了输入嵌入,多头注意力则通过多个并行的注意力头捕捉不同类型的依赖关系。交叉注意力则允许模型在两个不同输入序列间传递信息,适用于机器翻译和图像描述等任务。因果自注意力确保模型在生成文本时仅考虑先前的上下文,适用于解码器风格的模型。通过本文的详细解析和代码实现,读者可以全面掌握这些机制的应用潜力。
116 3
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力