[Pytorch案例实践004]CIFAR-100图像分类

一、项目概述

        这个项目旨在基于 PyTorch 框架构建和训练一个卷积神经网络(CNN),用于对 CIFAR-100 数据集进行分类。CIFAR-100 是一个更复杂的数据集,包含 100 类不同的图像,每类图像有 600 张,总计 60,000 张彩色图像。

主要步骤
  1. 数据预处理和加载

    • 加载 CIFAR-100 数据集,进行数据增强和归一化处理,以适应神经网络的输入。
    • 使用 DataLoader 创建数据加载器,支持高效的批量数据处理。
  2. 模型构建

    • 使用 nn.Sequential 构建一个卷积神经网络,网络结构包括多个卷积层、ReLU 激活函数、最大池化层、展平层和全连接层。
    • 增加模型复杂度,以适应 CIFAR-100 的多类别分类任务。
  3. 训练和验证

    • 训练过程中使用交叉熵损失函数和 Adam 优化器,模型的参数通过反向传播更新。
    • 训练完成后,使用验证集数据评估模型的泛化能力,记录损失和准确率。
  4. 模型保存

    • 在每个 epoch 结束时,保存验证集准确率最高的模型权重,确保保存的模型具有最佳性能。
  5. 结果可视化

    • 绘制并保存训练和验证过程中的损失和准确率曲线,以便后续分析。

二、数据集介绍

概述

        CIFAR-100 数据集是由加拿大多伦多大学的 Alex Krizhevsky 和 Geoffrey Hinton 在 2009 年推出的,用于训练机器学习和计算机视觉算法。CIFAR-100 是 CIFAR 系列中的一员,另一个常用的数据集是 CIFAR-10。与 CIFAR-10 的 10 个类别不同,CIFAR-100 包含 100 个不同的类别,每类图像都相对少量,但总共包含 60,000 张彩色图像。

数据集组成
  • 类别:100 个类别,每个类别有 600 张图像。
    • 500 张图像用于训练。
    • 100 张图像用于测试。
  • 图像尺寸:每张图像为 32x32 像素,彩色图像(3 个通道,RGB)。
  • 总样本数量:共 60,000 张图像,其中 50,000 张用于训练,10,000 张用于测试。
类别组织

CIFAR-100 的 100 个类别进一步分为 20 个超类(superclasses),每个超类下包含 5 个细类。每个图像都有一个 "fine" 标签(对应具体类别)和一个 "coarse" 标签(对应超类)。

例如,"superclass" 和 "fine" 类别的示例:

  • 超类 (Superclass): “鱼类 (fish)”
    • 细类 (Fine classes):
      • 鳗鱼 (aquarium fish)
      • 鲸鱼 (whale)
      • 鲸鲨 (shark)
      • 剑鱼 (swordfish)
      • 比目鱼 (flatfish)
数据集特点
  1. 复杂度高:相比 CIFAR-10 的 10 个类别,CIFAR-100 的类别数目多达 100 个,因此分类任务更具挑战性。
  2. 多样性:数据集中包含了不同类型的物体,涵盖了动植物、交通工具、日常用品等多个领域。
  3. 图像质量:图像为 32x32 像素,这种较小的尺寸对图像分类算法提出了较高的要求,需要模型具备较强的特征提取能力。

三、完整代码

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
from tqdm import tqdm
import matplotlib.pyplot as plt

# 设置设备(使用GPU如果可用,否则使用CPU)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 数据预处理,转为Tensor并归一化
transform = transforms.Compose([
    transforms.ToTensor(),  # 转为Tensor
    transforms.Normalize((0.5,), (0.5,))  # 归一化
])

# 加载Fashion-MNIST训练集
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)
trainloader = DataLoader(trainset, batch_size=100, shuffle=True, num_workers=2)

# 加载Fashion-MNIST测试集
testset = torchvision.datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)
testloader = DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

# 构建简单的卷积神经网络
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),  # 卷积层1
            nn.ReLU(),  # 激活函数
            nn.MaxPool2d(kernel_size=2, stride=2),  # 池化层1

            nn.Conv2d(32, 64, kernel_size=3, padding=1),  # 卷积层2
            nn.ReLU(),  # 激活函数
            nn.MaxPool2d(kernel_size=2, stride=2),  # 池化层2

            nn.Conv2d(64, 128, kernel_size=3, padding=1),  # 卷积层3
            nn.ReLU(),  # 激活函数
            nn.MaxPool2d(kernel_size=2, stride=2),  # 池化层3


            nn.Flatten(),  # 展平
            nn.Linear(128*3*3, 256),  # 全连接层1
            nn.ReLU(),  # 激活函数
            nn.Linear(256, 10)  # 全连接层2(输出层)
        )

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

