第一篇章:CNN 的基础构建单元(Layers & Initialization)
这一部分回答"怎么搭建网络骨架"。
1. 归一化层(Normalization Layers):让数据"稳定发力"
-
💡 核心逻辑公式:无论哪种归一化,都遵循两步操作:
-
标准化 :
(将数据拉到均值为 0,方差为 1 的标准正态分布)。
-
缩放与平移 :
(
是缩放因子,
是偏移量。注意:这两个参数是模型通过梯度下降自动学习的)。
-
-
不同归一化层的根本区别(谁来当分母?) :
想象数据是一个 4D 张量:
[N(样本数), C(通道数), H(高度), W(宽度)]。-
Batch Norm (BN) :跨样本(N) 算统计量。(CNN 常用,但要求 Batch Size 够大,比如 32 以上。如果只有 2 张图,算出来的均值毫无意义)。
-
Layer Norm (LN) :跨通道(C) 算统计量。(Transformer 和 NLP 任务常用,不依赖 Batch 大小,适合变长序列)。
-
Instance Norm (IN) :仅在自己身上(H,W) 算统计量。(主要用于图像风格迁移)。
-
Group Norm (GN) :将通道 C 分成几组,在组内算 。它是 BN 的完美替代者(当显存不够,Batch Size 设得很小比如为 2 时,用 GN 效果极佳,不会崩坏)。
-
2. 权重初始化(Weight Initialization):为什么不能全设 0?
如果你把全连接层的权重 W 初始化为 0,那么每一层的输出都是一样的,梯度更新时所有神经元也是同步更新,网络无法"多样化"学习。所以必须使用随机初始化。
-
❌ 错误案例 1:权重初始化太小(如标准差为 0.01)
-
现象:经过 ReLU 激活后,随着层数加深,激活值全部坍缩到 0 附近。
-
后果:梯度消失。网络后面的层根本收不到有效信息,无法更新。
-
-
❌ 错误案例 2:权重初始化太大(如标准差为 0.05)
-
现象:经过 ReLU 激活后,数值逐层变大,到第 6 层时均值变成了 109 ,出现了 NaN(数值爆炸)。
-
后果:梯度爆炸。网络无法收敛。
-
-
✅ 正确做法:Kaiming He 初始化(专为 ReLU 设计)
-
不要用固定常数,应该根据输入神经元的数量动态决定随机分布的大小。
-
公式 :
W = np.random.randn(D_in, D_out) * np.sqrt(2.0 / D_in)。这里的sqrt(2.0/D_in)保证了经过 ReLU 后,每一层输出的方差大致相等,不会放大也不会消失。
-
3. 激活函数(Activation Functions):引入非线性
-
ReLU (Rectified Linear Unit) :
max(0, x)。最大的问题是,小于 0 时梯度为 0,会造成部分神经元永久"死亡" (不会再被激活)。因此后来有了 Leaky ReLU(小于 0 时乘以一个很小的系数如 0.01)进行缓解。 -
GELU (Gaussian Error Linear Unit) :✨ Transformer 的标配。它结合了 ReLU 和 Dropout 的思想,在 0 附近有非常平滑的梯度,没有"死神经元"的困扰,模型表现更稳。
第二篇章:经典 CNN 架构演进(Architectures)
这部分回答"主流模型到底长什么样"。
1. VGGNet:用"小滤子"堆叠出"大视野"(2014)
-
核心绝招 :放弃了 AlexNet 的大卷积核,全部使用 3×33×3 卷积(步长 1,边缘补 1) + 2×22×2 最大池化(步长 2)。
-
💡【初学者的必考点:感受野实战计算】
-
问:为什么堆叠 3 个 3×33×3 卷积,等价于 1 个 7×77×7 卷积的感受野?
-
图解推导:
text
第一层 3x3 感受野: 3x3 第二层 3x3 感受野:(3-1)*1 + 3 = 5x5 第三层 3x3 感受野:(5-1)*1 + 3 = 7x7 -
算力优势:假设输入输出通道都是 C。
-
1 个 7×7 卷积核的参数量 = 7×7×C×C=49
-
堆叠 3 个 3×33×3 卷积核的参数量 = 3×(3×3×C×C)=27
-
-
结论 :用了 3 个小卷积核,不仅感受野一样大,参数量还节省了将近一半,并且多了 3 次非线性激活,表达能力更强!
-
2. ResNet(残差网络):让网络可以"无限深"(2015)
-
痛点 :以前大家以为网络越深越好,但发现 20 层的效果比 56 层还好。原因不是过拟合,而是深层网络太难优化了,梯度传不到前面去。
-
💡 天才解法:残差连接(Skip Connection)
-
传统网络:y=Conv(x),必须强行从零学会从原始图到高级特征的全部变换。
-
残差网络 :y=Conv(x)+x。网络不需要学会"全部答案" ,只需要学会"答案 - 输入 = 残差"。
-
为什么有效? 假如已经训练得很好了,我们再多加几层。如果这些新加的层没什么用,它只要把权重都学习成 0,那么 Conv(x)=0,最终输出依然是 0+x=x。有了这条捷径,梯度在反向传播时可以直接原封不动地传回浅层,彻底解决了梯度消失问题!
-
-
ResNet 工程细节:
-
每隔几个残差块,会将 通道数翻倍 ,同时用 步长为 2 的卷积将图片长宽减半(参数量和计算量保持平衡)。
-
结构上,在残差块之前,先做一次 7×7 的大卷积(类似"粗加工")。
-
第三篇章:如何训练出高泛化能力的 CNN(Training Tricks)
这部分回答"怎么让模型在没见过的测试集上表现更好"。
1. 数据增强(Data Augmentation):凭空造出更多数据
-
核心目的:给原始图片施加随机变换,让模型"看"到多样化的样本,防止死记硬背,提升泛化性(注意:训练 Loss 会变高,但测试 Loss 会变低)。
-
常用手段:
-
水平翻转(适合物体识别,不适合 OCR 文字识别)。
-
随机裁剪与缩放(让模型不依赖物体在画面中的绝对位置)。
-
颜色抖动(改变亮度、饱和度、对比度)。
-
随机遮挡(随机在图片上用黑块遮挡,让模型学会看局部的特征)。
-
-
✨ 高级技巧:测试时增强(TTA)
-
在测试 阶段,把一张图裁剪成 5 种(四周+中间)或者翻转等多种变化,输入模型得出多个预测,最后把所有预测结果取平均。
-
通常能在准确率上提升 1%~2%。
-
2. 正则化 Dropout:强迫模型不要"死记硬背"
-
做法:在训练的前向传播中,随机把神经元(比如 50%)直接置为 0。
-
背后的用意 :强制网络不能依赖特定的某条通路,必须学会冗余特征,这就好比你想考出好成绩,不能只押某一题的答案,必须全面复习。
-
⚠️【初学者的易错点:训练和测试的缩放机制】
-
训练时:使用了 Mask。假设 p=0.5,那么输出只有一半。
-
测试时 :绝对不能丢弃神经元 !因为不丢弃,所有神经元都激活,输出值就是训练时的 2 倍。为了解决这个问题,测试时必须把输出乘以概率 p(即乘以 0.5),这样才能保证测试和训练时的数值幅度一致。
-
(注:现在流行的实现叫"Inverted Dropout",是在训练时除以 p,这样测试时代码完全不用改动,更方便)。
-
3. 迁移学习(Transfer Learning):站在巨人的肩膀上
如果你没有几十万张图片,不要自己从头训练大模型!直接拿别人训练好的 ImageNet 预训练模型。
-
情形 A(小数据集,且图片风格类似 ImageNet):
- 做法 :冻结 前面的所有卷积层(当作特征提取器),只把最后的全连接层(原本是 1000 类)换成你自己任务的类别数(比如 2 类),只训练这最后一层。非常适合少样本学习。
-
情形 B(大数据集,且图片风格类似 ImageNet):
- 做法 :用预训练权重做初始化,替换最后一层,然后解除所有层的冻结,对整个网络进行微调(Fine-tuning),这样能获得最佳性能。
-
情形 C(如果图片风格差异极大,比如医学图像):
- 做法 :建议多解冻早期的几层,或者从零训练部分新加入的层。
🧠 总结图表
| 课程模块 | 核心知识点 | 一句话总结 |
|---|---|---|
| 归一化 | BN/LN/IN/GN | 统计量算错维度,结果大不同(BN 看样本,LN 看通道) |
| 激活函数 | ReLU / GELU | 解决梯度死寂,GELU 是 Transformer 的王牌 |
| 权重初始化 | Kaiming He | 初始值要配输入层数,不能太小也不能太炸 |
| VGG架构 | 3x3 堆叠代替 7x7 | 感受野不变,参数少一半,非线性更强 |
| ResNet架构 | 残差连接(Skip) | 允许梯度直通,网络再深也不怕梯度消失 |
| Dropout | 训练丢弃,测试缩放 | 强制网络学冗余特征,防止死记硬背 |
| 迁移学习 | 冻结 + 微调 | 小数据靠预训练,大数据才全量微调 |