Skip to content

元数据卡

  • 前置知识:ch09 神经网络基础
  • 预计时间:60 分钟
  • 核心难度:深入
  • 阅读模式:高度专注
  • 完成标志:能理解 CNN、RNN、Attention 和 Transformer 的核心机制

你的进度

全连接网络在模型工坊里跑起来了,能认手写数字了。

但你把一张 256x256 的照片扔进去,参数量直接从几万跳到几百万。训练一天还没收敛。

你意识到:全连接没有利用数据的结构——相邻像素应该共享参数,时序信息应该按顺序处理。模型工坊的最深处藏着两个更先进的引擎:卷积和注意力。

你的任务

深度学习的核心突破来自结构化的网络设计:卷积(CNN)利用空间局部性,循环(RNN)利用时序依赖,注意力(Attention)利用全局相关性。Transformer 将注意力推到极致,成为现代生成式 AI 的基石。

本章分层

  • 必读:卷积操作、自注意力机制、Transformer 架构
  • 选读:LSTM 门控机制、残差连接
  • 进阶:位置编码的数学原理、多头注意力的计算

破局 · 溯源

全连接网络的每个神经元看到的是"整张图"——一个像素和一个角落的像素在参数上同等重要。这在图像上浪费严重:猫的耳朵和眼睛往往在相邻区域出现,你的网络应该利用这种空间结构。

CNN 的方案是让神经元只看到局部窗口(感受野),不同位置的局部窗口共享同一组参数(卷积核/滤波器)。于是"垂直边缘检测器"在图片的任何位置都用同一组权重,参数数量大幅下降。

卷积神经网络

卷积操作:一个小的核(如 3x3)滑过整张图像,在每个位置做逐元素相乘后求和。

python
import torch
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(64 * 7 * 7, 10)  # MNIST: 28x28 -> 池化后 7x7

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))  # 28→14
        x = self.pool(torch.relu(self.conv2(x)))  # 14→7
        x = x.view(x.size(0), -1)
        return self.fc(x)

model = SimpleCNN()
print(f"参数量: {sum(p.numel() for p in model.parameters())}")

跟全连接网络对比:同样处理 28x28 的 MNIST 图像,全连接首层就 784128≈10 万参数,而 CNN 的首卷积层(conv1)只有 13233 + 32 ≈ 320 个参数。

CNN 设计的关键演进:残差连接(ResNet)解决了深层网络退化问题——直接跨层加和让梯度流可以不经过非线性层直接传递到浅层。

循环神经网络

序列数据(文本、音频、时间序列)需要"记忆"——当前输入的意义取决于之前的上下文。RNN 在每个时间步接受一个输入和上一个时间步的隐状态,输出新的隐状态。

python
class SimpleRNN(nn.Module):
    def __init__(self, vocab_size, hidden_dim):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, 128)
        self.rnn = nn.RNN(128, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, vocab_size)

    def forward(self, x, hidden=None):
        x = self.embedding(x)
        output, hidden = self.rnn(x, hidden)
        return self.fc(output), hidden

RNN 的问题:随着时间的推移,梯度需要在时间维度上反向传播(BPTT),链式法则导致梯度指数级消失或爆炸。LSTM(长短期记忆网络)通过三个门(输入门、遗忘门、输出门)和一个独立记忆单元缓解了这个问题。

注意力机制

注意力(Attention)让模型在处理序列时选择性地关注不同位置。RNN 只能按顺序"读"序列——注意力允许模型在计算当前位置时"回头看"任何位置。

python
# Scaled Dot-Product Attention
import torch.nn.functional as F

def attention(query, key, value, mask=None):
    """注意力计算:Q*K^T / sqrt(d_k) -> softmax -> *V"""
    d_k = query.size(-1)
    scores = query @ key.transpose(-2, -1) / (d_k ** 0.5)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, float('-inf'))
    weights = F.softmax(scores, dim=-1)
    return weights @ value

核心公式:Attention(Q,K,V) = softmax(QK^T / sqrt(d_k)) * V

  • Q(Query):当前位置的查询向量,想知道"我应该关注什么"
  • K(Key):每个位置的键向量,告诉 Q"我这里有这个信息"
  • V(Value):每个位置的实际信息

点积注意力衡量 Q 和 K 的相似度,加权求和得到最终的上下文向量。

Transformer

Transformer = 去掉 RNN,全部用注意力。2017 年《Attention Is All You Need》提出的架构让整个 NLP 领域重写。

python
class TransformerBlock(nn.Module):
    def __init__(self, d_model, n_heads, d_ff, dropout=0.1):
        super().__init__()
        self.attention = nn.MultiheadAttention(d_model, n_heads, dropout)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Linear(d_ff, d_model),
            nn.Dropout(dropout)
        )

    def forward(self, x, mask=None):
        # 多头自注意力 + 残差连接 + 层归一化
        attn_out, _ = self.attention(x, x, x, attn_mask=mask)
        x = self.norm1(x + attn_out)
        # 前馈网络 + 残差连接
        ffn_out = self.ffn(x)
        x = self.norm2(x + ffn_out)
        return x

Transformer 相对于 RNN 带来的改变:

  • 并行计算:RNN 必须按时间步串行。Transformer 并行处理整个序列,训练快了数百倍。
  • 长距离依赖:RNN 对长序列的记忆随距离衰减。Transformer 的注意力直接连接任意两个位置。
  • 多头:N 个头并行计算 N 组注意力,每头关注不同类型的相关性(语法、语义、指代等)。

Transformer 的代价:自注意力的时间复杂度是 O(n^2),其中 n 是序列长度。长文本(如整本书)需要稀疏注意力或近似方法。

常见陷阱

  • CNN 的感受野只能通过层层堆叠增大——单个 3x3 卷积的感受野是 3x3,两层堆叠后等效 5x5,堆叠 N 层等效 (2N+1)x(2N+1)。
  • RNN 的梯度爆炸:梯度裁剪(gradient clipping)是标准处理方法。梯度消失:换 LSTM 或 Transformer。
  • 自注意力中没有位置信息——原始 Transformer 用正弦-余弦位置编码注入位置信息,BERT 用可学习的绝对位置嵌入,GPT-2 用可学习位置嵌入。
  • LayerNorm 与 BatchNorm 的区别:LayerNorm 对每个样本的两个维度归一化,适合 NLP(序列长度变化大);BatchNorm 对每个特征维度跨样本归一化,适合 CV(批量大小稳定)。
  • Dropout 只在训练时开启,推理时关闭——PyTorch 的 nn.Dropout 会自动处理这一点(model.train() vs model.eval())。

通关挑战

  • 热身(10 分钟):在 MNIST 上训练 SimpleCNN,分别将卷积核大小设为 1、3、5、7,观察参数数量和准确率的变化趋势。
  • 挑战(45 分钟):用 PyTorch 实现一个简化版 Transformer(2 层 encoder,d_model=128,n_heads=4),在 IMDB 情感分类任务上训练。对比使用 RNN 和 Transformer 的收敛速度。
  • 观察:打印一个句子的注意力权重矩阵(8 个词,8x8 矩阵),观察每个词对哪些词有高注意力——"it"通常对"the cat"有高权重。

旅人笔记

CNN 把图像的结构性(局部性、平移不变性)编码到网络架构中。Transformer 把注意力推到极致,去掉了序列性假设,让并行训练成为可能。在这之上,现代生成式 AI 开始发力。

-> 下一站预告

Transformer 让大规模预训练成为可能——从 BERT 到 GPT,从 Tokenization 到 Prompt Engineering。下一章进入现代生成式 AI 的世界。

Built with VitePress | Software Systems Atlas