# 定义训练和验证的主函数
def main():
    # 实例化网络并移动到设备(GPU或CPU)
    net = SimpleCNN().to(device)

    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(net.parameters(), lr=0.001)

    # 训练和验证
    num_epochs = 30  # 训练的轮数
    best_acc = 0.0  # 初始化最佳准确率
    train_losses = []  # 用于保存训练损失
    test_losses = []  # 用于保存测试损失
    train_accuracies = []  # 用于保存训练准确率
    test_accuracies = []  # 用于保存测试准确率

    for epoch in range(num_epochs):
        net.train()  # 设置网络为训练模式
        running_loss = 0.0
        correct = 0
        total = 0

        # 使用tqdm显示训练进度条
        train_bar = tqdm(trainloader, desc=f'Training Epoch {epoch+1}/{num_epochs}')
        for inputs, labels in train_bar:
            inputs, labels = inputs.to(device), labels.to(device)

            optimizer.zero_grad()  # 梯度清零
            outputs = net(inputs)  # 前向传播
            loss = criterion(outputs, labels)  # 计算损失
            loss.backward()  # 反向传播
            optimizer.step()  # 优化器更新参数

            running_loss += loss.item()
            _, predicted = outputs.max(1)  # 获取预测结果
            total += labels.size(0)
            correct += predicted.eq(labels).sum().item()

            # 更新进度条信息
            train_bar.set_postfix(loss=running_loss/(len(train_bar)*trainloader.batch_size), acc=100.*correct/total)

        train_loss = running_loss / len(trainloader)
        train_acc = 100. * correct / total
        train_losses.append(train_loss)
        train_accuracies.append(train_acc)

        net.eval()  # 设置网络为评估模式
        test_loss = 0.0
        correct = 0
        total = 0
        with torch.no_grad():  # 禁用梯度计算
            # 使用tqdm显示验证进度条
            test_bar = tqdm(testloader, desc=f'Validating Epoch {epoch+1}/{num_epochs}')
            for inputs, labels in test_bar:
                inputs, labels = inputs.to(device), labels.to(device)
                outputs = net(inputs)
                loss = criterion(outputs, labels)
                test_loss += loss.item()
                _, predicted = outputs.max(1)
                total += labels.size(0)
                correct += predicted.eq(labels).sum().item()
                test_bar.set_postfix(loss=test_loss/(len(test_bar)*testloader.batch_size), acc=100.*correct/total)

        test_loss = test_loss / len(testloader)
        test_acc = 100. * correct / total
        test_losses.append(test_loss)
        test_accuracies.append(test_acc)

        # 保存最好的模型
        if test_acc > best_acc:
            best_acc = test_acc
            torch.save(net.state_dict(), 'best_model.pth')

    # 绘制损失和准确率曲线并保存
    plt.figure(figsize=(12, 5))

    # 绘制损失曲线
    plt.subplot(1, 2, 1)
    plt.plot(range(num_epochs), train_losses, label='Training Loss')
    plt.plot(range(num_epochs), test_losses, label='Validation Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    plt.title('Loss Curve')

    # 绘制准确率曲线
    plt.subplot(1, 2, 2)
    plt.plot(range(num_epochs), train_accuracies, label='Training Accuracy')
    plt.plot(range(num_epochs), test_accuracies, label='Validation Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.title('Accuracy Curve')

    # 保存图像
    plt.savefig('loss_accuracy_curves.png')
    plt.show()

if __name__ == "__main__":
    main()

四、总结

        本项目使用 PyTorch 框架构建了一个卷积神经网络(CNN)模型,针对 CIFAR-100 数据集进行了图像分类任务的实现。CIFAR-100 数据集具有 100 个类别,每个类别包含 600 张图像,是一个复杂的、多类别的图像分类任务。通过这个项目,我们对如何使用深度学习技术来处理图像分类问题有了深入的理解。我们不仅熟悉了使用 PyTorch 构建和训练卷积神经网络的全过程,还掌握了如何处理更复杂的多类别图像分类问题。尽管项目取得了一定的成功,但也暴露了在更大规模数据集上训练的挑战,如需要更多的计算资源、更深的网络结构或更复杂的模型调整策略。

未来的工作可以包括:

  • 尝试使用预训练模型进行迁移学习,以提升模型性能。
  • 引入更先进的网络架构,如 ResNet 或 DenseNet,以进一步提高分类准确率。
  • 优化数据预处理流程,探索更有效的数据增强方法。

        这个项目为后续更复杂的深度学习任务打下了坚实的基础。通过持续学习和实验,不断提升模型的性能和效率,将能够在实际应用中取得更好的结果。

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供一些PyTorch案例!以下是一些常见的PyTorch案例: 1. 图像分类:使用PyTorch可以构建用于图像分类的深度学习模型。您可以使用经典的数据集如MNIST或CIFAR-10,也可以使用自定义数据集。通过构建卷积神经网络(CNN)模型,您可以训练模型对图像进行分类。 2. 目标检测:使用PyTorch可以实现目标检测任务。目标检测是指在图像或视频中定位和识别特定对象的任务。您可以使用预训练的目标检测模型(如Faster R-CNN、YOLO等)或自定义模型来进行目标检测。 3. 机器翻译:使用PyTorch可以构建用于机器翻译的神经网络模型。您可以使用序列到序列(seq2seq)模型,如编码器-解码器架构,用于将一种语言的句子翻译成另一种语言。 4. 文本生成:PyTorch可以用于文本生成任务,如生成对话、生成故事等。您可以使用循环神经网络(RNN)或变换器(Transformer)模型来实现文本生成。 5. 强化学习:PyTorch也广泛应用于强化学习领域。您可以使用PyTorch构建强化学习模型,并通过与环境的交互来训练模型学习最佳策略,如Deep Q-Network(DQN)、Proximal Policy Optimization(PPO)等。 这只是一些PyTorch的应用案例,实际上,PyTorch在深度学习领域有广泛的应用,涵盖了图像处理、自然语言处理、语音识别等多个领域。希望这些案例能为您提供一些参考!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值