实验3:卷积神经网络(PyTorch CNN实践)
本博客详细记录了基于PyTorch的卷积神经网络入门实验在MNIST上对比了全连接网络与卷积网络的性能差异在CIFAR10上分别实现了LeNet和VGG变体进行图像分类。通过打乱像素顺序的对照实验直观验证了卷积网络利用图像空间结构的本质从LeNet的63%到VGG的74.71%看到了网络深度对复杂分类任务的提升作用。实验涵盖张量操作、模型定义、训练循环、超参数调优及8道思考题。项目 内容作者昵称 Morwen_OUC本实验属于哪门课程 中国海洋大学《软件工程原理与实践》实验名称 实验3卷积神经网络完成日期 2026年10月18日一、实验内容本次实验在Google ColabT4 GPU上完成三个CNN相关的代码练习①在MNIST上对比参数量相近的全连接网络与卷积网络并验证打乱像素后CNN的优势消失②用LeNet对CIFAR10分类③用简化版VGG对CIFAR10分类。运行设备由torch.cuda.is_available()判断为cuda:0同一份代码无需修改即可在CPU/GPU上运行仅GPU速度更快。第一部分代码练习练习1MNIST上全连接网络vs卷积网络关键对比参数量几乎相同的全连接网络和卷积网络谁在MNIST上更强再把像素顺序打乱后会怎样导入PyTorch相关库自动检测GPU设备加载MNIST手写数字数据集训练集60000张、测试集10000张28×28灰度图。构造一个784→8→8→10的全连接网络FC6442参数和一个两层卷积池化的CNN约5994参数两者参数量几乎相同唯一区别是CNN保留二维空间结构。FC训练1个epoch后测试准确率为88%CNN训练1个epoch后测试准确率为98%。参数量几乎相同的情况下CNN比FC高出10个百分点。个人理解 CNN之所以更强是因为卷积利用了图像的局部性相邻像素相关和平移不变性同一个物体在图中任何位置都应该被识别为同一类而池化进一步增强了对微小平移的鲁棒性。FC把图片直接拉成784维向量完全丢失了空间结构信息。为了验证CNN确实在利用空间结构我们用一个固定的随机置换打乱所有图片的像素顺序对每张图用同一个permutation肉眼看就是雪花噪点。打乱后分别训练FC和CNN结果汇总原图 打乱像素后FC6442参数 88% 90%基本不变CNN5994参数 98% 92%下降打乱像素后FC准确率几乎不变它本来就不看空间结构而CNN的优势大幅缩水从领先10个点缩到只领先2个点。这反过来证明CNN确实在利用图像的二维邻域关系。练习2LeNet对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)。用Adamlr0.001训练10个epoch。训练完成后取8张测试图看预测效果LeNet在10000张测试图上的准确率为63%。练习3VGG变体对CIFAR10分类按指导文档的结构定义简化版VGG64 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%。三个练习的准确率对比模型 数据集 参数量 测试准确率FC784→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取不同值有什么区别shuffleTrue时每个epoch开始前会打乱训练数据的顺序让每个batch里的样本组合不同避免模型按固定顺序学习导致过拟合于特定batch的统计特性也有利于梯度下降更平稳地收敛。shuffleFalse时数据按原始顺序读取训练集可能有类别排序如CIFAR10默认按类别排列导致模型先学完一类再学另一类收敛不稳定。一般训练集shuffleTrue测试集shuffleFalse测试不需要打乱保持顺序方便对照。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_size64。一个epoch包含训练集大小 / batch_size个batch。iteration一个batch 一次参数更新。设epoch10表示完整看10遍训练数据batch_size64表示每次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-51998年结构输入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_size1, stridestride)把x的通道数和空间尺寸投影到与F(x)相同再相加。有什么方法可以进一步提升准确率数据增强随机裁剪、水平翻转、颜色抖动扩充训练集更深更宽的网络用ResNet、DenseNet等现代架构替代简单VGG正则化Dropout、Weight Decay、Batch Normalization学习率调度用StepLR/CosineAnnealingLR逐步降低学习率更好的优化器SGDMomentum 学习率衰减通常比Adam泛化更好预训练在ImageNet上预训练后微调迁移学习。三、问题总结与体会遇到的问题与解决CIFAR10下载极慢Colab在国内访问多伦多大学服务器只有30~40kB/s170MB需要近1小时。解决办法是让它在后台慢慢下载期间不中断等下完后再继续跑后续格子。误点定义网络格导致准确率暴跌LeNet训练完成后不小心又点了一下定义网络那格把训练好的权重重置为随机初始化导致测试准确率从63%暴跌到10%。解决办法是重新按顺序跑定义网络 → 训练 → 测试。GPU未切换第一次跑第一格时输出device: cpu说明没选GPU运行时。切到T4 GPU后重新跑后续训练速度明显加快。收获与体会通过FC vs CNN的对照实验直观理解了卷积利用空间结构的本质——打乱像素后FC不变而CNN优势消失比看书本定义深刻得多从LeNet63%到VGG74.71%的对比看到了网络深度和参数量对复杂图像分类任务的提升作用学会了在Colab上完整走通加载数据→定义网络→训练循环→测试评估的深度学习流水线。