第三章:深度学习基础回顾(下)——序列、注意力与生成模型

好,咱们接着聊。上一章我们把CNN和基础优化讲透了,这一章我带你看看深度学习里另外几个“狠角色”。说实话,做视觉定位这些年,我越来越觉得光靠单张图像是不够的——你得理解时序,你得学会“看哪里”,甚至还得学会“生成”。这一章,我们就来啃这三块硬骨头。

3.1 循环神经网络(RNN)与序列建模

先问个问题:为什么CNN处理不了视频?因为CNN没有“记忆”。它看每一帧都是独立的,就像金鱼一样——7秒后啥也不记得。但视觉定位里,你连续拍到的图像帧之间是有强关联的。这时候,RNN就派上用场了。

3.1.1 RNN的核心思想:带状态的网络

RNN说白了,就是给网络加了一个“隐状态”h_t。这个状态会随着时间步不断更新:

h_t = tanh(W_h * h_{t-1} + W_x * x_t + b)
y_t = W_y * h_t + b_y

你看,h_t不仅依赖当前输入x_t,还依赖上一时刻的状态h_{t-1}。这就是“记忆”的来源。

关键理解:RNN的本质是在时间轴上共享参数。同一个W_h、W_x,在每个时间步都被重复使用。这大大减少了参数量,但也带来了梯度问题。

3.1.2 我踩过的坑:梯度消失与LSTM

我在2017年做过一个项目,用RNN预测无人车的行驶轨迹。训练了三天,loss死活降不下去。后来一查,梯度早就消失了——早期的信息根本传不到后面。

解决方案?LSTM(长短期记忆网络)。它引入了“门控机制”:

  • 遗忘门:决定丢弃哪些旧信息
  • 输入门:决定存入哪些新信息
  • 输出门:决定输出哪些信息

LSTM的核心是那条“细胞状态”传送带C_t。它像高速公路一样,让梯度可以无损地流过长时间步。

我的建议:现在做序列建模,除非数据量极小,否则优先用GRU(比LSTM少一个门,计算更快)。如果序列特别长(比如1000步以上),直接上Transformer。

3.1.3 双向RNN与深层RNN

有时候,当前时刻的输出不仅依赖过去,还依赖未来。比如在视觉定位中,判断一个场景是室内还是室外,看看后面的帧可能更有把握。这时候就用双向RNN

h_t_forward = RNN_forward(x_t, h_{t-1})
h_t_backward = RNN_backward(x_t, h_{t+1})
h_t = concat(h_t_forward, h_t_backward)

至于深层RNN,就是把多个RNN层堆叠起来。我一般堆2-3层,再深就容易过拟合了。

3.2 注意力机制与Transformer入门

RNN有个硬伤:它必须按顺序处理数据。你想想看,如果句子有100个词,第1个词和第100个词的关系,要经过99次传递才能建立。这效率太低了。

注意力机制的出现,彻底改变了这个局面。

3.2.1 注意力是什么?

注意力机制的核心思想很简单:让模型自己学会“看哪里”。它计算一个加权和,权重表示每个位置的重要性。

公式长这样:

Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V

其中Q是查询,K是键,V是值。说白了,就是拿你的“问题”去和所有“候选答案”做匹配,匹配度高的就给更多权重。

个人体会:我第一次理解这个公式时,觉得它美极了。它把“关注什么”这个抽象概念,变成了一个可微分的数学运算。你想想看,这多优雅。

3.2.2 Transformer:抛弃RNN

2017年那篇“Attention Is All You Need”出来时,我还在用LSTM做机器翻译。读完论文后我沉默了——Transformer完全不用RNN,全靠注意力机制和全连接层,效果却吊打所有序列模型。

Transformer的核心组件:

  • 自注意力(Self-Attention):每个位置都能直接看到所有位置,O(1)路径长度
  • 多头注意力(Multi-Head Attention):让模型从不同子空间学习关联
  • 位置编码(Positional Encoding):因为没有时序结构,得手动告诉模型位置信息
  • 层归一化(Layer Norm) + 残差连接:让深层网络训练更稳定

下面这张图,是我自己总结的Transformer编码器结构,你一看就明白:

Transformer编码器结构(单层) 输入序列 x₁, x₂, ..., xₙ + 位置编码 多头自注意力 (Multi-Head Attention) Q, K, V 均来自同一序列 残差连接 + 层归一化 前馈神经网络 (FFN) 两层全连接 + ReLU 残差连接 + 层归一化 输出到下一层

