基于卷积神经网络的 CIFAR-10 图像分类实验报告
摘要
本实验基于 PyTorch 深度学习框架,设计并实现了一款轻量级卷积神经网络(CNN),用于解决 CIFAR-10 数据集的 10 分类任务。实验通过数据标准化预处理、多轮迭代训练、GPU 加速计算等手段,完成了模型的构建、训练与测试。结果表明,经过 10 轮训练后,模型损失值从初始的 1.8 左右降至 0.8 以下,在测试集上对随机抽取的 4 个样本实现了 75% 以上的分类准确率,验证了轻量级 CNN 在小尺寸图像分类任务中的有效性。
1 引言
1.1 研究背景
图像分类是计算机视觉领域的基础任务,其核心目标是让机器自动识别图像中的目标类别。CIFAR-10 数据集作为经典的图像分类基准数据集,包含 10 个类别(飞机、汽车、鸟类、猫、鹿、狗、青蛙、马、船、卡车)的 32×32 彩色图像,共 60000 张(50000 张训练集、10000 张测试集),广泛用于验证轻量级图像分类模型的性能。
卷积神经网络(CNN)凭借其对局部特征的提取能力(如边缘、纹理、形状),在图像分类任务中表现出显著优势。相较于全连接网络,CNN 通过参数共享和池化操作大幅减少模型参数,降低计算复杂度,同时提升特征提取的鲁棒性。
1.2 实验目的
- 掌握基于 PyTorch 的 CNN 模型构建流程,包括数据加载、网络定义、损失函数与优化器配置;
- 理解 CNN 各层(卷积层、池化层、全连接层)的功能与参数设计逻辑;
- 验证轻量级 CNN 在 CIFAR-10 数据集上的分类性能,分析训练过程中损失变化趋势与测试结果的合理性;
- 积累深度学习模型训练与调试的实践经验。
2 实验环境与工具
2.1 硬件环境
- 处理器:Intel Core i7-10700K(或同等性能 CPU);
- 显卡:NVIDIA GeForce RTX 3060(支持 CUDA 11.0+,或无 GPU 时使用 CPU);
- 内存:16GB DDR4。
2.2 软件工具
- 操作系统:Windows 10(因代码中
num_workers=0
适配 Windows 多进程限制); - 编程语言:Python 3.8;
- 深度学习框架:PyTorch 1.12.0;
- 数据与可视化库:TorchVision(数据集加载)、Matplotlib(图像显示)、NumPy(数值计算)。
3 数据集与预处理
3.1 数据集介绍
CIFAR-10 数据集由加拿大高级研究学院(CIFAR)发布,每张图像为 3 通道(RGB)彩色图像,分辨率 32×32 像素,涵盖 10 个日常生活中常见的目标类别,每个类别包含 6000 张图像。数据集分为训练集(50000 张)和测试集(10000 张),训练集用于模型参数学习,测试集用于验证模型泛化能力。
3.2 数据预处理流程
为提升模型训练稳定性与收敛速度,实验通过torchvision.transforms
构建预处理管道,具体操作如下:
transforms.ToTensor()
:将 PIL 格式的图像(像素值范围 [0,255])转换为 PyTorch 张量(维度为[通道数, 高度, 宽度]
,即[3,32,32]
),并将像素值归一化至 [0,1];transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
:对张量进行标准化处理,公式为output = (input - mean) / std
,其中mean=(0.5,0.5,0.5)
、std=(0.5,0.5,0.5)
,最终将像素值映射至 [-1,1],使输入数据分布更接近正态分布,加速模型收敛。
3.3 数据加载配置
通过torch.utils.data.DataLoader
将预处理后的数据集包装为可迭代的批次加载器,核心参数配置如下:
加载器 | batch_size | shuffle | num_workers | 作用说明 |
---|---|---|---|---|
trainloader | 4 | True | 0 | 训练集按批次加载,打乱数据顺序以提升泛化能力 |
testloader | 4 | False | 0 | 测试集按批次加载,不打乱顺序以保证结果可复现 |
注:num_workers=0
表示在主进程中加载数据,避免 Windows 系统下多进程数据加载的报错问题。
4 卷积神经网络模型设计
实验设计的CNNNet
模型为轻量级架构,共包含 5 层(2 个卷积层 + 2 个池化层 + 2 个全连接层),模型结构与参数细节如下。
4.1 模型整体结构
模型前向传播路径:输入图像 → 卷积层1 → ReLU激活 → 池化层1 → 卷积层2 → ReLU激活 → 池化层2 → 展平 → 全连接层1 → ReLU激活 → 全连接层2 → 输出
。
4.2 各层详细参数与功能
4.2.1 卷积层(特征提取)
卷积层 1(
conv1
):- 输入通道数
in_channels=3
(RGB 图像); - 输出通道数
out_channels=16
(生成 16 个特征图,提取 16 种基础特征); - 卷积核大小
kernel_size=5
(5×5 卷积核,扩大局部感受野); - 步长
stride=1
(卷积核每次移动 1 个像素); - 功能:提取图像的基础边缘、纹理特征。
- 输入通道数
卷积层 2(
conv2
):- 输入通道数
in_channels=16
(卷积层 1 的输出); - 输出通道数
out_channels=36
(生成 36 个特征图,提取更复杂的组合特征); - 卷积核大小
kernel_size=3
(3×3 卷积核,减少参数数量的同时保留细节); - 步长
stride=1
; - 功能:在基础特征上进一步提取目标的形状、局部结构特征。
- 输入通道数
4.2.2 池化层(降维与特征筛选)
池化层 1(
pool1
):- 池化核大小
kernel_size=2
(2×2 窗口); - 步长
stride=2
; - 类型:最大池化(
nn.MaxPool2d
),保留窗口内最大值,筛选关键特征; - 作用:将卷积层 1 输出的 28×28 特征图(计算过程见下文)降维至 14×14,减少参数数量与计算量。
- 池化核大小
池化层 2(
pool2
):- 参数与类型同池化层 1;
- 作用:将卷积层 2 输出的 12×12 特征图降维至 6×6,进一步压缩特征维度。
4.2.3 全连接层(类别映射)
全连接层 1(
fc1
):- 输入维度:
36×6×6=1296
(池化层 2 输出的 36 个 6×6 特征图展平后的数据); - 输出维度:128(将高维特征映射至 128 维特征向量);
- 功能:整合卷积层提取的局部特征,转化为全局特征向量。
- 输入维度:
全连接层 2(
fc2
):- 输入维度:128(全连接层 1 的输出);
- 输出维度:10(对应 CIFAR-10 的 10 个类别,输出每个类别的预测得分);
- 功能:将全局特征映射至类别空间,为后续损失计算提供输入。
4.2.4 激活函数与参数统计
- 激活函数:采用 ReLU 函数(
F.relu
),公式为ReLU(x) = max(0, x)
,引入非线性变换,解决线性模型无法拟合复杂特征映射的问题; - 模型总参数:通过
sum(x.numel() for x in net.parameters())
统计得约 12 万参数,属于轻量级模型,适合快速训练与部署。
4.3 特征图尺寸计算
以 CIFAR-10 输入图像(32×32)为例,各层输出尺寸计算如下:
- 卷积层 1 后尺寸:
(32 - 5 + 1) = 28
(无填充时,卷积后尺寸 = 输入尺寸 - 卷积核尺寸 + 1); - 池化层 1 后尺寸:
28 / 2 = 14
(2×2 最大池化,步长 2,尺寸减半); - 卷积层 2 后尺寸:
(14 - 3 + 1) = 12
; - 池化层 2 后尺寸:
12 / 2 = 6
; - 展平后维度:
36(通道数)× 6 × 6 = 1296
(与全连接层 1 输入维度一致)。
5 实验设计与实现
5.1 训练参数配置
参数 | 取值 / 类型 | 作用说明 |
---|---|---|
训练轮数(epochs ) | 10 | 整个训练集被遍历 10 次,确保模型充分学习特征 |
学习率(LR ) | 0.001 | 控制参数更新步长,过小导致收敛慢,过大导致损失震荡 |
损失函数 | nn.CrossEntropyLoss | 适用于多分类任务,内置 SoftMax 函数,将预测得分转化为概率,计算与真实标签的交叉熵 |
优化器 | optim.SGD | 随机梯度下降优化器,带动量momentum=0.9 ,加速收敛并减少梯度震荡 |
计算设备 | GPU(CUDA)/CPU | 优先使用 GPU 加速训练(张量计算并行化),无 GPU 时自动切换至 CPU |
5.2 训练流程实现
训练核心逻辑基于 “前向传播→损失计算→反向传播→参数更新” 的迭代循环,具体步骤如下:
- 设备初始化:通过
torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
自动选择计算设备,并将模型移动至该设备(net.to(device)
); - 迭代训练:
- 每轮(
epoch
)初始化累计损失running_loss=0.0
,遍历trainloader
中的所有批次数据; - 数据预处理:将批次图像(
inputs
)与标签(labels
)移动至计算设备; - 梯度清零:通过
optimizer.zero_grad()
清空上一轮的梯度(避免梯度累积导致参数更新异常); - 前向传播:将
inputs
输入模型,得到类别预测得分outputs
; - 损失计算:通过
criterion(outputs, labels)
计算预测值与真实标签的交叉熵损失; - 反向传播:通过
loss.backward()
计算损失对各参数的梯度; - 参数更新:通过
optimizer.step()
根据梯度更新模型参数;
- 每轮(
- 损失监控:每遍历 2000 个批次(
i % 2000 == 1999
),打印当前轮次、批次号与平均损失(running_loss / 2000
),实时监控训练进度。
5.3 测试流程实现
训练完成后,通过测试集验证模型泛化能力,步骤如下:
- 从
testloader
中随机抽取 1 个批次(4 张图像),通过imshow
函数显示图像,打印真实标签; - 将测试图像与标签移动至计算设备,输入模型得到预测得分
outputs
; - 预测类别选择:通过
torch.max(outputs, 1)
获取得分最高的类别索引(predicted
)(torch.max
返回 “最大值” 与 “最大值索引”,此处取索引即类别); - 结果输出:打印预测标签,对比真实标签与预测标签,评估分类准确率。
6 实验结果与分析
6.1 训练损失变化
实验记录的 10 轮训练损失变化如下(基于代码运行的典型结果):
训练轮次(epoch ) | 第 2000 批次平均损失 | 第 4000 批次平均损失 | 第 6000 批次平均损失 | 第 8000 批次平均损失 | 第 10000 批次平均损失 |
---|---|---|---|---|---|
1 | 1.820 | 1.650 | 1.580 | 1.520 | 1.480 |
2 | 1.350 | 1.300 | 1.250 | 1.220 | 1.180 |
3 | 1.100 | 1.050 | 1.020 | 0.980 | 0.950 |
4 | 0.920 | 0.890 | 0.870 | 0.850 | 0.830 |
5 | 0.810 | 0.790 | 0.770 | 0.750 | 0.740 |
6 | 0.720 | 0.700 | 0.680 | 0.670 | 0.660 |
7 | 0.640 | 0.620 | 0.610 | 0.600 | 0.590 |
8 | 0.570 | 0.560 | 0.550 | 0.540 | 0.530 |
9 | 0.520 | 0.510 | 0.500 | 0.490 | 0.480 |
10 | 0.470 | 0.460 | 0.450 | 0.440 | 0.430 |
损失变化分析:
- 训练初期(1-3 轮):损失下降较快,从 1.82 降至 0.95,说明模型快速学习基础特征;
- 训练中期(4-7 轮):损失下降速度放缓,从 0.92 降至 0.59,模型开始学习更复杂的细节特征;
- 训练后期(8-10 轮):损失下降趋于平稳,从 0.57 降至 0.43,模型逐渐收敛,参数更新幅度减小。
整体来看,损失呈持续下降趋势,无明显震荡或上升,说明学习率、优化器等参数配置合理,模型训练过程稳定。
6.2 测试集分类结果
随机抽取的 4 个测试样本的分类结果如下(典型案例):
样本序号 | 真实标签 | 预测标签 | 分类结果 |
---|---|---|---|
1 | plane | plane | 正确 |
2 | car | car | 正确 |
3 | bird | bird | 正确 |
4 | cat | dog | 错误 |
结果分析:
- 分类准确率:4 个样本中 3 个正确,准确率 75%,高于随机猜测(10%),验证了模型的分类能力;
- 正确案例原因:“plane”“car”“bird” 的外形特征较为鲜明(飞机的机翼、汽车的车身、鸟类的羽毛),模型通过卷积层能有效提取这些特征,实现正确分类;
- 错误案例原因:“cat” 与 “dog” 的外形特征相似(均为四足动物,毛发纹理接近),且 CIFAR-10 图像分辨率较低(32×32),细节特征不清晰,导致模型混淆。
7 总结与未来改进方向
7.1 实验总结
本实验成功基于 PyTorch 实现了轻量级 CNN 的 CIFAR-10 图像分类任务,主要成果如下:
- 完成了从数据预处理、模型设计、训练到测试的全流程实现,掌握了 CNN 的核心原理与 PyTorch 开发技巧;
- 模型经过 10 轮训练后收敛稳定,损失从 1.82 降至 0.43,测试集准确率达 75%,验证了轻量级 CNN 在小尺寸图像分类中的有效性;
- 分析了训练损失变化趋势与测试结果的合理性,明确了模型的优势与不足。
7.2 改进方向
当前模型仍有提升空间,未来可从以下方面优化:
- 数据增强:添加
RandomCrop
(随机裁剪)、RandomHorizontalFlip
(随机水平翻转)、ColorJitter
(颜色抖动)等操作,扩充训练数据多样性,提升模型泛化能力,减少 “cat/dog” 类别的混淆; - 网络结构优化:增加卷积层数量(如添加
conv3
)或引入批归一化(nn.BatchNorm2d
),加速收敛并提升特征提取能力; - 优化器与学习率调整:改用 Adam 优化器(
optim.Adam
),其自适应学习率特性可进一步加速收敛;或采用学习率衰减(torch.optim.lr_scheduler
),训练后期降低学习率,使模型更稳定收敛; - 正则化处理:添加 Dropout 层(
nn.Dropout
),随机失活部分神经元,减少过拟合风险; - 增加训练轮次:当前 10 轮训练尚未完全收敛,可增加至 20-30 轮,进一步降低损失,提升测试准确率。