1. 概述

本文将带你深入了解 Transformer 模型的内部结构,特别是它是如何表示文本的。接着我们还会介绍一个非常流行的衍生模型 BERT,并讲解如何使用它来获取更丰富的文本向量表示。

要理解以下内容,你需要具备一定的深度学习和循环神经网络(RNN)的基础知识。

让我们开始吧!

2. 什么是 Transformer?

Transformer 是一种基于编码器-解码器结构的大规模模型,能够通过一种复杂的注意力机制处理整个序列。

在 Transformer 出现之前,最先进的结构是使用 LSTM 或 GRU 的循环神经网络(RNN)。这些结构存在以下问题:

  • 难以处理非常长的序列(尽管使用了 LSTM 和 GRU)
  • 训练效率低,因为它们的顺序处理方式无法并行化

而 Transformer 的工作方式完全不同:

  • 它可以处理整个序列,从而更好地捕捉长距离依赖关系
  • 部分结构可以并行处理,使得训练速度大幅提升

Transformer 最早出现在论文 Attention Is All You Need 中,这个名字来源于它提出的新注意力机制。

3. Transformer 内部结构解析

3.1 整体架构

假设我们要将 “My tailor is rich” 从英文翻译成西班牙语。Transformer 的整体结构如下:

architecture overall

正如你所见,它是一个典型的编码器-解码器结构。输入序列首先经过一个编码器块,生成每个 token 的丰富嵌入,然后这些嵌入被传入解码器块生成输出。

结构可以简化为:

architecture 2 blocks

每个编码器/解码器块内部其实是由多个相同的子模块堆叠而成。这样设计的好处是:

  • 浅层捕捉更基础的模式
  • 深层能识别更复杂的语义关系,类似于卷积网络

如下图所示,最后一个编码器的输出会被所有解码器使用:

architecture blocks inside

3.2 输入处理

编码器不能直接处理原始文本,需要先将文本转换为向量。

处理流程如下:

  1. 将文本切分为 token,这些 token 来自一个固定的词汇表
  2. 使用预训练的词向量模型(如 word2vec)将每个 token 转换为向量

由于 Transformer 是一次性处理整个序列,如何表示 token 的位置信息?

解决方案是:在每个 token 的 embedding 上加上位置编码(positional encoding)向量,这样每个 token 的向量就包含了位置信息。

input

这些向量就可以输入到编码器中了。

3.3 编码器栈

编码器接收一个 token 序列的向量表示:

并返回一个同样长度的输出向量序列:

可以理解为:编码器把每个 token 的输入向量“增强”为包含更丰富信息的输出向量。

简化结构如下图:

encoder overall

接下来我们打开这个黑盒,看看里面到底做了什么。

自注意力机制(Self-Attention)

这是编码器中最核心的部分,能捕捉序列中任意两个 token 之间的关系,无论它们相隔多远。

举个例子:“The cat is on the mat. It ate a lot of food.” 中的 “It” 应该指向 “cat” 而不是 “mat”。注意力机制会在这一步赋予 “cat” 更高的权重。

这部分是顺序处理的,因为注意力机制需要整个序列。

encoder 1 cropped

Add & Normalize

将自注意力的输出与输入相加,并做归一化处理。这一步也是顺序处理的,因为归一化需要整个序列的信息。

encoder 2 cropped

前馈网络(Feed Forward)

每个 token 独立通过一个全连接神经网络,这部分可以并行处理

encoder 3 cropped

再次 Add & Normalize

将前馈网络的输出与输入相加,并再次归一化。

encoder 5 cropped

整个编码器内部的顺序处理(灰色)和并行处理(橙色)分布如下:

processing encoder cropped 1

编码器栈的每一层都会输出一个更新后的 token 序列:

最后一层编码器的输出将作为整个编码器栈的输出。

整个过程的动态演示如下:

encoder architecture

3.4 解码器栈

解码器结构与编码器类似,但多了一个编码器-解码器注意力层(Encoder-Decoder Attention)

每个解码器的输入包括:

  • 已生成的序列
  • 编码器的输出

简化结构如下:

decoder black box

自注意力机制

与编码器的自注意力不同,解码器的自注意力只能看到已生成的部分序列:

这部分是顺序处理的。

decoder step 1 cropped

Add & Normalize

和编码器一样,这部分也是顺序处理的。

编码器-解码器注意力层

这个注意力机制用于识别当前输出 token 对应的输入序列中哪些 token 更重要

这部分也是顺序处理的。

decoder step 3 cropped

前馈网络 + Add & Normalize

这部分可以并行处理。

decoder step 5 cropped 1

整个解码器的处理流程中,大部分是顺序处理(灰色),仅一层可并行(橙色):

processing decoder cropped

每个解码器的输入是:

输出是:

这个输出会传给下一个解码器。最后一层解码器连接输出层,生成下一个 token。

这个过程会一直持续,直到生成一个特殊的“句尾”标记(EOS)

整个流程的动态演示如下:

decoder architecture

3.5 输出处理

解码器输出的是当前已生成 token 的增强表示,下一步是如何生成下一个 token。

具体流程如下:

  1. 解码器输出一个 float 向量
  2. 通过一个全连接层(线性层)将其映射为一个词汇表大小的向量(logits)
  3. 通过 softmax 转换为概率分布
  4. 选择概率最高的 token 作为下一个输出

整个流程如下图所示:

output 1

4. BERT 简介

4.1 模型介绍

BERT 是一个预训练的 Transformer 编码器栈

它是 NLP 领域的一项重大突破,因为它只需少量微调即可适应各种具体任务

类似于图像识别中使用预训练模型(如 ResNet),BERT 通过大规模语料训练已经学习了大量基础语言特征,我们可以在此基础上进行微调,完成各种下游任务。

例如,我们可以在 BERT 的输出上加几层全连接层,构建一个分类器。虽然需要适应不同的词汇、语法等,但基础语义理解已经由 BERT 提供。

4.2 BERT 的运行方式

BERT 的输入需要满足以下条件:

  • 使用两个特殊 token:[CLS][SEP]
  • 输入长度固定(通常为 512)

输入格式如下:

  • 开头必须是 [CLS](表示分类)
  • 结尾必须是 [SEP](表示分隔符)

如果输入序列长度不足,其余位置用 padding 填充,并通过 attention mask 标记有效 token。

如下图所示:

bert

4.3 文本嵌入方式

如果需要获取每个 token 的向量表示,可以直接使用 BERT 编码器输出的对应向量(图中的 “y” 向量)。

如果需要整个句子的向量表示,有三种常用策略:

使用 [CLS] 的输出向量(最常用)
对所有 token 向量做平均池化(mean pooling)
对所有 token 向量做最大池化(max pooling)

一些论文指出 后两种方式在某些任务中效果更好,但默认推荐使用 [CLS] 向量。

5. 总结

本文我们学习了:

  • Transformer 的基本结构及其优势
  • 自注意力机制如何提升模型对长距离依赖的捕捉能力
  • BERT 的基本原理及其作为预训练模型的优势
  • 如何使用 BERT 获取文本的嵌入向量

Transformer 的出现彻底改变了 NLP 领域,BERT 等模型的广泛应用也证明了其强大的表达能力。掌握其原理,有助于我们更好地进行模型调优和应用开发。


原始标题:Transformer Text Embeddings