姓名:zgx 学号:******姓名和学号zgx,******本实验属于哪门课程中国海洋大学25秋《软件工程原理与实践》实验名称实验3:卷积神经网络一、实验内容本次实验中的三个实验均来自以下链接:实验三:https://oucaigroup.feishu.cn/wiki/ZZHiwlpZJiLuNCkpL5ScHeCTnqg实验四:https://oucaigroup.feishu.cn/wiki/TWFdw1ecwiBILikSJrecvMX4nOf实验五:https://oucaigroup.feishu.cn/wiki/UJ1xwmjVziixTckP1zFcgNgcnqc1. 实验三:MNIST数据集分类1.1 基础准备这部分代码主要是在为后面的神经网络训练做准备,导入所需要的库、定义模型参数统计函数、设置运行设备三部分。1.2 加载数据(MNIST)1.2.1 MNIST 数据集并预处理设置图片的大小为28*28, 并设置输出类别数10(0-9), 并加载训练集和测试集。对图片进行预处理, transforms.ToTensor()将图片转换成张量,并将像素值缩放到0~1, 通过transforms.Normalize()对像素进行标准化,并用transforms.Compose()将上述操作组合起来依次执行。1.2.2 显示数据集中的部分图像取出 MNIST 训练集中的前 20 张图片,按 4 行 5 列显示出来。1.3 创建网络1.3.1 构建神经网络这部分代码定义了两种模型:全连接神经网络首先将每张 28×28 的图片展开为包含 784 个像素值的一维向量,然后依次通过两个隐藏层和一个输出层,引入ReLU函数进行非线性变换,最后通过LogSoftmax输出各类别的对数概率。卷积神经网络直接接收二维图像,通过两次卷积提取图像中的笔画、边缘等局部特征,并在每次卷积后使用 ReLU 激活和最大池化。将大小从 28×28 逐步缩小为 4×4,再将特征展开,送入两个全连接层完成分类。这部分主要是为后续训练和比较分类做准备。1.3.2 定义训练和测试函数对每批数据依次执行梯度清零、前向传播、损失计算、反向传播和参数更新。损失计算采用负对数似然损失,主要是用于衡量预测结果与真实标签之间的差距。每隔 100 个批次输出一次训练进度和当前批次的损失,这样也能方便观察结果。最后是进行测试,选择每张图片输出值最大的类别作为预测标签,将预测标签与真实标签进行比较,累计预测正确的数量,同时累加各批次的损失。计算平均损失和分类准确率。1.4 进行训练1.4.1 在小型全连接网络上训练先设置隐藏层有8个神经元,随后调用FC2Layer创建全连接模型。开始进行训练。其中的optim.SGD()是带动量的随机梯度下降优化器。有动量可以使参数更新时结合之前积累的更新方向,可以更好的减少来回震荡。1.4.2 在卷积神经网络上训练定义两个卷积层各输出 6 个特征通道,利用CNN()创建卷积神经网络,也同样为CNN设计带动量的随机梯度下降优化器。最后输出结果通过以上对比,可以发现含有相同参数的CNN效果要明显优于简单的全连接网络。主要是因为CNN中的“卷积”和“池化”可以更好的挖掘图像中的信息,帮助神经网络更精准的识别。1.5 打乱像素顺序后再次在两个网络上训练与测试如果把图像中的像素打乱顺序,“卷积”和“池化”会难以发挥作用。再次实验观察两个神经网络上的结果如何。1.5.1 随机打乱像素后图像的形态把像素打乱就是:把图片中的28\×28=784 个像素随机打乱,然后组成的图像。1.5.2 重新定义训练与测试函数与之前的测试函数没多大区别,只是对数据进行了打乱顺序操作。1.5.3 在小型全连接网络上训练1.5.3 在卷积神经网络上训练通过两次实验来看,全连接网络的性能基本没有发生变化,但是卷积神经网络的性能明显的下降。这主要因为卷积神经网络的核心“卷积”和“池化”需要利用像素之间的局部关系,打乱之后这些像素关系就无法得到利用了,也大大影响了卷积神经网络的性能。2. 实验四:CIFAR10 数据集分类2.1 基础准备这部分代码完成了模型训练前的数据准备工作。先导入所需的库,并根据 GPU 是否可用选择计算设备。随后,将图片转换成张量,把像素值调整到 −1 到 1 的范围,再分别加载 CIFAR-10 的训练集和测试集,使用 DataLoader 按批次读取数据。训练时打乱样本顺序,测试时保持原有顺序。最后定义类别名称,方便查看预测结果。展示CIFAR10 数据集里面的一些照片:这里的迭代器没有 .next() 方法,需要使用 Python 内置的 next() 函数获取一批数据。将原语句改成:images, labels = next(iter(trainloader))即可2.2 定义网络、损失函数和优化器这部分代码搭建了一个包含两个卷积层、两次最大池化和三个全连接层的分类网络。卷积层负责提取图片特征,池化层负责缩小特征图、减少计算量,全连接层则综合这些特征,输出十个类别的得分。图片经过卷积和池化后,每张得到 16 张大小为 5×5 的特征图,需要先展开成 400 个特征值,再送入全连接层。最后,代码将模型放到指定设备上,并设置交叉熵损失函数和 Adam 优化器,为后续计算损失和更新参数做好准备。2.3 训练网络这部分代码实现了模型的训练过程,共训练 10 轮,每轮按批次读取训练图片和真实标签。每个批次先清空之前的梯度,再将图片输入模型,计算预测结果与真实标签之间的损失,随后通过反向传播计算梯度,由优化器更新模型参数。反向传播负责计算梯度,而优化器负责真正调整参数,两者共同完成模型的学习。训练过程中还会定期输出当前批次的损失,方便观察训练进度和损失变化。2.4 训练结果从测试集中取出8张图片:这部分也会报错,解决方法同2.1中的图片展示方法把图片输入模型,看看CNN把这些图片识别成了什么:可以看出有部分图片识别错了。网络在整个数据集上的表现:3. 实验五:VGG16对CIFAR10分类3.1 定义dataloader这部分代码在原有的数据加载流程中加入了数据增强,并分别设置训练集和测试集的预处理方式。训练图片经过随机裁剪和水平翻转后,同一张图片在不同轮次中可能呈现不同的位置和朝向,有助于模型适应图片的变化。测试图片只进行张量转换和标准化,保证评估过程稳定。同时,代码调整了各通道的标准化参数,并将训练和测试的批次大小都设为 128。也就是 transform 负责处理单张图片,而 DataLoader 负责把图片和标签组织成批次,两者共同为模型提供训练和测试数据。3.2 VGG网络定义模型实现代码:这部分代码通过配置列表搭建了一个 VGG 风格的卷积神经网络,列表中的数字表示卷积层的输出通道数,M 表示最大池化。相比之前的简单网络,它增加了卷积层和通道数,并在每个卷积层后加入批量归一化和 ReLU,以提取更丰富的特征并帮助稳定训练。图片经过五次池化后,由 32×32 缩小到 1×1,最终得到 512 个特征,再通过全连接层输出十个类别的得分。代码中需要修改一下语句:self.features = self._make_layers(self.cfg),否则会导致变量名不一致。代码中需要修改一下语句:self.classifier = nn.Linear(512, 10)(将2048改为512),适配后续的代码参数,否则无法运行成功。初始化一些参数:使用交叉熵损失函数衡量预测结果与真实标签之间的差距,再设置学习率为 0.001 的 Adam 优化器,用于后续更新模型参数。对比之下损失函数和优化方式是保持不变的。3.3 网络训练训练的代码和之前完全一样:3.4 测试验证准确率测试代码也与之前完全一样:根据结果可以发现:一个简化版的VGG网络就可以将准确率从63%大幅度提升到82.79%二、问题总结与体会1. DataLoader 中,shuffle 取不同值有什么区别?shuffle决定读取样本时是否打乱顺序。shuffle=True:每轮训练重新打乱样本顺序,使不同 batch 的样本组合发生变化,减少固定排列顺序对训练的影响。shuffle=False:按数据集原有顺序读取,每轮的样本顺序基本一致。训练集通常设为True,测试集通常设为False。训练时打乱数据有助于模型学习;测试时不更新参数,一般不需要打乱,也方便对应预测结果和原始样本。2. transform 中,取不同值有什么区别?Normalize(mean, std)是按通道调整像素数值,改变输入数据的中心位置和数值尺度。其计算公式为:x′=x−meanstd x'=\frac{x-\text{mean}}{\text{std}}x′=stdx−mean例如,Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))中,两组数分别对应 RGB 三个通道的均值参数和标准差参数。输入已经在[0,1]时,变换后落在[-1,1]。这不代表处理后的实际均值一定为 0、标准差一定为 1。只有使用数据本身的相应统计量,才有这样的标准化效果。3. epoch 和 batch 的区别是什么?batch:一次送入模型的一批样本。batch size:这一批包含多少个样本。epoch:整个训练集被完整训练一遍。例如,训练集有 50,000 张图片,batch_size=100,那么:1 个 epoch=500 个 batch 1\text{ 个 epoch}=500\text{ 个 batch}1个epoch=500个batch通常每处理一个 batch,就进行一次前向传播、损失计算、反向传播和参数更新。因此,训练 10 个 epoch,通常会更新参数 5,000 次。4. 1×1 卷积和 FC 有什么区别?主要起什么作用?1×1 卷积虽然只覆盖一个空间位置,但会使用该位置的所有输入通道,对这些通道进行加权组合。例如,输入为64×32×32,使用 16 个 1×1 卷积核,步长为 1、不填充时,输出为:64×32×32→16×32×32 64\times32\times32\rightarrow16\times32\times3264×32×32→16×32×32空间尺寸不变,通道数由 64 变成 16。对比项1×1 卷积展平后的全连接层 FC处理范围每个空间位置上的所有通道展平后的全部输入特征空间结构保留二维位置结构通常输出一个特征向量参数共享不同空间位置使用同一组权重不同输入位置通常使用不同权重常见作用通道融合、升降维、残差分支对齐综合全部特征,输出分类得分1×1 卷积主要有三个用途:调整通道数,使特征符合后续网络的输入要求。融合不同通道的信息,学习新的特征组合。先降低通道数,再进行较大的卷积,减少后续计算量。它本身仍是线性变换,接上 ReLU 等激活函数后,才能引入非线性。5. Residual Learning 为什么能够提升准确率?普通网络直接学习目标映射 H(x),残差学习则让网络学习:F(x)=H(x)−x F(x)=H(x)-xF(x)=H(x)−x最后通过跳跃连接得到:y=F(x)+x y=F(x)+xy=F(x)+x也就是保留输入特征,再学习需要补充或修正的部分。它主要解决深层网络难以训练的问题:保留原有信息。输入可以通过跳跃连接直接传到后面,不必完全依赖多层变换。方便梯度传播。反向传播多了一条直接路径,有助于减轻深层网络的梯度传播困难。缓解网络退化。如果新增的层暂时学不到有效改进,可以让残差接近 0,使整个模块接近恒等映射,避免新增层必须重新学会“保留输入”。因此,残差结构使更深的网络更容易优化,从而有机会学到更有效的特征并提高准确率。6. 代码练习二中的网络,与 LeNet 有什么区别?代码练习二采用的是 LeNet 风格的卷积神经网络,由两层卷积、两次最大池化和三层全连接组成,用于 CIFAR-10 图像分类。输入图片为三通道的 32×32 彩色图像,数据在网络中的变化如下,表中省略 batch 维度:网络操作输出形状输入图片3×32×32第一层 5×5 卷积,接 ReLU6×28×28第一次 2×2 最大池化6×14×14第二层 5×5 卷积,接 ReLU16×10×10$第二次 2×2 最大池化16×5×516×5×516×5×5展平400第一层全连接,接 ReLU120第二层全连接,接 ReLU84第三层全连接10两者的共同点是采用局部连接和卷积权重共享来提取图像特征,再通过后续网络完成分类。它们都能直接从图像中学习特征,不需要手工设计特征。主要区别如下:激活函数不同。早期网络使用 sigmoid 类的平滑饱和激活函数,本实验在两层卷积和前两层全连接之后使用 ReLU。ReLU 计算简单,正值区域不会因激活函数饱和而使梯度趋近于零,有利于训练。下采样方式不同。本实验明确使用MaxPool2d(2, 2),每次取局部区域的最大值,使特征图的高、宽减半。1989 年网络的下采样由其局部连接和步长设计实现,不能直接理解为本代码中的独立最大池化层。具体层结构和参数配置不同。本实验的卷积通道数为3→6→16,全连接层为400→120→84→10。它沿用了 LeNet 系列的设计思路,但不是对 1989 年网络结构的原样复现。训练配置不同。本实验使用交叉熵损失和 Adam 优化器,学习率为0.001。最后一层直接输出 10 个类别的原始得分,由CrossEntropyLoss完成相应计算,因此不需要在网络末尾额外添加 Softmax。7. 卷积后 feature map 尺寸变小,如何应用 Residual Learning?关键要求是:参与相加的两个张量必须具有相同的形状,包括通道数、高和宽。尺寸一致时,可以直接相加:y=F(x)+x y=F(x)+xy=F(x)+x尺寸不一致时,需要先调整捷径分支:y=F(x)+P(x) y=F(x)+P(x)y=F(x)+P(x)其中,P(x) 是用于匹配形状的变换。情况处理方法高、宽不变,通道数改变用 1×1 卷积调整通道数高、宽缩小,例如减半用带步长的 1×1 卷积,同时调整空间尺寸和通道数因未填充卷积而缩小,如32→28可修改主分支的 padding 保持尺寸,或对捷径分支进行匹配的裁剪等处理例如,主分支把输入从64×32×32变成128×16×16,捷径分支可以使用nn.Conv2d(64, 128, kernel_size=1, stride=2)。这样两条分支的输出都是128×16×16,可以逐元素相加。8. 有什么方法可以进一步提升准确率?可以从以下方面改进:方法具体做法与目的数据增强训练时加入适度的随机裁剪、水平翻转,减少对固定图像形式的依赖调整学习率前期使用合适的学习率,后期逐步降低,让参数调整更细调整训练轮数训练不足时增加 epoch;出现过拟合时不再单纯延长训练改进网络结构适当增加卷积通道或深度,引入残差连接,提高特征提取能力加入 BatchNorm改善网络的训练稳定性控制过拟合使用权重衰减、适当的 Dropout 或早停检查数据处理确保标签正确、标准化一致,测试时调用model.eval()首先应同时观察训练集和验证集的损失、准确率,再决定调整方向:训练集和验证集都表现不好:重点检查是否训练不足、学习率不合适,或模型能力不足。训练集很好,验证集明显较差:重点考虑过拟合,增加数据增强和正则化。训练过程中损失反复大幅波动:优先检查学习率和输入数据。心得体会通过本次实验,我学会了在 Colab 中使用 PyTorch 完成 MNIST 和 CIFAR-10 图像分类,熟悉了数据预处理、模型搭建、训练和测试的基本过程,也弄清了卷积层、池化层和全连接层各自的作用,对图片如何经过网络得到分类结果有了更具体的认识。通过简单卷积网络和 VGG 网络的对比,我进一步理解了不同网络结构在特征提取方式上的差异。同时也认识到,图像分类效果不仅与网络结构有关,数据增强、学习率和训练轮数等设置也会影响结果,不能只靠增加网络层数来提高准确率。这次实验让我逐渐能够把代码中的操作与所学原理联系起来,对卷积神经网络有了更清楚的理解,也学会了在遇到维度不匹配等问题时,沿着数据在网络中的变化过程查找原因。
姓名:zgx 学号:******姓名和学号zgx,******本实验属于哪门课程中国海洋大学25秋《软件工程原理与实践》实验名称实验3:卷积神经网络一、实验内容本次实验中的三个实验均来自以下链接:实验三:https://oucaigroup.feishu.cn/wiki/ZZHiwlpZJiLuNCkpL5ScHeCTnqg实验四:https://oucaigroup.feishu.cn/wiki/TWFdw1ecwiBILikSJrecvMX4nOf实验五:https://oucaigroup.feishu.cn/wiki/UJ1xwmjVziixTckP1zFcgNgcnqc1. 实验三:MNIST数据集分类1.1 基础准备这部分代码主要是在为后面的神经网络训练做准备,导入所需要的库、定义模型参数统计函数、设置运行设备三部分。1.2 加载数据(MNIST)1.2.1 MNIST 数据集并预处理设置图片的大小为28*28, 并设置输出类别数10(0-9), 并加载训练集和测试集。对图片进行预处理, transforms.ToTensor()将图片转换成张量,并将像素值缩放到0~1, 通过transforms.Normalize()对像素进行标准化,并用transforms.Compose()将上述操作组合起来依次执行。1.2.2 显示数据集中的部分图像取出 MNIST 训练集中的前 20 张图片,按 4 行 5 列显示出来。1.3 创建网络1.3.1 构建神经网络这部分代码定义了两种模型:全连接神经网络首先将每张 28×28 的图片展开为包含 784 个像素值的一维向量,然后依次通过两个隐藏层和一个输出层,引入ReLU函数进行非线性变换,最后通过LogSoftmax输出各类别的对数概率。卷积神经网络直接接收二维图像,通过两次卷积提取图像中的笔画、边缘等局部特征,并在每次卷积后使用 ReLU 激活和最大池化。将大小从 28×28 逐步缩小为 4×4,再将特征展开,送入两个全连接层完成分类。这部分主要是为后续训练和比较分类做准备。1.3.2 定义训练和测试函数对每批数据依次执行梯度清零、前向传播、损失计算、反向传播和参数更新。损失计算采用负对数似然损失,主要是用于衡量预测结果与真实标签之间的差距。每隔 100 个批次输出一次训练进度和当前批次的损失,这样也能方便观察结果。最后是进行测试,选择每张图片输出值最大的类别作为预测标签,将预测标签与真实标签进行比较,累计预测正确的数量,同时累加各批次的损失。计算平均损失和分类准确率。1.4 进行训练1.4.1 在小型全连接网络上训练先设置隐藏层有8个神经元,随后调用FC2Layer创建全连接模型。开始进行训练。其中的optim.SGD()是带动量的随机梯度下降优化器。有动量可以使参数更新时结合之前积累的更新方向,可以更好的减少来回震荡。1.4.2 在卷积神经网络上训练定义两个卷积层各输出 6 个特征通道,利用CNN()创建卷积神经网络,也同样为CNN设计带动量的随机梯度下降优化器。最后输出结果通过以上对比,可以发现含有相同参数的CNN效果要明显优于简单的全连接网络。主要是因为CNN中的“卷积”和“池化”可以更好的挖掘图像中的信息,帮助神经网络更精准的识别。1.5 打乱像素顺序后再次在两个网络上训练与测试如果把图像中的像素打乱顺序,“卷积”和“池化”会难以发挥作用。再次实验观察两个神经网络上的结果如何。1.5.1 随机打乱像素后图像的形态把像素打乱就是:把图片中的28\×28=784 个像素随机打乱,然后组成的图像。1.5.2 重新定义训练与测试函数与之前的测试函数没多大区别,只是对数据进行了打乱顺序操作。1.5.3 在小型全连接网络上训练1.5.3 在卷积神经网络上训练通过两次实验来看,全连接网络的性能基本没有发生变化,但是卷积神经网络的性能明显的下降。这主要因为卷积神经网络的核心“卷积”和“池化”需要利用像素之间的局部关系,打乱之后这些像素关系就无法得到利用了,也大大影响了卷积神经网络的性能。2. 实验四:CIFAR10 数据集分类2.1 基础准备这部分代码完成了模型训练前的数据准备工作。先导入所需的库,并根据 GPU 是否可用选择计算设备。随后,将图片转换成张量,把像素值调整到 −1 到 1 的范围,再分别加载 CIFAR-10 的训练集和测试集,使用 DataLoader 按批次读取数据。训练时打乱样本顺序,测试时保持原有顺序。最后定义类别名称,方便查看预测结果。展示CIFAR10 数据集里面的一些照片:这里的迭代器没有 .next() 方法,需要使用 Python 内置的 next() 函数获取一批数据。将原语句改成:images, labels = next(iter(trainloader))即可2.2 定义网络、损失函数和优化器这部分代码搭建了一个包含两个卷积层、两次最大池化和三个全连接层的分类网络。卷积层负责提取图片特征,池化层负责缩小特征图、减少计算量,全连接层则综合这些特征,输出十个类别的得分。图片经过卷积和池化后,每张得到 16 张大小为 5×5 的特征图,需要先展开成 400 个特征值,再送入全连接层。最后,代码将模型放到指定设备上,并设置交叉熵损失函数和 Adam 优化器,为后续计算损失和更新参数做好准备。2.3 训练网络这部分代码实现了模型的训练过程,共训练 10 轮,每轮按批次读取训练图片和真实标签。每个批次先清空之前的梯度,再将图片输入模型,计算预测结果与真实标签之间的损失,随后通过反向传播计算梯度,由优化器更新模型参数。反向传播负责计算梯度,而优化器负责真正调整参数,两者共同完成模型的学习。训练过程中还会定期输出当前批次的损失,方便观察训练进度和损失变化。2.4 训练结果从测试集中取出8张图片:这部分也会报错,解决方法同2.1中的图片展示方法把图片输入模型,看看CNN把这些图片识别成了什么:可以看出有部分图片识别错了。网络在整个数据集上的表现:3. 实验五:VGG16对CIFAR10分类3.1 定义dataloader这部分代码在原有的数据加载流程中加入了数据增强,并分别设置训练集和测试集的预处理方式。训练图片经过随机裁剪和水平翻转后,同一张图片在不同轮次中可能呈现不同的位置和朝向,有助于模型适应图片的变化。测试图片只进行张量转换和标准化,保证评估过程稳定。同时,代码调整了各通道的标准化参数,并将训练和测试的批次大小都设为 128。也就是 transform 负责处理单张图片,而 DataLoader 负责把图片和标签组织成批次,两者共同为模型提供训练和测试数据。3.2 VGG网络定义模型实现代码:这部分代码通过配置列表搭建了一个 VGG 风格的卷积神经网络,列表中的数字表示卷积层的输出通道数,M 表示最大池化。相比之前的简单网络,它增加了卷积层和通道数,并在每个卷积层后加入批量归一化和 ReLU,以提取更丰富的特征并帮助稳定训练。图片经过五次池化后,由 32×32 缩小到 1×1,最终得到 512 个特征,再通过全连接层输出十个类别的得分。代码中需要修改一下语句:self.features = self._make_layers(self.cfg),否则会导致变量名不一致。代码中需要修改一下语句:self.classifier = nn.Linear(512, 10)(将2048改为512),适配后续的代码参数,否则无法运行成功。初始化一些参数:使用交叉熵损失函数衡量预测结果与真实标签之间的差距,再设置学习率为 0.001 的 Adam 优化器,用于后续更新模型参数。对比之下损失函数和优化方式是保持不变的。3.3 网络训练训练的代码和之前完全一样:3.4 测试验证准确率测试代码也与之前完全一样:根据结果可以发现:一个简化版的VGG网络就可以将准确率从63%大幅度提升到82.79%二、问题总结与体会1. DataLoader 中,shuffle 取不同值有什么区别?shuffle决定读取样本时是否打乱顺序。shuffle=True:每轮训练重新打乱样本顺序,使不同 batch 的样本组合发生变化,减少固定排列顺序对训练的影响。shuffle=False:按数据集原有顺序读取,每轮的样本顺序基本一致。训练集通常设为True,测试集通常设为False。训练时打乱数据有助于模型学习;测试时不更新参数,一般不需要打乱,也方便对应预测结果和原始样本。2. transform 中,取不同值有什么区别?Normalize(mean, std)是按通道调整像素数值,改变输入数据的中心位置和数值尺度。其计算公式为:x′=x−meanstd x'=\frac{x-\text{mean}}{\text{std}}x′=stdx−mean例如,Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))中,两组数分别对应 RGB 三个通道的均值参数和标准差参数。输入已经在[0,1]时,变换后落在[-1,1]。这不代表处理后的实际均值一定为 0、标准差一定为 1。只有使用数据本身的相应统计量,才有这样的标准化效果。3. epoch 和 batch 的区别是什么?batch:一次送入模型的一批样本。batch size:这一批包含多少个样本。epoch:整个训练集被完整训练一遍。例如,训练集有 50,000 张图片,batch_size=100,那么:1 个 epoch=500 个 batch 1\text{ 个 epoch}=500\text{ 个 batch}1个epoch=500个batch通常每处理一个 batch,就进行一次前向传播、损失计算、反向传播和参数更新。因此,训练 10 个 epoch,通常会更新参数 5,000 次。4. 1×1 卷积和 FC 有什么区别?主要起什么作用?1×1 卷积虽然只覆盖一个空间位置,但会使用该位置的所有输入通道,对这些通道进行加权组合。例如,输入为64×32×32,使用 16 个 1×1 卷积核,步长为 1、不填充时,输出为:64×32×32→16×32×32 64\times32\times32\rightarrow16\times32\times3264×32×32→16×32×32空间尺寸不变,通道数由 64 变成 16。对比项1×1 卷积展平后的全连接层 FC处理范围每个空间位置上的所有通道展平后的全部输入特征空间结构保留二维位置结构通常输出一个特征向量参数共享不同空间位置使用同一组权重不同输入位置通常使用不同权重常见作用通道融合、升降维、残差分支对齐综合全部特征,输出分类得分1×1 卷积主要有三个用途:调整通道数,使特征符合后续网络的输入要求。融合不同通道的信息,学习新的特征组合。先降低通道数,再进行较大的卷积,减少后续计算量。它本身仍是线性变换,接上 ReLU 等激活函数后,才能引入非线性。5. Residual Learning 为什么能够提升准确率?普通网络直接学习目标映射 H(x),残差学习则让网络学习:F(x)=H(x)−x F(x)=H(x)-xF(x)=H(x)−x最后通过跳跃连接得到:y=F(x)+x y=F(x)+xy=F(x)+x也就是保留输入特征,再学习需要补充或修正的部分。它主要解决深层网络难以训练的问题:保留原有信息。输入可以通过跳跃连接直接传到后面,不必完全依赖多层变换。方便梯度传播。反向传播多了一条直接路径,有助于减轻深层网络的梯度传播困难。缓解网络退化。如果新增的层暂时学不到有效改进,可以让残差接近 0,使整个模块接近恒等映射,避免新增层必须重新学会“保留输入”。因此,残差结构使更深的网络更容易优化,从而有机会学到更有效的特征并提高准确率。6. 代码练习二中的网络,与 LeNet 有什么区别?代码练习二采用的是 LeNet 风格的卷积神经网络,由两层卷积、两次最大池化和三层全连接组成,用于 CIFAR-10 图像分类。输入图片为三通道的 32×32 彩色图像,数据在网络中的变化如下,表中省略 batch 维度:网络操作输出形状输入图片3×32×32第一层 5×5 卷积,接 ReLU6×28×28第一次 2×2 最大池化6×14×14第二层 5×5 卷积,接 ReLU16×10×10$第二次 2×2 最大池化16×5×516×5×516×5×5展平400第一层全连接,接 ReLU120第二层全连接,接 ReLU84第三层全连接10两者的共同点是采用局部连接和卷积权重共享来提取图像特征,再通过后续网络完成分类。它们都能直接从图像中学习特征,不需要手工设计特征。主要区别如下:激活函数不同。早期网络使用 sigmoid 类的平滑饱和激活函数,本实验在两层卷积和前两层全连接之后使用 ReLU。ReLU 计算简单,正值区域不会因激活函数饱和而使梯度趋近于零,有利于训练。下采样方式不同。本实验明确使用MaxPool2d(2, 2),每次取局部区域的最大值,使特征图的高、宽减半。1989 年网络的下采样由其局部连接和步长设计实现,不能直接理解为本代码中的独立最大池化层。具体层结构和参数配置不同。本实验的卷积通道数为3→6→16,全连接层为400→120→84→10。它沿用了 LeNet 系列的设计思路,但不是对 1989 年网络结构的原样复现。训练配置不同。本实验使用交叉熵损失和 Adam 优化器,学习率为0.001。最后一层直接输出 10 个类别的原始得分,由CrossEntropyLoss完成相应计算,因此不需要在网络末尾额外添加 Softmax。7. 卷积后 feature map 尺寸变小,如何应用 Residual Learning?关键要求是:参与相加的两个张量必须具有相同的形状,包括通道数、高和宽。尺寸一致时,可以直接相加:y=F(x)+x y=F(x)+xy=F(x)+x尺寸不一致时,需要先调整捷径分支:y=F(x)+P(x) y=F(x)+P(x)y=F(x)+P(x)其中,P(x) 是用于匹配形状的变换。情况处理方法高、宽不变,通道数改变用 1×1 卷积调整通道数高、宽缩小,例如减半用带步长的 1×1 卷积,同时调整空间尺寸和通道数因未填充卷积而缩小,如32→28可修改主分支的 padding 保持尺寸,或对捷径分支进行匹配的裁剪等处理例如,主分支把输入从64×32×32变成128×16×16,捷径分支可以使用nn.Conv2d(64, 128, kernel_size=1, stride=2)。这样两条分支的输出都是128×16×16,可以逐元素相加。8. 有什么方法可以进一步提升准确率?可以从以下方面改进:方法具体做法与目的数据增强训练时加入适度的随机裁剪、水平翻转,减少对固定图像形式的依赖调整学习率前期使用合适的学习率,后期逐步降低,让参数调整更细调整训练轮数训练不足时增加 epoch;出现过拟合时不再单纯延长训练改进网络结构适当增加卷积通道或深度,引入残差连接,提高特征提取能力加入 BatchNorm改善网络的训练稳定性控制过拟合使用权重衰减、适当的 Dropout 或早停检查数据处理确保标签正确、标准化一致,测试时调用model.eval()首先应同时观察训练集和验证集的损失、准确率,再决定调整方向:训练集和验证集都表现不好:重点检查是否训练不足、学习率不合适,或模型能力不足。训练集很好,验证集明显较差:重点考虑过拟合,增加数据增强和正则化。训练过程中损失反复大幅波动:优先检查学习率和输入数据。心得体会通过本次实验,我学会了在 Colab 中使用 PyTorch 完成 MNIST 和 CIFAR-10 图像分类,熟悉了数据预处理、模型搭建、训练和测试的基本过程,也弄清了卷积层、池化层和全连接层各自的作用,对图片如何经过网络得到分类结果有了更具体的认识。通过简单卷积网络和 VGG 网络的对比,我进一步理解了不同网络结构在特征提取方式上的差异。同时也认识到,图像分类效果不仅与网络结构有关,数据增强、学习率和训练轮数等设置也会影响结果,不能只靠增加网络层数来提高准确率。这次实验让我逐渐能够把代码中的操作与所学原理联系起来,对卷积神经网络有了更清楚的理解,也学会了在遇到维度不匹配等问题时,沿着数据在网络中的变化过程查找原因。