避坑指南:我曾经在训练Transformer时,发现loss震荡得厉害。后来发现是学习率没配合好。Transformer需要warmup策略——先让学习率从0慢慢升到目标值,再按余弦退火下降。这个细节,很多人会忽略。

3.2.3 视觉Transformer(ViT)

2020年,Google把Transformer用到了图像分类上。做法很简单:把图像切成16x16的patch,每个patch拉平成一个向量,然后当成“词”输入Transformer。

结果?ViT在ImageNet上直接干翻了最好的CNN。我当时就意识到:视觉领域的范式要变了。现在做视觉定位,很多方法都开始用ViT做特征提取,效果确实比ResNet好一截。

3.3 生成模型:GAN与VAE简介

生成模型在视觉定位里有什么用?我举两个例子:

  • 数据增强:用GAN生成不同光照、视角下的训练图像
  • 场景重建:用VAE学习场景的隐空间表示,实现从2D到3D的推断

3.3.1 GAN:生成对抗网络

GAN的思想特别有意思:让两个网络互相博弈。生成器负责“造假”,判别器负责“打假”。两者对抗训练,最终生成器能造出以假乱真的数据。

# 伪代码示意
for epoch in range(epochs):
    # 训练判别器
    real_loss = -log(D(real_data))
    fake_loss = -log(1 - D(G(noise)))
    D_loss = real_loss + fake_loss
    
    # 训练生成器
    G_loss = -log(D(G(noise)))  # 骗过判别器

注意:GAN训练非常不稳定。我做过一个项目,生成器loss一直降,但生成出来的全是噪声。后来发现是判别器太强了,生成器根本骗不过它。解决办法是调整两者的学习率,或者用WGAN(Wasserstein GAN)替换原始GAN。

3.3.2 VAE:变分自编码器

VAE和GAN不同,它走的是概率路线。它把输入编码成一个概率分布(均值+方差),然后从这个分布里采样,再解码还原。

VAE的损失函数有两部分:

  • 重构损失:让输出尽量接近输入
  • KL散度:让学到的分布尽量接近标准正态分布

VAE的好处是:它学到的隐空间是连续的、有结构的。你可以在隐空间里做插值,生成平滑过渡的图像。这在视觉定位中做视角插值特别有用。

3.4 常用深度学习框架对比

说到框架,我用过Caffe、Torch、TensorFlow、PyTorch。现在我的主力是PyTorch,但我也得客观说说各自的优劣。

特性 PyTorch TensorFlow
动态图 原生支持,调试方便 2.0后支持Eager模式,但历史包袱重
部署 TorchScript / ONNX TF Serving / TFLite,生态更成熟
社区 学术界首选,论文代码几乎全是PyTorch 工业界用得多,尤其移动端
调试体验 和Python原生调试一样,爽 以前很痛苦,现在好多了
分布式训练 DistributedDataParallel,好用 MirroredStrategy,功能更全

我的选择:做研究、快速原型,无脑选PyTorch。做产品落地、移动端部署,考虑TensorFlow。但说实话,现在PyTorch的部署生态也在快速追赶,我预测未来PyTorch会一统天下。

3.4.1 一个简单的PyTorch训练模板

import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
class SimpleNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc = nn.Linear(784, 10)
    
    def forward(self, x):
        return self.fc(x.view(x.size(0), -1))

# 训练循环
model = SimpleNet()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

for epoch in range(10):
    for data, target in dataloader:
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

小技巧:我习惯在训练脚本里加上torch.backends.cudnn.benchmark = True。这能让cuDNN自动选择最优卷积算法,训练速度能提升20%-30%。

本章小结

这一章我们覆盖了三个大方向:

  • RNN与序列建模:带记忆的网络,适合处理视频、时序数据。但要注意梯度问题,LSTM/GRU是标配。
  • 注意力机制与Transformer:让模型学会“看哪里”,彻底改变了NLP和CV的格局。ViT已经证明了它在视觉上的潜力。
  • 生成模型:GAN和VAE各有千秋,GAN生成质量高但训练难,VAE隐空间好但生成偏模糊。
  • 框架选择:PyTorch适合研究,TensorFlow适合部署。我建议你两个都了解,但主力用PyTorch。

下一章,我们会把这些基础串起来,看看它们在视觉定位中具体怎么用。嗯,到时候会有很多实战干货,你准备好了吗?


公众号:蓝海资料掘金营,微信deep3321