PyTorch入门与实战:用卷积神经网络(CNN)进行图像分类

在这里插入图片描述

前言

深度学习在计算机视觉领域的应用已经取得了革命性的突破,而卷积神经网络(CNN)是其背后的核心技术。对于希望进入人工智能领域的开发者来说,掌握一个主流的深度学习框架并利用它来构建图像分类模型,是必备的入门技能。PyTorch 以其灵活性、易用性和强大的社区支持,成为了学术界和工业界的首选框架之一。

本文将提供一个详尽的、端到端的实战教程,旨在引导初学者使用 PyTorch 构建一个完整的 CNN 模型,并应用于经典的 CIFAR-10 图像分类任务。文章将覆盖从数据准备、模型构建、训练到最终评估的全过程。


1. 卷积神经网络 (CNN) 核心概念

卷积神经网络是一种特殊设计用于处理具有网格状拓扑结构数据(如图像)的深度神经网络。其核心思想在于通过局部感受野权值共享下采样来有效提取和学习图像特征。

一个基础的 CNN 通常由以下几种关键层组成:

  • 卷积层 (torch.nn.Conv2d): 网络的核心,通过可学习的滤波器(或称卷积核)在输入图像上滑动,以生成特征图(Feature Map),从而捕捉图像的局部特征(如边缘、角点、纹理等)。
  • 激活函数 (如 ReLU): 对卷积层输出的特征图进行非线性变换,增强网络的表达能力。ReLU(x) = max(0, x) 是最常用的激活函数之一。
  • 池化层 (torch.nn.MaxPool2d): 也称为下采样层。它在保留显著特征的同时,减小特征图的空间尺寸,从而减少网络参数数量和计算复杂度,并增强模型的平移不变性。
  • 全连接层 (torch.nn.Linear): 在网络的末端,负责将前面卷积和池化层提取到的高级特征进行整合,并映射到最终的输出(例如,各个类别的得分)。

2. 步骤一:环境配置与数据加载

在开始编码前,请确保已安装 PyTorch 和 torchvision

# 强烈建议访问 PyTorch 官网 (https://pytorch.org/) 以获取最适合您系统(CUDA/CPU)的安装指令。
# 以下为通用 CPU 版本的安装示例:
pip install torch torchvision

我们将使用 torchvision 中内置的 CIFAR-10 数据集。该数据集包含 10 个类别的 60,000 张 32x32 彩色图像。

torchvision.transforms 模块用于对图像数据进行预处理,torch.utils.data.DataLoader 则用于高效地加载数据。

import torch
import torchvision
import torchvision.transforms as transforms

# 1. 定义数据预处理流程
# a. 将 PIL.Image 或 numpy.ndarray 转换为 torch.FloatTensor。
# b. 将 [0, 1] 范围的张量归一化到 [-1, 1] 范围。
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))])

# 2. 下载并准备训练数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
# 3. 创建数据加载器
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

# 4. 同样地准备测试数据集
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

# 类别标签
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

3. 步骤二:定义 CNN 模型结构

在 PyTorch 中,任何自定义模型都应继承自 torch.nn.Module。我们需要在 __init__ 方法中定义网络层,并在 forward 方法中指定数据在前向传播过程中的流向。

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

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        # 定义网络层
        # 输入: 3x32x32
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5) # -> 6x28x28
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # -> 6x14x14
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5) # -> 16x10x10
        # self.pool 之后 -> 16x5x5
        
        # 全连接层
        self.fc1 = nn.Linear(16 * 5 * 5, 120) # 16*5*5 是展平后的维度
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10) # 最终输出10个类别

    def forward(self, x):
        # 定义数据流
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        
        # 将多维特征图展平为一维向量
        x = x.view(-1, 16 * 5 * 5)
        
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

# 实例化模型
net = SimpleCNN()
print(net)

