第 12 课
← 返回系列列表

Course 5:自然语言处理与注意力机制

Deep Learning Specialization — 深度学习专项课程

Word Embeddings、Seq2Seq、Attention、Transformer 简介。

Course 5:自然语言处理与注意力机制

课程简介

Word Embeddings、Seq2Seq、Attention、Transformer 简介。

🎬 本课程视频:Deep Learning Specialization — 深度学习专项课程


一、词嵌入(Word Embeddings)

1.1 词表示的困境

传统 one-hot 编码将每个词表示为一个 V 维向量(V 为词汇表大小),只有一个位置为 1,其余为 0。问题:任意两个词的 one-hot 向量的内积为 0,完全无法表达词之间的语义相似性。

1.2 特征化表示

词嵌入将每个词映射到低维连续向量空间(通常 50-300 维),使语义相近的词在向量空间中距离相近。

例如:"猫"和"狗"的嵌入向量应该比"猫"和"桌子"更接近。"国王" - "男人" + "女人" ≈ "女王"——这个经典的类比推理展示了词嵌入的语义捕获能力。

1.3 Word2Vec

Word2Vec 有两种架构:
- Skip-Gram:给定中心词,预测上下文词
- CBOW:给定上下文词,预测中心词

Skip-Gram 使用 softmax 输出层,计算每个上下文词的概率:
$$P(c|t) = \frac{e^{\theta_c^T e_t}}{\sum_{c'} e^{\theta_{c'}^T e_t}}$$

其中 e_t 是中心词 t 的嵌入向量,theta_c 是上下文词 c 的输出向量。

词汇表 V 很大时 softmax 的计算成本极高。优化方法:
- 负采样:将多分类问题转化为二分类问题(区分真实配对和随机噪声配对)
- 层次 Softmax:使用 Huffman 树结构加速计算

1.4 GloVe

GloVe 基于词共现矩阵。核心思想是词的语义可以通过它们共同出现的统计规律来捕获。GloVe 的损失函数最小化词向量内积与共现概率对数的差异。

1.5 嵌入矩阵

词嵌入可以组织为嵌入矩阵 E ∈ R^{V×d}。每个词 w 的嵌入 = E[w](查表操作)。

# Keras 嵌入层
embedding_layer = layers.Embedding(
    input_dim=vocab_size,  # 词汇表大小
    output_dim=128,        # 嵌入维度
    weights=[pretrained_embeddings],  # 可加载预训练词向量
    trainable=True         # 是否微调
)

二、Seq2Seq 模型

2.1 编码器-解码器架构

Seq2Seq 模型将一个序列映射到另一个序列,广泛应用于机器翻译、文本摘要、对话系统。

编码器:使用 RNN/LSTM 将输入序列编码为固定长度的上下文向量 C。
解码器:使用另一个 RNN/LSTM 从 C 开始逐步生成输出序列。

训练阶段使用 Teacher Forcing:解码器在时间步 t 的输入是上一个时间步的真实输出(而非模型自己的预测),加速收敛。

2.2 瓶颈问题

固定长度的上下文向量成为性能瓶颈——长序列的信息无法全部压缩到一个向量中。Attention 机制解决了这个问题。

三、注意力机制

3.1 核心思想

Attention 机制让解码器在生成每个输出词时,能够"关注"输入序列中与之最相关的部分,而非依赖固定的上下文向量。

3.2 计算过程

在每个解码时间步 t:
1. 计算解码器当前隐藏状态 s_t 与每个编码器隐藏状态 h_i 的注意力分数
2. 分数通过 softmax 归一化得到注意力权重
3. 计算上下文向量 c_t = 加权求和所有 h_i

$$ ext{score}(s_t, h_i) = s_t^T W_a h_i$$
$$lpha_{ti} = \frac{\exp(\text{score}(s_t, h_i))}{\sum_j \exp(\text{score}(s_t, h_j))}$$
$$c_t = \sum_i \alpha_{ti} h_i$$

常见的注意力分数计算方式:
- 加性注意力(Bahdanau):score = v_a^T tanh(W_a [s_t; h_i])
- 乘性注意力(Luong):score = s_t^T W_a h_i

3.3 注意力可视化

注意力权重可以通过热力图可视化,展示翻译过程中源词和目标词的对齐关系——这正是"注意力"这个名字的来源。

四、Transformer

4.1 摆脱 RNN

Transformer 完全抛弃 RNN 的循环结构,仅基于自注意力(Self-Attention)机制处理序列。它标志着现代 NLP 时代的开始。

4.2 自注意力(Self-Attention)

对于输入序列 X = {x_1, ..., x_T},自注意力计算每个元素与序列中所有元素的关联:

$$Q = XW_Q, \quad K = XW_K, \quad V = XW_V$$
$$ ext{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$

缩放因子 1/sqrt(d_k) 防止 softmax 输入过大导致梯度极其微小。

自注意力的优势:任意两个位置的交互只需要一步矩阵乘法(O(1) 路径长度),而 RNN 需要 O(序列长度) 步。

4.3 多头注意力

将 Q、K、V 投影到多个子空间,并行计算自注意力,然后拼接结果:

$$ ext{MultiHead}(Q,K,V) = \text{Concat}(head_1, ..., head_h)W_O$$
$$\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$$

每个 head 可以关注序列中不同类型的依赖关系(如语法依赖、语义依赖)。

4.4 位置编码

由于 Transformer 没有循环结构,它不知道词的顺序。需要显式添加位置信息:

$$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$
$$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$

正弦函数的性质允许模型轻松学习到相对位置关系。

4.5 Transformer 编码器

编码器由 N 个相同的层堆叠组成。每层包含:
1. 多头自注意力
2. 前馈神经网络(两层 MLP,中间使用 ReLU)
3. 残差连接 + Layer Normalization

4.6 Transformer 解码器

解码器在编码器的结构上增加了掩码自注意力和编码器-解码器注意力:
- 掩码自注意力:确保解码器只能看到已生成的词,不能"偷看"未来的词
- 编码器-解码器注意力:让解码器关注输入序列的相关部分

class MultiHeadSelfAttention(layers.Layer):
    def __init__(self, d_model, num_heads):
        super().__init__()
        self.num_heads = num_heads
        self.d_model = d_model
        self.depth = d_model // num_heads
        self.wq = layers.Dense(d_model)
        self.wk = layers.Dense(d_model)
        self.wv = layers.Dense(d_model)
        self.dense = layers.Dense(d_model)

    def call(self, x, mask=None):
        batch_size = tf.shape(x)[0]
        Q = self.wq(x)
        K = self.wk(x)
        V = self.wv(x)
        # 分割多头
        Q = tf.reshape(Q, (batch_size, -1, self.num_heads, self.depth))
        Q = tf.transpose(Q, perm=[0, 2, 1, 3])
        # 计算注意力分数
        scores = tf.matmul(Q, K, transpose_b=True) / tf.sqrt(tf.cast(self.depth, tf.float32))
        if mask is not None:
            scores += (mask * -1e9)
        attention = tf.nn.softmax(scores, axis=-1)
        output = tf.matmul(attention, V)
        output = tf.transpose(output, perm=[0, 2, 1, 3])
        output = tf.reshape(output, (batch_size, -1, self.d_model))
        return self.dense(output)

五、BERT——大规模预训练

BERT 使用 Transformer 编码器进行大规模预训练,然后在特定任务上微调。预训练任务:
1. 掩码语言模型(MLM):随机掩盖 15% 的词,预测被掩盖的词
2. 下一句预测(NSP):判断两句话是否连续

延伸阅读

← Course 5:循环神经网络基础 Course 5:语音识别与生成 →