一、主要知识点总结
1. 卷积操作基础
-
卷积核(filter/kernel):在输入上滑动,执行点乘求和,提取局部特征。
-
输出尺寸公式(高度/宽度相同):
Hout=⌊Hin−K+2PS⌋+1Hout=⌊SHin−K+2P⌋+1
-
HinHin:输入尺寸
-
KK:卷积核大小
-
PP:填充(padding)
-
SS:步幅(stride)
-
2. 填充与步幅
-
填充(padding):在输入边界周围补零,用于控制输出尺寸、保留边缘信息。
-
padding='same'(PyTorch中可用):当 stride=1 时,输出尺寸等于输入尺寸。
-
-
步幅(stride):卷积核滑动的步长,步幅越大,输出尺寸越小。
3. 池化层(Pooling)
-
作用:下采样,减少特征图尺寸,降低计算量;扩大感受野;增强平移不变性。
-
最大池化(MaxPool):取窗口内最大值,保留显著特征。
-
平均池化(AvgPool):取窗口内平均值,平滑特征。
-
常用参数:kernel_size=2, stride=2,输出尺寸减半。
4. 多输入/多输出通道
-
输入通道数(in_channels):例如 RGB 图像为 3。
-
输出通道数(out_channels):每个输出通道对应一个卷积核(一组滤波器)。
-
卷积核形状:[out_channels, in_channels, kernel_height, kernel_width]
5. 感受野(Receptive Field)
-
定义:特征图上某个神经元在原始输入图像上所能看到的区域大小。
-
计算公式(从最后一层向前累加):
RFi=RFi+1+(Ki−1)×∏j=i+1LSjRFi=RFi+1+(Ki−1)×j=i+1∏LSj
简化函数(实验中所用):
python
rf = 1
for k, s in zip(reversed(kernel_sizes), reversed(strides)):
rf = rf + (k – 1) * s -
网络越深,感受野越大。
6. LeNet 网络结构(针对 MNIST 调整)
| conv1 | 5×5 conv, 6 通道 | 1×28×28 | 6×24×24 |
| pool1 | 2×2 maxpool, stride=2 | 6×24×24 | 6×12×12 |
| conv2 | 5×5 conv, 16 通道 | 6×12×12 | 16×8×8 |
| pool2 | 2×2 maxpool, stride=2 | 16×8×8 | 16×4×4 |
| flatten | 展平 | 16×4×4 | 256 |
| fc1 | 全连接 120 | 256 | 120 |
| fc2 | 全连接 84 | 120 | 84 |
| fc3 | 全连接 10 | 84 | 10 |
-
激活函数:ReLU(除输出层外)
-
损失函数:交叉熵 nn.CrossEntropyLoss()
7. 数据增强
-
训练时使用:随机旋转、水平翻转等,提高泛化能力。
-
测试时不用数据增强:保证评估的稳定性和一致性。
8. 设备管理
-
model.to(device) 将模型移到 GPU/CPU。
-
输入数据也需要 .to(device)。
-
评估时使用 with torch.no_grad(): 禁用梯度。
二、考试复习题(含例题)
选择题
1. 对于一个 32×32 的输入图像,使用 3×3 卷积核,stride=2,padding=0,输出特征图的大小是:
A. 15×15 ✅
B. 16×16
C. 14×14
D. 30×30
计算:(32 – 3 + 0)//2 + 1 = 29//2 + 1 = 14 + 1 = 15
2. 以下哪种操作可以保证 stride=1 时输出尺寸等于输入尺寸?
A. padding=0
B. padding=(kernel_size-1)//2 ✅
C. stride=2
D. 使用更大卷积核
3. 在 LeNet 网络中,经过 conv2 和 pool2 后,特征图的形状是:
A. 6×12×12
B. 16×4×4 ✅
C. 16×8×8
D. 120×1
conv2 输出 16×8×8,pool2(2,2) 减半为 16×4×4
4. 关于感受野,下列说法正确的是:
A. 浅层神经元感受野比深层大
B. 两层 3×3 卷积(stride=1)的感受野等于 5 ✅
C. 步幅增大不会改变感受野
D. 感受野只与卷积核大小有关
5. 训练时使用数据增强,测试时不使用,主要原因是:
A. 测试集数据量小
B. 保证评估的稳定性和一致性 ✅
C. 加快测试速度
D. 防止过拟合
填空题
卷积输出尺寸计算公式为:Hout=⌊Hin−K+2PS⌋+1Hout=⌊SHin−K+2P⌋+1。
在 PyTorch 中,nn.MaxPool2d(kernel_size=2, stride=2) 会使特征图的高和宽变为原来的 一半。
一个卷积层的权重张量形状为 [32, 64, 3, 3],则该层的输入通道数为 64,输出通道数为 32。
两层 3×3 卷积(步幅均为1)的感受野大小为 5。
LeNet 全连接层之前的展平操作使用 x = x.view(x.size(0), -1),其中 -1 表示 自动计算该维度大小。
简答题
1. 简述卷积层中 padding 和 stride 的作用,并说明 padding='same' 的含义。
padding 用于控制输出尺寸,保留边缘信息;stride 控制卷积核滑动的步长,影响输出大小和计算量。padding='same' 指当 stride=1 时,输出尺寸等于输入尺寸,通过自动添加合适的零填充实现。
2. 最大池化与平均池化的区别是什么?分别适用于什么场景?
最大池化取窗口最大值,保留显著纹理和边缘特征,适用于需要突出强特征的任务(如图像分类)。平均池化取窗口平均值,平滑特征,适用于需要保留背景信息的场景(如风格迁移)。CNN 中通常默认使用最大池化。
3. 为什么测试阶段不能使用数据增强?
数据增强引入随机性(随机旋转、翻转等),同一张图片多次预测结果会不同,导致准确率不稳定、不可重复。测试需要固定输入,以公平评估模型性能并模拟真实应用(输入通常不经随机变换)。
4. 给定两层卷积:第一层 kernel=3, stride=2;第二层 kernel=3, stride=1。计算第二层输出在原始输入上的感受野。
从最后一层(第二层)开始向前计算:
第二层自身的感受野为 1(相对于其输入)。
向前累加:rf = 1 + (3-1)*1 = 3(考虑第一层到第二层的映射)
再往前:rf = 3 + (3-1)*2 = 3 + 4 = 7。
最终感受野为 7。
计算/代码填空
题目1:补全以下卷积输出形状的计算结果。
| 32×32×3 | Conv2d(3,16,3,stride=1,padding=0) | 30×30×16 |
| 30×30×16 | MaxPool2d(2,stride=2) | 15×15×16 |
| 32×32×3 | Conv2d(3,16,5,stride=2,padding=1) | 16×16×16 |
| 28×28×6 | Conv2d(6,16,5,stride=1,padding=0) | 24×24×16 |
题目2:补全 LeNet 的 forward 函数中的缺失代码。
python
def forward(self, x):
x = self.pool1(torch.relu(self.conv1(x)))
x = self.pool2(torch.relu(self.conv2(x)))
x = x.view(x.size(0), -1) # 填空:展平
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
题目3:判断以下代码是否正确?若不正确请说明理由。
python
test_transform = transforms.Compose([
transforms.RandomRotation(10),
transforms.ToTensor()
])
不正确。测试阶段不应使用随机数据增强(如 RandomRotation),否则评估结果不稳定。测试集应仅使用 ToTensor() 和 Normalize()。
分析题
题目:某同学在 MNIST 上训练 LeNet,发现测试准确率只有 85%,训练准确率很高。分析可能的原因并提出改进方法。
参考答案:
可能是过拟合或数据预处理不当。改进方法:
-
添加数据增强(随机旋转、平移)
-
增大训练集(若已使用增强则检查强度)
-
添加 Dropout 或增大权重衰减
-
降低模型复杂度(但 LeNet 对 MNIST 已足够小,过拟合概率较低,更可能是数据归一化错误或标签错乱)
-
检查归一化参数是否正确(MNIST 均值 0.1307,标准差 0.3081)



