本博客详细记录了基于PyTorch的卷积神经网络入门实验,在MNIST上对比了全连接网络与卷积网络的性能差异,在CIFAR10上分别实现了LeNet和VGG变体进行图像分类。通过打乱像素顺序的对照实验,直观验证了卷积网络利用图像空间结构的本质;从LeNet的63%到VGG的74.71%,看到了网络深度对复杂分类任务的提升作用。实验涵盖张量操作、模型定义、训练循环、超参数调优及8道思考题。
项目 内容
作者昵称 Morwen_OUC
本实验属于哪门课程? 中国海洋大学《软件工程原理与实践》
实验名称 实验3:卷积神经网络
完成日期 2026年10月18日
一、实验内容
本次实验在Google Colab(T4 GPU)上完成三个CNN相关的代码练习:①在MNIST上对比参数量相近的全连接网络与卷积网络,并验证打乱像素后CNN的优势消失;②用LeNet对CIFAR10分类;③用简化版VGG对CIFAR10分类。运行设备由torch.cuda.is_available()判断为cuda:0,同一份代码无需修改即可在CPU/GPU上运行,仅GPU速度更快。
第一部分:代码练习
练习1:MNIST上全连接网络vs卷积网络
关键对比:参数量几乎相同的全连接网络和卷积网络,谁在MNIST上更强?再把像素顺序打乱后会怎样?
导入PyTorch相关库,自动检测GPU设备,加载MNIST手写数字数据集(训练集60000张、测试集10000张,28×28灰度图)。
构造一个784→8→8→10的全连接网络(FC,6442参数)和一个两层卷积+池化的CNN(约5994参数),两者参数量几乎相同,唯一区别是CNN保留二维空间结构。
FC训练1个epoch后测试准确率为88%,CNN训练1个epoch后测试准确率为98%。参数量几乎相同的情况下,CNN比FC高出10个百分点。
个人理解: CNN之所以更强,是因为卷积利用了图像的局部性(相邻像素相关)和平移不变性(同一个物体在图中任何位置都应该被识别为同一类),而池化进一步增强了对微小平移的鲁棒性。FC把图片直接拉成784维向量,完全丢失了空间结构信息。
为了验证CNN确实在利用空间结构,我们用一个固定的随机置换打乱所有图片的像素顺序(对每张图用同一个permutation),肉眼看就是雪花噪点。
打乱后分别训练FC和CNN:
结果汇总:
原图 打乱像素后
FC(6442参数) 88% 90%(基本不变)
CNN(5994参数) 98% 92%(下降)
打乱像素后,FC准确率几乎不变(它本来就不看空间结构),而CNN的优势大幅缩水(从领先10个点缩到只领先2个点)。这反过来证明CNN确实在利用图像的二维邻域关系。
练习2:LeNet对CIFAR10分类
CIFAR10包含10类3×32×32彩色图(飞机、汽车、鸟、猫、鹿、狗、蛙、马、船、卡车)。数据经过transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))归一化到[-1,1]。
定义LeNet风格网络:Conv(3→6,5) → Pool → Conv(6→16,5) → Pool → FC(400→120→84→10)。用Adam(lr=0.001)训练10个epoch。
训练完成后,取8张测试图看预测效果:
LeNet在10000张测试图上的准确率为63%。
练习3:VGG变体对CIFAR10分类
按指导文档的结构定义简化版VGG:64 conv→pool → 128 conv→pool → 256 conv×2→pool → 512 conv×2→pool → 512 conv×2→pool → FC(512→10)。共约923万参数。
训练10个epoch后:
VGG在10000张测试图上的准确率为74.71%。
三个练习的准确率对比:
模型 数据集 参数量 测试准确率
FC(784→8→8→10) MNIST 6442 88%
CNN(两层卷积) MNIST 5994 98%
LeNet CIFAR10 ~6万 63%
VGG变体 CIFAR10 923万 74.71%
可以看到,网络越深、参数越多,在更复杂的CIFAR10上准确率越高(63% → 74.71%)。
第二部分:思考题
- DataLoader里shuffle取不同值有什么区别?
shuffle=True时每个epoch开始前会打乱训练数据的顺序,让每个batch里的样本组合不同,避免模型按固定顺序学习导致过拟合于特定batch的统计特性,也有利于梯度下降更平稳地收敛。shuffle=False时数据按原始顺序读取,训练集可能有类别排序(如CIFAR10默认按类别排列),导致模型先学完一类再学另一类,收敛不稳定。一般训练集shuffle=True,测试集shuffle=False(测试不需要打乱,保持顺序方便对照)。
- transform里取不同值有什么区别?
transform定义了对图像的预处理流水线。常见操作: - ToTensor():把PIL图片或numpy数组转换成PyTorch Tensor,像素值从[0,255]缩放到[0,1]; - Normalize(mean, std):对每个通道做标准化(x - mean) / std,把数据分布平移到均值0、标准差1,有利于训练稳定; - 还可以加RandomCrop、RandomHorizontalFlip、ColorJitter等数据增强操作,在训练时随机变换图像,相当于扩充数据集、防止过拟合。
训练集通常做增强+标准化,测试集只做ToTensor+标准化(不做随机变换,保证评估可复现)。
- epoch和batch的区别?
epoch:把整个训练集完整过一遍。一个epoch内,所有训练样本都被模型看到一次。
batch:每次模型参数更新时实际喂入的一小批样本数量(如batch_size=64)。一个epoch包含训练集大小 / batch_size个batch。
iteration:一个batch = 一次参数更新。
设epoch=10表示完整看10遍训练数据;batch_size=64表示每次64张图算一次梯度。batch_size越大梯度估计越准但内存占用越大;epoch太多会过拟合。
- 1×1卷积和全连接(FC)有什么区别?主要起什么作用?
形式上:1×1卷积在每个空间位置上做一次C_in × 1 × 1到C_out × 1 × 1的线性变换,相当于对每个像素位置的所有通道做一次全连接。它保持了空间维度(H×W)不变,只改变通道数。
与FC的区别:FC把所有空间位置拉平后做全局矩阵乘法,丢失空间结构;1×1卷积在每个位置独立做相同的线性变换,参数共享,保留空间布局。
作用:①跨通道信息融合(如把256通道压到64通道),降低计算量;②在不改变特征图尺寸的情况下增加网络深度和非线性;③相当于在通道维度上做特征重加权。
5. Residual Learning(残差学习)为什么能提升准确率?
深层网络在训练时会遇到"退化问题":网络加深后训练误差反而上升(不是过拟合,而是优化困难),因为多层非线性堆叠后难以学到恒等映射。ResNet的残差块把输出设计为H(x) = F(x) + x,即让网络学习残差F(x) = H(x) - x。这样如果最优映射接近恒等映射,只需把F(x)趋近于0,比直接学恒等映射容易得多;短路连接为梯度提供了一条"高速公路",反向传播时梯度可以直接传回浅层,缓解梯度消失。
- 练习2里的网络和1989年LeCun提出的LeNet有什么区别?
原始LeNet-5(1998年)结构:输入32×32灰度图 → Conv(1→6,5) → AvgPool → Conv(6→16,5) → AvgPool → FC(120→84→10)。本次实验的LeNet变体:输入是3×32×32彩色图;用MaxPool替代了AvgPool;激活函数用ReLU而非tanh;优化器用Adam而非SGD。整体结构思想一致,但适配了彩色输入并使用了现代激活函数和优化器。
- 练习2里卷积后feature map尺寸变小,如何应用Residual Learning?
标准残差块要求F(x)和x的尺寸相同才能相加。但卷积+池化后特征图的空间尺寸和通道数通常会变化,无法直接短路连接。解决方法:在短路路径上添加一个1×1卷积(如nn.Conv2d(C_in, C_out, kernel_size=1, stride=stride)),把x的通道数和空间尺寸投影到与F(x)相同,再相加。
- 有什么方法可以进一步提升准确率?
数据增强:随机裁剪、水平翻转、颜色抖动,扩充训练集;
更深更宽的网络:用ResNet、DenseNet等现代架构替代简单VGG;
正则化:Dropout、Weight Decay、Batch Normalization;
学习率调度:用StepLR/CosineAnnealingLR逐步降低学习率;
更好的优化器:SGD+Momentum + 学习率衰减通常比Adam泛化更好;
预训练:在ImageNet上预训练后微调(迁移学习)。
三、问题总结与体会
遇到的问题与解决:
CIFAR10下载极慢:Colab在国内访问多伦多大学服务器只有30~40kB/s,170MB需要近1小时。解决办法是让它在后台慢慢下载,期间不中断,等下完后再继续跑后续格子。
误点定义网络格导致准确率暴跌:LeNet训练完成后不小心又点了一下定义网络那格,把训练好的权重重置为随机初始化,导致测试准确率从63%暴跌到10%。解决办法是重新按顺序跑:定义网络 → 训练 → 测试。
GPU未切换:第一次跑第一格时输出device: cpu,说明没选GPU运行时。切到T4 GPU后重新跑,后续训练速度明显加快。
收获与体会:
通过FC vs CNN的对照实验,直观理解了卷积"利用空间结构"的本质——打乱像素后FC不变而CNN优势消失,比看书本定义深刻得多;从LeNet(63%)到VGG(74.71%)的对比,看到了网络深度和参数量对复杂图像分类任务的提升作用;学会了在Colab上完整走通"加载数据→定义网络→训练循环→测试评估"的深度学习流水线。