CS231n笔记08:CNN训练
P1:权重初始化
初始化大小选择
初始化权重的示例:
1 | dims = [4096] * 7 |
在这段代码中,使用p来控制权重的初始化范围。不同的p值会影响网络的训练效果。p较小时(如0.01),随着层数加深,方差逐渐趋近于0,导致梯度消失;

p较大时(如0.05),方差会变得非常大,导致梯度爆炸。

Kaiming/MSRA Initialization
为了解决p的选择问题,使用Kaiming/MSRA初始化方法:
1 | for Din, Dout in zip(dims[:-1], dims[1:]): |

这种初始化方法根据输入维度动态调整权重的标准差,从而保持每层输出的方差稳定,避免梯度消失或爆炸问题。理解这种方法的关键在于,由于每次使用ReLU函数会关闭一半的激活值,为了保持信号的方差不变,初始化的方差应当乘2,因此有了这个 修正。
P2:数据处理与增强
TLDR for Image Normalization
在训练神经网络时,通常会对输入图像进行归一化处理。使用以下步骤:
- 计算每个通道的均值和标准差。
- 对每个通道进行标准化处理:
1 | mean = np.mean(pixel[:,:,c]) |
正则化方法
在训练中,对于 可以为其增加一定的随机性(如Dropout,随机丢弃一定的激活值)。那么在测试中,就有:。这意味着在测试时,模型的输出是对所有可能的随机性进行平均的结果,从而提高模型的泛化能力。
数据增强
数据增强(Data Augmentation)是一类非常常用的正则化手段:在不改变标签语义的前提下,对输入图像做随机变换,等价于“用同一张图生成更多不同但合理的训练样本”,从而降低过拟合、提升泛化。
一个典型训练流程可以理解为:加载图像与标签(例如“cat”)→ 对图像做随机变换(augmentation)→ 输入 CNN 前向计算 → 计算 loss 并反向传播更新参数。关键点是:增强发生在输入端,训练时每次迭代都可能看到“不同版本”的同一张图。
常见做法包括:
- 水平翻转(Horizontal Flip):最基础、收益稳定的增强之一。
- 随机裁剪与尺度缩放(Random crops & scales):
- 训练时:随机采样裁剪区域/缩放比例(让模型对位置与尺度更鲁棒)。以 ResNet 的常见配方为例:先在 里随机选短边长度,将图像短边 resize 到 ,再随机采样一个 的 patch。
- 测试时增强(Test Time Augmentation, TTA):对一组固定裁剪/翻转的预测结果做平均,以减少单次裁剪带来的方差。例如 ResNet:先把图像 resize 到 5 个尺度 {224, 256, 384, 480, 640},每个尺度取 10 个 crop(四角+中心,再加翻转),最后对这些预测求平均。
- 颜色扰动(Color Jitter):最简单的形式是随机改变亮度与对比度(有时也包含饱和度/色相),让模型对光照变化更稳健。
- Cutout(或随机遮挡):训练时将图像中的随机区域置零(或置为常数),迫使模型不要过度依赖局部显著区域;测试时使用完整图像。该方法在 CIFAR 这类小数据集上效果往往更明显,在 ImageNet 等大规模数据集上相对不那么常见。
P3:迁移学习
有时我们并没有大量带标签的数据,这种情况下仅使用少量的数据进行训练是远远不够的。这个时候就需要先使用其他相似的数据集(如ImageNet)进行预训练——虽然相似数据集与小数据集的数据未必相同,但是通过使用大数据集的训练,可以使得神经网络有较强的特征提取和泛化能力(有点期末周刷卷子拟合的感觉了)。

在相似数据集上训练完后,我们得到了一个具有良好特征提取能力的卷积层和全连接层。接下来要在小数据集上进行训练,以此图为例,从一个1000分类问题变成了一个小数据集上的C分类问题。此时前面的层已经有了较好的特征提取性能,使用小数据集训练未必能得到提升,因此只将最后一层FC-1000换成FC-C,然后固定其他层,只用小数据训练最后一层FC-C,就得到了一个C分类的神经网络。当然,如果有较大的数据集,也完全可以直接训练整个网络,提高模型在特定数据集上的表现。

如果本来就有较大的数据集,那么完全可以直接训练所有层或从头开始训练模型;数据集较小的情况下,借助相似的数据集也可以进行迁移学习来得到需要的模型。最坏的情况是数据量小的情况下又没有相似的数据集——这种情况下模型的特征提取能力无法迁移,自然使用迁移学习也是没有意义的,只能收集更多的数据或者更换模型。
P4:超参数选择
Step 1:检查初始 loss 是否合理
随机初始化后先跑少量 iteration,看 loss 数值是否在“合理范围”。例如 softmax 分类在未学习时,loss 常接近 ( 为类别数)。若 loss 极端异常(NaN/inf 或者离谱偏大/偏小),优先检查:数据/标签、损失实现、正则项、初始化、学习率是否过大。
Step 2:在很小样本上过拟合(Overfit a small sample)
取极小子集(比如几十到几百张),关闭或减弱随机增强与正则(dropout / weight decay 等),目标是让训练集准确率接近 100%、loss 明显下降。如果做不到,通常说明模型/代码/优化流程存在 bug,先不要进入大规模调参。
Step 3:找到能让 loss 下降的学习率(Learning Rate, LR)
- 固定“上一步能工作的架构”,使用全部训练数据,使用小的 weight decay(防止完全无约束),尝试一个学习率让 loss 在约 ~100 次迭代内有显著下降。
- 常见可试的数量级:
1e-1, 1e-2, 1e-3, 1e-4, 1e-5。 - 经验信号:
- loss 立刻爆炸/NaN:LR 可能过大(或数值不稳定)。
- loss 几乎不动:LR 可能过小(或正则过强/梯度过小)。
Step 4:粗粒度网格(或随机)搜索超参数,短训 1–5 个 epoch
在已“能下降”的 LR 附近,配合 batch size、weight decay、动量/Adam 参数、模型宽度/深度等做粗搜索。只训练很短时间(约 1–5 epoch)用于快速排序候选配置,避免把算力浪费在明显不行的组合上。
- 当只有少数超参数真正“关键”时,随机搜索往往比网格搜索更高效:随机采样更容易覆盖到关键维度的有效取值。
- 实操中常对 LR、weight decay 用 log 级别采样(例如在 的 log 空间均匀采样),通常比线性步进更合理。

Step 5:缩小范围,细化搜索,并训练更久
选出前几组,缩小搜索区间(例如在 log 空间里更密集采样),把训练 epoch 拉长,比较稳定收敛后的效果。
Step 6:结合 loss/accuracy 曲线诊断问题
只看最终一个点不够,曲线形状能直接提示下一步应该改什么。
- 训练准确率还在上升(Train 还没饱和):通常说明还没训练够,优先“训练更久/调整学习率调度”,再谈其它超参。
- 训练/验证差距巨大(Train 高、Val 低)= 过拟合:增大正则(weight decay、dropout、数据增强)、降低模型容量,或获取更多数据。
- 训练/验证都不高且差距不大(几乎无 gap)= 欠拟合:训练更久、减弱正则、或使用更大的模型。