4. 步骤三:定义损失函数和优化器

  • 损失函数 (Loss Function): 用于衡量模型预测值与真实标签之间的差异。对于多分类问题,交叉熵损失 nn.CrossEntropyLoss 是标准选择。
  • 优化器 (Optimizer): 根据损失函数计算出的梯度,来更新网络的权重参数,以期减小未来的损失。随机梯度下降(SGD)是其中最基础和常用的优化算法。
import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

5. 步骤四:训练网络

训练过程是一个迭代的过程。在每个迭代(epoch)中,我们遍历整个训练数据集,执行以下操作:

  1. DataLoader 获取一批(batch)数据。
  2. 将优化器的梯度缓存清零 (optimizer.zero_grad())。
  3. 执行前向传播,得到模型输出 (outputs = net(inputs))。
  4. 计算损失 (loss = criterion(outputs, labels))。
  5. 执行反向传播,计算梯度 (loss.backward())。
  6. 调用优化器,更新网络权重 (optimizer.step())。
print('--- 开始训练 ---')

for epoch in range(2):  # 训练两个 epoch 作为演示
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # 1. 获取数据
        inputs, labels = data

        # 2. 梯度清零
        optimizer.zero_grad()

        # 3. 前向传播、计算损失、反向传播、优化
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # 4. 打印日志
        running_loss += loss.item()
        if i % 2000 == 1999:    # 每 2000 个 mini-batches 打印一次平均损失
            print(f'[Epoch: {epoch + 1}, Batch: {i + 1:5d}] loss: {running_loss / 2000:.3f}')
            running_loss = 0.0

print('--- 训练结束 ---')

6. 步骤五:在测试集上评估模型

训练完成后,我们需要在从未见过的数据(测试集)上评估模型的性能。

correct = 0
total = 0

# 在评估模式下,我们不需要计算梯度
with torch.no_grad():
    for data in testloader:
        images, labels = data
        # 将图像输入网络
        outputs = net(images)
        # 获取预测结果:得分最高的类别
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
print(f'模型在 10000 张测试图像上的准确率: {accuracy:.2f} %')

Ai 产品推荐

😳 0v0 AI 助手推荐、官网:https://0v0.pro

  • 🆓 开源模型全免费:Llama、Qwen、Deepseek 等
  • 😲 基础模型全免费:gpt-4o、o4-mini 、gpt-5-mini 等
  • ♾️ 对话真正无限制:不限时间、不限次数
  • 🫡 每周免费一个旗舰模型:本周免费:gpt-5 ,不限使用!

LLM AI API 推荐 🗨️

🖐️ 按量计算、官网:https://llm-all.pro

  • 😊 opneai 、cluade、genimi、gork 等模型:0.5:1刀 、官方 1 折
  • 🤓 国内模型 豆包、千问 、deepseek、kimi 等:2 - 6 折
  • ☺️ 除了以上模型外,还包含全球各类以上未列出的模型

👺 按次计算、官网:https://fackai.chat

  • 国内外全模型
  • 1 :100次,性价比推荐

总结

本文详细介绍了如何使用 PyTorch 从零开始构建一个卷积神经网络用于图像分类。我们回顾了整个工作流:

  1. 数据处理:使用 torchvision.transformsDataLoader 对 CIFAR-10 数据集进行加载和预处理。
  2. 模型定义:继承 nn.Module 来构建一个包含卷积、池化和全连接层的 CNN 结构。
  3. 损失与优化:选择了 CrossEntropyLossSGD 作为损失函数与优化器。
  4. 网络训练:编写标准的训练循环,完成模型参数的学习。
  5. 性能评估:在测试集上计算模型的分类准确率。

通过这个实例,您应该对 PyTorch 的基本工作流程有了扎实的理解。这仅仅是深度学习之旅的起点,后续您还可以探索更深的网络结构、更复杂的优化技巧以及更多有趣的应用。

如果觉得本文对您有帮助,请点赞、收藏并关注博主,感谢您的支持!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