PyTorch入门与实战:用卷积神经网络(CNN)进行图像分类
本文介绍了如何使用PyTorch构建卷积神经网络(CNN)进行图像分类。主要内容包括:1) CNN核心概念讲解,包括卷积层、池化层等;2) 环境配置与CIFAR-10数据加载;3) 定义CNN模型结构;4) 设置损失函数和优化器;5) 训练网络过程;6) 测试集评估模型性能。教程从零开始,逐步指导读者完成一个完整的图像分类项目,适合PyTorch初学者学习深度学习的基本流程。
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)中,我们遍历整个训练数据集,执行以下操作:
- 从
DataLoader获取一批(batch)数据。 - 将优化器的梯度缓存清零 (
optimizer.zero_grad())。 - 执行前向传播,得到模型输出 (
outputs = net(inputs))。 - 计算损失 (
loss = criterion(outputs, labels))。 - 执行反向传播,计算梯度 (
loss.backward())。 - 调用优化器,更新网络权重 (
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 从零开始构建一个卷积神经网络用于图像分类。我们回顾了整个工作流:
- 数据处理:使用
torchvision.transforms和DataLoader对 CIFAR-10 数据集进行加载和预处理。 - 模型定义:继承
nn.Module来构建一个包含卷积、池化和全连接层的 CNN 结构。 - 损失与优化:选择了
CrossEntropyLoss和SGD作为损失函数与优化器。 - 网络训练:编写标准的训练循环,完成模型参数的学习。
- 性能评估:在测试集上计算模型的分类准确率。
通过这个实例,您应该对 PyTorch 的基本工作流程有了扎实的理解。这仅仅是深度学习之旅的起点,后续您还可以探索更深的网络结构、更复杂的优化技巧以及更多有趣的应用。
如果觉得本文对您有帮助,请点赞、收藏并关注博主,感谢您的支持!
更多推荐
所有评论(0)