深度学习
深度学习的全部魔力可以压缩成三句话:用多层可微函数堆出强大的表示;用反向传播算出每个参数对损失的贡献;用梯度下降(及其改进)更新它们。本文讲透这条主线的每个环节,再按 CNN → RNN → Transformer 的顺序给出结构演进,动手实践见 PyTorch,论文原典见 文献收藏经典论文。
一、神经元与表示
- 单个神经元 =
y = f(w·x + b):线性打分 + 非线性激活; - 没有非线性的多层等于一层:叠 n 个线性层还是线性变换(矩阵乘结合律),非线性是「深度有意义」的前提;
- 激活函数速查:
| 激活 | 公式直觉 | 特点 |
|---|---|---|
| ReLU | max(0,x) | 便宜、梯度不衰减(正区),但有死区(dying ReLU) |
| LeakyReLU | x<0 时给个小斜率 | 缓解死区 |
| GELU | 概率性保留负值 | Transformer 时代默认(近似 x·Φ(x)) |
| Sigmoid/Tanh | 压缩到 (0,1)/(-1,1) | 曾用于隐层,现在多用于门控与概率输出 |
- 初始化的目的:让各层输出的方差在传播中不炸不塌(He 初始化配 ReLU、Xavier 配 tanh),配合归一化一起解决「信号随层数放大/消失」。
二、反向传播:误差如何「怪罪」每一层
- 前向:输入逐层算出损失 L;反向:从 L 出发,用链式法则把「损失对上层输出的偏导」逐层传回——每层的梯度 = 上层传来的梯度 × 本层局部导数;
- 直觉:梯度是每层「该往哪挪」的账单,链式法则是账单的分摊规则;某层梯度为 0,前面所有层都收不到信号(梯度消失);
- 手动算一次两层网络的梯度,比读十篇博客都管用;之后交给 PyTorch 的 autograd 即可;
- 经典数字陷阱:深层 sigmoid 连乘使梯度指数衰减 → 换成 ReLU + 残差(见 ResNet 精读)是治本方案。
三、优化器:梯度下降的三个时代
| 优化器 | 一句话思想 | 适用 |
|---|---|---|
| SGD | 沿梯度反方向走 | baseline;需要手动调学习率 |
| Momentum | 梯度方向被历史「惯性」平滑,冲出平坦区/抖动 | 比 SGD 快而稳 |
| AdaGrad | 每个参数按历史梯度平方自适应缩小步长 | 稀疏特征 |
| RMSProp | 用滑动平均的梯度平方归一化步长 | 非平稳目标 |
| Adam | 一阶动量 + 二阶动量(自适应)组合 | 默认选择,收敛快 |
| AdamW | Adam + 解耦的权重衰减(真正压权重) | 预训练/微调 LLM 的标准 |
- 配套三件套:warmup(前几步学习率从 0 线性爬升,避免大步踩出预训练区域)、学习率衰减/余弦退火(后期小步精修)、梯度裁剪(梯度过大时按范数缩放,防爆炸);
- 调参顺序:先定学习率(最关键,可差一个数量级)——loss 震荡调小,loss 不动调大;再看批大小与它的配比(批大往往配更大学习率)。
四、归一化:每一层的「体重秤」
| 方法 | 对谁做 | 思想 | 常见场景 |
|---|---|---|---|
| BatchNorm | 每个 batch 的每通道 | 把层输入拉回单位方差,允许训练用更大学习率 | CNN |
| LayerNorm | 每个样本的所有特征 | 不依赖 batch、不随批大小变 | Transformer、NLP |
| GroupNorm/RMSNorm | 分组/根的均方归一化 | BN 在小组批失效的替代;RMSNorm 省去均值 | 视觉任务/LLM |
归一化的作用不只是数值稳定,它让网络对「输入尺度」不那么敏感,从而扩大可用的学习率区间——训练能从「找能跑的 lr」变成「找最快的 lr」。
五、CNN:感受野与平移不变性
- 卷积 = 在整张图上滑动共享的小核(kernel):参数共享 + 局部连接让参数从全连接的 O(n²) 降到 O(k²);
- 堆叠小核(3×3)比单个大核更省参数且感受野相同:两层 3×3 感受野 5×5,参数 2×9=18 < 25;
- 结构演进史(详见 ResNet 论文精读):
- LeNet → AlexNet(ReLU/Dropout/GPU,2012 引爆深度学习);
- VGG(统一小核、深);ResNet(残差短路,152 层可训,2015);DenseNet(稠密连接)与 EfficientNet(神经架构搜索出的缩放);
- 现代变体:深度可分离卷积(轻量)、注意力视觉模型(ViT 把图像切成 patch 直接上 Transformer)。
六、RNN 与序列建模
- 朴素 RNN:
h_t = tanh(W x_t + U h_{t-1})——状态沿时间传递,天然处理变长序列; - 致命伤:沿时间连乘的梯度会指数爆炸/消失(长程依赖记不住)→ 门控机制补救;
- LSTM:输入门/遗忘门/输出门 + 细胞状态 c——细胞状态提供「穿过时间的高速公路」(与 ResNet 残差异曲同工);GRU 简化为两个门;
- 局限:串行展开无法并行、难以捕获超长依赖 → 序列建模的主导权 2017 年后移交 Transformer(自注意力一步看全部位置);
- RNN/LSTM 的今日位置:音频流、实时场景仍有用,但文本与大多数序列任务已是 Transformer 的天下。
七、Transformer:深度学习至此归一
- 核心直觉见 Attention Is All You Need 精读:自注意力 = 一次对所有位置做加权聚合的软检索,多头 = 多种关系并行;
- 需要抓住的机制点:
- 缩放点积注意力:Q·Kᵀ 打分 → softmax 加权 V;除以 √d 防点积过大;
- 位置编码:注意力置换不变,须注入位置;从正弦波 → 可学习 → RoPE(旋转位置,兼顾相对位置与外推);
- 层结构:多头注意力 + FFN + 残差 + LayerNorm;decoder 用因果掩码保证只能看过去;
- KV cache:推理时缓存历史 K/V,只算新 token(复杂度从重复算整段降到增量),是生成速度的关键;
- 现代工程版图:FlashAttention(IO 感知注意力,把显存流量降一个数量级)、稀疏/线性注意力(省长序列)、MoE(稀疏专家扩大参数量);
- 若只理解一条主线:深度模型都想解决「如何让信息无损地跨过很远的位置流动」——CNN 靠局部+堆叠,RNN 靠门控状态,Transformer 靠注意力直连 + 残差。
八、训练工程:从「能跑」到「跑得快且稳」
- 批大小:大 batch 梯度稳但泛化常略差、显存大;分布式训练常用大 batch + 线性 lr 缩放 + warmup;
- 混合精度(AMP):fp16 计算 + fp32 主权重(损失缩放),速度近翻倍且显存减半——现代 GPU 默认配置;
- 梯度累积:显存放不下时,多个小 batch 的梯度累加再更新一次(等价大 batch);
- 过拟合防控全套:数据增强 > 早停 > Dropout/权重衰减 > 减模型;先让训练 loss 降下去(能过拟合),再谈泛化(欠拟合时加数据加强模型是无效劳动);
- 复现性三件套:固定 seed、固定数据顺序(或保证 DataLoader 确定)、固定环境版本;分布式下额外注意并发算子对随机性的影响;
- 看曲线的顺序:训练 loss 不降 = 学习率/结构问题;验证 loss 抬升 = 过拟合开始;先修前者再谈后者。
九、踩坑清单
- 忘加归一化/初始化乱来:深层网络训练 loss 纹丝不动,先查激活前后方差是否炸/塌;
- 学习率一拍脑袋:loss 震荡或 NaN → 调小;loss 慢爬不动 → 调大;warmup + 余弦退火是通用解;
- 分类用 MSE:收敛慢且假设错误,分类用交叉熵;
- BN 的批大小魔咒:显存限制 batch 很小时 BN 方差噪声大,换 LayerNorm/GroupNorm;
- 训练不收敛先怀疑实现:梯度检查(数值梯度 vs 反向传播)永远值得做一次;
- 只看训练 loss 判断过拟合:必须盯验证集曲线与泛化差距;
- 序列任务硬塞 RNN:现代默认先试 Transformer/注意力;
- 数据增强过度/错误:增强后人类都认不出的样本会教坏模型,验证集别做增强;
- 复现性不管 seed:论文与团队协作中「换一次结果大变」几乎都是随机性未控制;
- GPU 利用率低就以为在训练:看吞吐与显存,瓶颈常在 DataLoader 与数据搬运。
继续学习:理解网络机制后,动手请走 PyTorch;大模型时代的两大延伸——Transformer 之上的自回归与对齐见 LLM 原理,应用层工程见 AI 工程化。