Skip to content

MIT深度学习课程第七讲:Transformer Encoder 与 Self-Attention

本节课进入 transformer

老师先说明,transformer 最初是为 machine translation 设计的,例如:

  • English 到 German
  • German 到 French
  • 其他语言之间的翻译

但它后来被证明是一种非常有效的深度神经网络架构,适用范围远远超过翻译任务

现在,很多问题一旦进入建模阶段,往往会优先尝试 transformer,因为它在大量任务上都能取得很强的效果。

一、Transformer 的应用范围

老师列举了 transformer 已经产生重要影响的方向:

  • machine translation
  • Google Search
  • information retrieval
  • speech recognition
  • text-to-speech
  • computer vision
  • reinforcement learning
  • generative AI
  • large language models
  • multimodal models
  • 特定领域系统,例如 AlphaFold

其中,AlphaFold 这类 protein-folding AI 也运行在 transformer stack 上。

老师强调,transformer 是一种非常灵活的架构,不只是自然语言处理中的单一模型。

二、用信息检索作为动机案例

本节课使用 search,更广义地说是 information retrieval,作为引入 transformer 的动机。

这类任务中,用户可能输入或说出自然语言查询,系统需要准确理解用户想要什么。

老师给出的例子包括:

text
Find me all flights from Boston to LaGuardia tomorrow morning.

也可以更具体:

text
Tell me all the flights that are leaving from Boston and going to LaGuardia tomorrow morning between 8:00 and 9:00.

这类问题不同于开放式生成任务,例如:

text
Write me a limerick about deep learning.

开放式生成可能有很多合理答案,但航班查询、合同检索、客户行为分析等任务通常要求很高的准确性。

老师还列举了其他类似查询:

  • how many customers abandon their shopping cart
  • find all contracts that are up for renewal next month
  • tell me all customers who ended a call center call yesterday and were not pleased with the transaction

本节课主要聚焦 travel-related query。

三、自然语言查询到结构化查询

历史上,这类系统常见的处理流程是:

  1. 接收 natural language query。
  2. 解析查询文本。
  3. 抽取关键实体。
  4. 把抽取出的实体重新组装成 structured query。
  5. 用 structured query 查询数据库。
  6. 格式化查询结果并返回给用户。

这里的 structured query 可以是 SQL,也可以是其他结构化查询形式。

老师使用 SQL 作为例子,是因为它更容易被理解。

对于航班查询:

text
Find me all flights from Boston to LaGuardia tomorrow morning.

系统需要自动抽取出与 travel 相关的实体,例如:

  • BOS
  • LGA
  • tomorrow morning
  • flights

问题的核心变成:

text
如何从自然语言查询中自动抽取 travel-related entities?

四、ATIS 数据集与 Slot Filling

本节使用的数据集是:

text
Airline Travel Information Systems Data Set

通常简称为:

text
ATIS

这个数据集中包含数千条旅行查询。研究人员已经人工检查每一条查询,并给查询中的每个词标注它属于哪一种 travel entity,或者标注为不关心的类别。

这些被标注的 entity 类别称为:

text
slots

因此,这个任务也可以称为:

text
slot filling

五、Slot 标注示例

老师用下面这类句子说明标注方式:

text
I want to fly from Boston at 7:00 AM and arrive at 11 in the morning.

其中:

  • I
  • want
  • to
  • fly
  • from

这些词本身不对应需要抽取的具体 travel entity,因此标注为:

text
O

O 表示:

text
other

也就是当前任务中不关心的类别。

当句子中出现:

text
Boston

它在这个上下文中表示出发城市,因此会被标注为:

text
B-fromloc.city_name

其中:

  • fromloc 表示 departure location。
  • city_name 表示城市名。
  • B 表示这个实体从当前 token 开始。

对于:

text
7:00 AM

它由两个 token 组成,共同表示 departure time。

因此会使用 BI 的标注方式:

  • 7:00 是 departure time 的开始,标为 B-...
  • AM 是同一个实体的一部分,标为 I-...

这里:

  • B 表示 Beginning
  • I 表示 Intermediate 或 inside/in the middle

对于后面的到达时间:

  • 11 可以标为 B-arrive_time
  • morning 可以标为 arrive_time.period

这个例子说明,slot filling 的本质是:

text
给句子中的每个 token 分配一个与任务相关的标签。

六、123 种 Slot 类型

在本节课的设置中,每个词会被分类到 123 种可能标签之一。

这些标签覆盖多种旅行相关信息,例如:

  • aircraft code
  • airline code
  • airline name
  • airport code
  • airport name
  • arrival date
  • relative date
  • round trip / one way
  • 与 today 相关的相对时间

老师特别指出,像 tomorrow morning 这样的表达是相对于 today 的,因此系统不仅需要处理绝对时间,也要处理相对时间。

七、课堂问答:Boston 的上下文标签

有学生问:

text
如果句子里出现 from Boston,标注时是否需要结合 from Boston 的上下文?

老师回答:

因为数据集是人工标注的,人类标注者会阅读完整句子,然后判断 Boston 在当前句子中是 departure city 还是 arrival city。

在:

text
from Boston

这个具体上下文中,Boston 会被标为 departure city。

但在另一条查询中,如果用户说的是飞往 Boston,那么 Boston 会得到不同的标签。

八、课堂问答:Compound Query

有学生问,如果查询是复合形式,例如:

text
give me flights from Boston at 7:00 AM and flights from Denver at 11:00 AM

模型是否处理这种 compound query。

老师回答,本节使用的数据集和示例主要关注 single query,因为大多数用户会提出类似:

  • give me a flight from here to there
  • what is the cheapest flight from here to there

这样的单个查询。

九、任务形式:Word-to-Slot Multi-Class Classification

这个问题可以表述为:

text
word-to-slot multi-class classification

也就是:

text
每个输入 token 都要被分类到一个 slot label。

老师强调,这不是把整条 query 分类到 123 个类别之一。

相反,是查询中的每个词都要独立得到一个标签,但这个标签又必须依赖上下文。

在课堂示例中,输入句子包含 18 个词,因此模型输出也需要包含 18 个位置:

text
18 in, 18 out

每个输出位置上都接一个:

text
123-way softmax

也就是说,18 个输出 token 中,每一个都需要在 123 个 slot 类型中选择一个。

十、这个任务对模型提出的三个要求

老师总结,slot filling 对模型有三个关键要求

第一,输出长度必须与输入长度相同

text
same cardinality

如果输入有 18 个 token,输出也应有 18 个 token。

第二,模型必须支持可变长度输入

现实查询可能很短,也可能很长。模型需要处理这种长度变化,但每条输入内部仍然要求输出与输入等长。

第三,模型必须同时考虑:

  • surrounding context
  • word order

原因是:

text
from Boston to LaGuardia

和:

text
from LaGuardia to Boston

含义完全不同。

十一、为什么 Context Matters

老师回顾上一节课中 standalone embeddings 的局限。

例如 GloVe 这类 standalone / uncontextual embedding,会给每个词一个固定向量。

如果一个词有多个含义,这个固定向量会变成多个含义的某种平均。

老师用几个例子说明同一个词在不同上下文中的含义差异。

see

text
I will see you soon.
I will see this project to its end.
I see what you mean.

bank

text
I went to the bank to apply for a loan.
I'm banking on the job.
I'm standing on the left bank.

it

text
The animal didn't cross the street because it was too tired.
The animal didn't cross the street because it was too wide.

第一句中的 it 指代 animal。

第二句中的 it 指代 street。

station

text
radio station
train station
being stationed somewhere
the International Space Station

这些例子说明,单个词的含义不能只由词本身决定,必须结合上下文。

十二、Transformer 满足这三个要求

老师指出,transformer 架构非常优雅地满足了前面三个条件

  • 能考虑 context。
  • 能考虑 order。
  • 输出与输入长度相同。

transformer 这个名字的含义在这里也很直观:

text
如果 10 个东西进去,10 个东西出来。

输出不是数量上的压缩,而是输入的每个元素都被转换成了新的表示。

输入的 10 个 token 仍然对应输出的 10 个 transformed token。

transformer2017 年提出。

老师提到,Google 曾长期投入 machine translation 和 search。

transformer 出现后,Google 把一个名为 BERT 的模型引入搜索系统,并显著提升了搜索质量。

搜索系统通常已经高度优化,因此改进往往很小。但老师指出,BERT 引入 Google Search 后带来了明显的 quality jump。

老师举了一个搜索例子:

text
Brazil traveler to USA needs a visa

理想结果应该是:

text
Brazilian traveler coming to the USA needs visa information.

但旧系统可能返回:

text
US citizens going to Brazil need visa information.

问题在于系统没有充分理解词序和关系。

引入 BERT 后,搜索结果能更准确地返回美国驻巴西使馆等相关页面。

老师称原始 transformer 论文中的架构图已经成为 deep learning community 中的 iconic picture,并说明后续课程会逐步理解这张图。

他还指出,原论文研究者最初主要聚焦 machine translation,并没有完全预料到这个架构后来会被广泛应用到几乎所有领域。

十四、课堂问答:是否可以先丢弃 O

有学生问:

text
是否可以先丢弃那些标为 O 的 token,只输出真正重要的实体?

例如 18 个输入 token 中,只有 8 个与实体有关,那么能否输出更短结果。

老师回答,这是完全可以思考的一种方式。

它相当于建立一个 two-stage model:

  1. 第一阶段做 O / non-O 分类。
  2. 第二阶段只处理 non-O token。

但老师也指出,即使用一个简单的 one-stage model,只要使用 transformer,也能得到非常好的准确率。后面 Colab 会展示这一点。

十五、Self-Attention:从 station 开始

老师接着回答第一个核心问题:

text
如何让一个词的表示考虑周围所有词的上下文?

示例句子是:

text
The train slowly left the station.

每个词先都有一个 standalone embedding

text
w1, w2, w3, w4, w5, w6

其中 station 对应 w6

station 可能表示 radio station、train station、space station 等不同含义。

在当前句子中,它显然是:

text
train station

因此,需要用句子里的其他词来调整 station 的 embedding。

十六、Attention Weight 的直觉

老师先做一个假设:

text
如果已经知道每个词对 station 应该有多大影响,应该怎样使用这些信息?

这就是 attention 的直觉

text
对不同词支付不同程度的注意力。

在:

text
The train slowly left the station.

中,为了理解 station,直觉上:

  • train 权重应较高。
  • slowlyleft 可能有一些帮助。
  • the 权重很低。
  • station 自己的原始 embedding 也应该保留较高权重。

老师手动给出了一组示意权重,例如:

  • train:约 30%
  • left:约 8%
  • slowly:约 12%
  • station 自身:约 40%
  • the:很低

老师强调,这些数字只是为了说明概念,是手工写出来的,不是实际模型计算得到的。

十七、课堂问答:这些权重属于谁

有学生问,这些权重是为了理解整句话,还是只和 station 有关。

老师回答:

text
这些权重只和 station 有关。

也就是说,这组权重描述的是每个词对 station 的 contextual embedding 有多大贡献。

对句子中的每个词,都要分别做类似计算,但权重会不同。

十八、课堂问答:此时是否理解 Word Order

有学生问,此时模型是否已经理解 order。

老师回答:

text
此时还没有处理 order,只是在处理 context。

词序会在后面通过 positional encoding 处理。

另一个学生问,模型如何知道 left 在这里的重要性较低。

老师回答,这种能力不是人工指定的,而是通过训练学出来的。

课程会先赋予模型这种表达能力,具体权重如何形成由 training 决定。

十九、Weighted Average 得到 Contextual Embedding

如果已经有了每个词对 station 的权重,最简单的做法是:

text
weighted average

也就是:

text
0.05 * w1 + 0.30 * w2 + ... + 0.40 * w6

结果仍然是一个向量。

这个新向量就是:

text
contextual embedding of station

老师用记号表示为:

text
w6_hat

其中:

  • w6station 的 standalone embedding。
  • w6_hat 是结合上下文后的 contextual embedding。

形式化地说,s1,6 表示第 1 个词对第 6 个词的权重,s2,6 表示第 2 个词对第 6 个词的权重,以此类推。

于是:

text
w6_hat = s1,6 * w1 + s2,6 * w2 + ... + s6,6 * w6

课堂问答:新词、新上下文与 Autocomplete

有学生问,像 Google 这样的系统如何理解新出现的词,或者一个已知词的新上下文。

老师回答,如果是已知词的新上下文,context 来自输入本身。查询进入系统时通常是一整句话,模型会把这句话作为当前输入的上下文。

如果是从未见过的新词,甚至没有对应的 standalone embedding,那么需要等后续课程讲 byte-pair encoding 后再解释。

学生又追问,这是否会直接影响 predictive search / autocomplete。

老师回答,autocomplete 使用的是稍有不同的机制。过去 Google 使用过复杂的 non-transformer 方案,现在很可能也有 transformer 版本,但老师并不了解其内部具体实现。学生提出的理解方式是合理的,但不能直接等同于课堂当前讲的 self-attention 流程。

二十、课堂问答:旧的 w6 是否保留

有学生问,算出 w6_hat 后,它是加入下一层,还是替换原来的 w6

老师回答:

text
w6_hat replaces w6

也就是说,w6 被替换为 contextual version。

随着表示流经 transformer,它会变得越来越 contextualized。

同样的逻辑会应用到句子中的每个词:

text
w1, w2, ..., w6

都会变成:

text
w1_hat, w2_hat, ..., w6_hat

二十一、权重从哪里来:Dot Product

接下来,老师回答核心问题:

text
attention weights 从哪里来?

直觉是:

text
一个词的权重应与它和目标词的相关程度成正比。

例如:

  • trainstation 很相关。
  • thestation 的相关性较弱。

衡量两个词相关性的一种方法是:

text
dot product

也就是计算两个 standalone embeddings 的点积。

对于两个向量:

text
train_embedding
station_embedding

它们的 dot product 可以写成:

text
|train| * |station| * cos(theta)

其中 theta 是两个向量之间的夹角。

为了简化理解,可以假设两个向量长度都接近 1,那么 dot product 的主要因素就是:

text
cos(theta)

二十二、Dot Product 的几何直觉

老师用角度解释 dot product 如何表示 relatedness。

如果两个向量方向非常接近:

text
theta ≈ 0
cos(theta) ≈ 1

说明它们高度相关。

如果两个向量互相垂直:

text
theta = 90 degrees
cos(theta) = 0

说明它们大致不相关。

如果两个向量方向相反:

text
theta = 180 degrees
cos(theta) = -1

说明它们可以被看作 anti-related。

因此,dot product 可以用来捕捉 embedding 之间的 closeness 或 relatedness

二十三、用 Softmax 把 Dot Products 变成权重

dot product 本身还不能直接作为 weighted average 的权重。

原因是权重需要满足两个条件:

  • 非负。
  • 加起来等于 1

但 dot product 或 cosine 可能是负数。

因此,需要使用:

text
softmax

做法是:

  1. 对每个 dot product 做 exponentiation。
  2. 用每个指数值除以所有指数值之和。

这会得到一组:

text
non-negative
sum to 1

的权重。

老师用角括号表示 dot product,例如:

text
<w1, w6>

再通过:

text
exp(<w1, w6>)

和 softmax 归一化得到真正的 attention weight。

二十四、从 Standalone Embedding 到 Contextual Embedding

整体过程可以总结为:

  1. 输入一组 standalone embeddings
  2. 用 dot product 衡量每个词与目标词的相关性。
  3. 用 softmax 把相关性分数转成 attention weights。
  4. 用 attention weights 对所有 embeddings 做 weighted average。
  5. 得到目标词的 contextual embedding

station 示例中,trainstation 有强相关性,因此会对 station 的 embedding 产生较强拉动。

如果句子中没有 radio,即使 radio station 也是常见含义,radio 在当前句子中也不会产生影响。

因此,当前句子会把 station 拉向 trains、platforms、departures、tickets 等 train station 相关语义区域。

老师也提醒,如果一句话里同时出现 radio stationtrain station 这类更复杂混合上下文,transformer 也可以处理;本节的例子只是为了说明主直觉。

这正是 context 的作用:

text
当前句子中出现了什么,就会影响当前词的 contextual embedding。

老师称这个机制为:

text
self-attention

这是 transformer 的关键构件

二十五、课堂问答:词自身的权重

有学生问,目标词自身在自己的 contextual embedding 中应该如何理解。

老师回答,目标词自身的权重通常会比较高,因为一个向量与自身的 cosine 很接近 1

但它不一定总是最高,因为向量长度并不一定都等于 1

可以把它理解成:

text
先对上下文做一个平均,再把这个结果与原始 embedding 平均。

实际计算中则是所有 token 一起按权重做 weighted average。

二十六、课堂问答:为什么保持输入输出数量相同

有学生问,为什么需要保持输入和输出数量相同。

老师回答,这样可以在通过 transformer stack 时尽量保留信息。

每个 token 都有自己的 contextual embedding,即使某个 token 最终可能标为 O,它在中间层仍可能为其他 token 提供上下文。

保持 cardinality 不变可以保留 optionality:

  • 最后可以选择 aggregate。
  • 可以选择 simplify。
  • 可以选择 summarize。
  • 也可以继续做 per-token classification。

二十七、课堂问答:Context Window

有学生问模型能处理多长的句子。

老师回答,这由:

text
context window

或:

text
maximum length

控制。

这是一个可以设置的参数,后面在 Colab 中会看到。

二十八、Multi-Head Attention 的动机

在单个 self-attention head 之后,老师引入:

text
multi-head attention

一个 attention head 可以学习某一种 attention pattern

但一个复杂句子中可能同时包含多种模式,例如:

  • meaning
  • grammar
  • tense
  • tone
  • facts vs opinions
  • 其他复杂语言模式

因此,不应该只有一种“注意”的方式。

多个 attention heads 可以让模型从不同角度学习不同 pattern

老师把它类比为 convolutional neural network 中的多个 filters:

  • 一个 filter 可能学到 line。
  • 一个 filter 可能学到 curve。
  • 其他 filters 学到其他视觉 pattern。

在 attention 中也是类似逻辑,只是模型通过训练自动学出不同模式,而不是人工指定。

二十九、原始 Transformer 论文中的 Attention 可视化

老师引用了原始 transformer 论文中的例子:

text
The law will never be perfect, but its application should be just.
This is what we are missing, in my opinion.

在一个 attention head 中,perfect 的 contextual embedding 可能大量关注 law

在另一个 attention head 中,perfect 可能主要关注它自身。

不同 attention heads 学到不同的注意模式

老师也提醒,现实中解释 attention head 为什么这样关注通常很困难,不一定能清楚解释每个 head 的语义。

但经验上,多个 attention heads 往往能显著提升目标任务表现。

三十、课堂问答:Attention Head 是否类似 CNN Filter

有学生把 attention head 与 CNN filter 类比。

老师确认这是同一类直觉。

他补充说明,在课堂早期讲 CNN 时,用 10 设计 filter 只是为了演示 vertical line 或 horizontal line detection。

真实训练中,CNN filter 的参数同样不是人工指定的,而是随机初始化后通过 backpropagation 学出来。

attention head 也是如此。

三十一、课堂问答:如果只是 Dot Product,为什么不同 Head 会不同

有学生提出一个关键问题:

text
如果 self-attention 只是 embeddings 的 dot product,那么同样的 embeddings 应该得到同样结果,为什么多个 head 会不同?

老师说这是一个很好的问题,并说明这要留到下一节课详细解释。

当前简化版 self-attention box 内部没有参数。

因此学生的问题等价于:

text
如果 self-attention 里面没有可学习参数,模型到底在学什么?

下一节课会引入更完整的机制,例如可以学习的参数。

本节先保留这个问题。

三十二、Concatenate and Project

多个 attention heads 的输出需要合并。

假设有两个 heads:

  • head 1 输出某个 token 的 contextual embedding:w1_hat
  • head 2 输出同一个 token 的 contextual embedding:z1

这两个向量都表示第 1 个词,但来自不同 attention head。

合并方式是:

text
concatenate

也就是把两个向量接在一起,形成一个更长的向量。

如果原始向量长度是 100,两个 heads concat 后会变成 200

但 transformer 需要保持每层输入输出的 vector length 不变

因此 concat 后会经过一个:

text
dense layer

把长向量投影回原始长度。

这一步称为:

text
concatenate and project

如果有 20 个 attention heads,concat 后向量会变成原来的 20 倍,再通过 projection 回到原始维度。

三十三、Feed-Forward / ReLU 层

在 multi-head attention 之后,还会加入 dense / ReLU 层来引入 non-linearity。

老师说明,通常会使用一个带 ReLU 的 hidden layer,然后再用一个 linear layer 投影回原始维度。

如果输入向量长度是 100,实践中常见设置是:

text
hidden ReLU width ≈ 400

也就是 hidden layer 约为输入维度的 4 倍。

随后再通过 dense layer 投影回 100

这一步的目的包括:

  • 增加 non-linearity。
  • 保持输出维度与输入维度一致。

老师指出,许多设计最初看起来有些 ad hoc,并非来自严格理论推导,但有很强直觉基础。后来很多研究尝试改进 transformer 的各个细节,但原始架构本身非常 robust,很难被轻易超越。

三十四、当前 Transformer Block 的流程

到这里,老师总结当前结构。

输入可以是:

  • random standalone embeddings
  • pretrained embeddings,例如 GloVe

然后:

  1. embeddings 进入多个 self-attention heads
  2. 每个 head 输出 contextual embeddings。
  3. 多个 heads 的输出被 concatenated。
  4. 通过 dense projection 回到原始维度。
  5. 经过 ReLU 和 linear layer。
  6. 输出同样数量、同样长度的 contextual embeddings。

如果输入是 6 个向量,每个向量长度为 100,输出仍然是:

text
6 vectors, each 100 dimensions

不同的是,输出向量的数值已经被上下文化。

老师用这种方式说明:

text
transformer block 是一个保持 shape 不变、但改变表示内容的 black box。

三十五、目前已经解决两个要求

到这里为止,模型已经满足了三个要求中的两个:

  1. 通过 self-attention 考虑 context。
  2. 输出长度与输入长度相同。

但还有一个问题没有解决:

text
word order

当前的 dot product self-attention 本质上作用于 set,而不是 sequence。

如果把句子:

text
The train slowly left the station.

打乱成:

text
The station slowly left the train.

只依赖 dot product 的 self-attention 无法区分它们的顺序差异。

因为它计算的是 token pair 之间的关系,而不包含位置。

三十六、Set 与 Sequence

老师指出,如果处理的问题本来不关心顺序,那么此时的 transformer 已经可以使用。

例如某些 structured / tabular data:

  • blood pressure
  • cholesterol level
  • 其他医学或结构化特征

这些特征之间没有自然词序,但仍可用于预测 heart disease 之类目标。

因此,transformer 可以服务于:

  • order 不重要的 set problem。
  • order 重要的 sequence problem。

对于 sequence,需要额外加入位置相关信息。

三十七、Positional Encoding

为了解决 word order,老师引入:

text
positional encoding

有很多方法可以给 transformer 提供位置信息。

本节课采用最简单且实践中效果不错的一种方式:

text
把每个位置也看作 categorical variable,并为每个位置学习一个 embedding。

如果最大句长是 30,那么每个词的位置就是:

text
0, 1, 2, ..., 29

这些位置编号可以像词一样拥有自己的 embedding。

做法是:

text
final input embedding = word embedding + position embedding

三十八、Positional Encoding 数值示例

老师给出一个极简词表:

text
unknown
cat
mat
I
sit
love
the
you
on

假设每个 word embedding 的维度只有 2

老师提醒,上一节使用的 GloVe embeddings 大约是 100 维,作业中使用的 embeddings 还会更长;这里设置为 2 维只是为了方便演示计算。

例如:

text
cat = [0.5, 7.1]

再假设最大句长是 10,位置编号为:

text
0, 1, 2, ..., 9

每个位置也有一个 2 维 embedding。

例如 position 0 的 embedding 是:

text
[1.3, 3.9]

对于句子:

text
Cat sat mat

cat 出现在 position 0

因此:

text
cat word embedding      = [0.5, 7.1]
position 0 embedding   = [1.3, 3.9]
sum                    = [1.8, 11.0]

于是,进入 transformer 的不是原始 cat embedding,而是:

text
[1.8, 11.0]

如果句子变成:

text
Mat sat cat

cat 的 word embedding 仍然是 [0.5, 7.1],但它的位置变了,因此会加上不同的 position embedding。

这样,同一个词出现在不同位置时,进入模型的向量也不同。

三十九、Position Embedding 从哪里来

老师问:

text
这些 position embeddings 从哪里来?

答案仍然是:

text
learned with backprop

训练开始时,这些 position embeddings 可以是随机数。

随着模型训练,它们会通过 backpropagation 被不断更新。

四十、课堂问答:Position Embedding 是否每个句子不同

有学生问,position embedding 是否会随每个句子变化。

老师回答:

text
不是。

position embedding table 是一张共享表。

例如任意输入句子中,只要某个 token 位于第 7 个位置,就使用第 7 个位置对应的 embedding。

它只与位置有关,不与具体句子有关。

四十一、课堂问答:同一个词重复出现

有学生问,如果同一个词在一个句子中出现多次怎么办。

老师用例子说明:

text
Cat cat cat

三个 cat 的 word embedding 都相同:

text
[0.5, 7.1]

但它们的位置不同:

  • 第一个 cat 加 position 0 embedding。
  • 第二个 cat 加 position 1 embedding。
  • 第三个 cat 加 position 2 embedding。

因此,三个最终向量不同。

这就是 position embedding 的作用。

四十二、课堂问答:Position Table 与 Word Table 是否绑定

有学生问,position embedding table 是否依赖于 standalone embedding table。

老师回答:

text
independent

position embedding table 只取决于最大输入长度假设。

它不关心词表里有哪些词。

word embedding table 和 position embedding table 是两张独立表,只是在输入 transformer 前被相加。

四十三、课堂问答:Malformed Sentence

有学生问,如果输入句子本身有错误,例如出现语法或缺词问题,输出是否会错。

老师回答,从严格的 arithmetic 角度看,错误输入会导致相应计算结果。

但 transformer 通常在大量数据上训练,因此对这类噪声可能相当 robust。

四十四、课堂问答:Filler Words

有学生问,如果输入来自语音转写,包含很多:

  • um
  • uh
  • like

这类 filler words,是否需要过滤。

老师回答,后面会讨论 byte-pair encoding

在那类 tokenization 中,模型会把 individual characters、word fragments 和 words 都作为可能的 tokens。

umuh 这样的词会被映射成较小 token,并像其他 token 一样被处理。

四十五、课堂问答:语义与位置哪个更重要

有学生问,既然 word embedding 和 position embedding 只是相加,那么语义信息是否可能比位置信息更重要。

老师回答,事先无法知道在某个具体任务或句子中哪一部分更重要。

训练过程会通过大量文本数据学习这些 embedding 的合适值,使整体准确率尽可能高。

这里体现了人类直觉与 backprop 学习之间的张力:很多时候可以把设计交给训练过程,让模型自己学出有效参数。

四十六、课堂问答:实际输入 Transformer 的是什么

有学生问,最终进入 transformer 的是 sum vector,还是幻灯片右侧展示的矩阵。

老师回答,实际进入 transformer 的是相加后的向量。

幻灯片右侧的矩阵只是为了演示计算过程。

四十七、课堂问答:Token 与 Punctuation

有学生问,输入是否还会去掉 punctuation,是否支持 multi-sentence input,以及每个句子是否都有 positional embedding。

老师回答,本节目前从 tokens 开始讨论。

在本节的简单例子中,token 基本等同于 words,并假设做了简单 standardization。

但在 GPT-4 这类模型中,tokenization scheme 不同。

一个 token 可能是:

  • word 的一部分
  • individual character
  • punctuation mark

因此,punctuation 是否被保留、如何被处理,取决于 tokenizer。

老师会在后续讲 byte-pair encoding 时回到这个问题。

课堂转写中这里出现了 doesn't support punctuation 的表述,但上下文是在说明 GPT 系列能够把 punctuation 作为 token 并在输出中保留完整标点,因此笔记按这个上下文理解为:GPT 类 tokenizer 可以处理 punctuation。

四十八、Transformer Encoder

到这里,三个要求都已经满足

  • 通过 self-attention 处理 surrounding context。
  • 通过 positional encoding 处理 order。
  • 通过 shape-preserving design 保持输出与输入等长。

这个结构称为:

text
transformer encoder

老师展示了原始论文中的 encoder 图,并解释其中流程:

  1. 输入文本,例如 The cat sat on the mat
  2. 文本被转换成 tokens。
  3. tokens 被转换成 input embeddings / standalone embeddings。
  4. 加上 position-dependent embeddings。
  5. 进入 transformer block。
  6. 经过 multi-head attention
  7. 经过 add and norm
  8. 经过 feed forward network
  9. 再经过 add and norm
  10. 输出 contextual representations。

其中:

  • add and norm 会在下一节课解释。
  • residual connections 和 layer normalization 也会在下一节课解释。

四十九、Encoder 的关键接口:输入输出 Shape 一致

老师强调,encoder 最重要的特点之一是:

text
输入和输出的 size 一致。

这里的 size 包括两层含义:

  1. token 数量相同。
  2. 每个 token 的 vector length 相同。

因为接口一致,所以可以把多个 transformer encoder blocks 堆叠起来:

text
encoder -> encoder -> encoder -> ...

老师用 pancakes 比喻这种堆叠方式。

他提到:

text
GPT-3 has 96 transformer stacks.

深度学习中,层数越多,模型通常能表示越复杂的模式;前提是有足够数据,避免过拟合。

五十、下一节课会补充的内容

本节课先使用简化版 self-attention解释 transformer 的主干直觉。

老师明确说明,下一节会继续讲:

  • self-attention 内部到底有哪些 learnable parameters
  • 如果当前简化版 self-attention 没有参数,模型到底在学什么
  • residual connections
  • layer normalization
  • add and norm

五十一、课堂问答:多个 Head 与多个 Block 的区别

有学生问,多个 transformer blocks 与多个 self-attention heads 有什么不同。

老师回答:

  • 一个 transformer block 内部可以有多个 attention heads。
  • 增加 heads 是“变宽”,可以在同一层中学习不同 attention patterns。
  • 堆叠 blocks 是“变深”,可以逐层学习更高层次的 abstraction。

老师补充,GPT-3 和 GPT-4 这类模型通常有很多 attention heads。实践中既可以增加 heads 让模型更“宽”,也可以堆叠 blocks 让模型更“深”。

老师用 CNN 类比:

较深的卷积层可以把低层特征组合成更抽象的概念。

例如前一层已经看到很多 edges,后一层可能把这些 edges 和 circles 组合起来识别为 face。

transformer stack 也是类似逻辑:越往上,表示越抽象。

五十二、Colab:用 Transformer 做 Travel Slot Filling

接下来进入 Colab。

目标是把刚刚学到的 transformer encoder 应用到 travel slot problem。

老师先做常规准备,并说明课程团队把前面提到的 ATIS 数据集放到了 raw box 中,便于 Colab 直接读取。

数据集中包含:

  • query column:自然语言输入。
  • slot-filling column:每个 token 对应的 slot label。
  • intent column:整条 query 的 intent label。

本节只使用:

  • query 作为 input text。
  • slot-filling 作为 dependent variable / output。

intent column 暂时不使用。

随后,代码会分别从 training data 和 test data 中取出 queryslot-filling 两列,用于训练和测试。

老师展示的数据示例包括:

  • I want to fly from Boston at 8:38 AM
  • I want to fly from Boston at 8:30 AM and arrive in Denver at 11:00 in the morning
  • What kind of ground transportation is available in Denver?
  • What's the airport at Orlando?
  • How much does the limo service cost within Pittsburgh?

这些例子说明 ATIS 覆盖了较宽范围的旅行相关查询。

五十三、HODL Library

课程团队把 Keras 中与 transformer 相关的代码封装进一个小文件,称为:

text
HODL

老师说明,称它为 library 有些夸张,本质上只是把一组代码放进一个文件,便于课堂使用。

Colab 中会从 HODL 导入:

python
TransformerEncoder

以及:

python
PositionalEmbedding

处理流程是:

  1. 对输入 query 做 vectorization。
  2. 对 token 做 positional embedding。
  3. 把结果送入 transformer encoder。

五十四、输入 Query 的 Vectorization

输入侧需要先对 query 做向量化。

老师演示时出现过 max_query_length is not defined,原因是没有按顺序运行所有 Colab cells;重新运行相关 cell 后继续。

在数据中,输入 queries 的 vocabulary 有:

text
888 tokens

因为输出模式需要 integer tokens,而不是 multi-hot encoding,所以 vectorizer 会输出整数序列。

这些整数后续会进入 embedding layer。

Keras 会保留特殊 token:

  • empty string 作为 pad token
  • UNK 作为 unknown token

老师提到,最常见的 token 中有:

  • to
  • from
  • flights
  • Boston

其中 Boston 出现得尤其频繁。

五十五、输出 Slot 的 Vectorization

输出侧的 slot labels 也是一串 token,因此也需要做类似 STIE 的处理。

但这里有一个重要差异

slot label 中的大小写和符号有具体含义。

例如:

text
B-fromloc.city_name

其中:

  • B
  • -
  • .
  • _

都不能随意删除或改写。

如果使用默认 standardization,Keras 可能会:

  • 去掉 punctuation。
  • 改成 lowercase。

这会破坏标签含义。

因此,输出侧 vectorizer 要设置:

python
standardization=None

也就是告诉 Keras:

text
不要对 slot labels 做默认标准化。

五十六、为什么输出 Vocabulary 是 125

老师在讲概念时说有:

text
123 slots

但在 Colab 中,输出 vocabulary 显示为:

text
125 tokens

学生回答,差异来自特殊 token。

也就是说,除 123 个实际 slot labels 外,还包含类似:

  • padding token
  • unknown token

这样的额外 token。

因此代码中的 softmax 会面向 125 个输出 token。

五十七、Slot Filling 模型结构

老师用一个简单输入说明模型结构:

text
fly from Boston to Denver

对应输出大致是:

text
O O B-fromloc.city_name O B-toloc.city_name

模型流程是:

  1. 输入 token 序列。
  2. 生成 positional input embeddings。
  3. 输入 transformer。
  4. 得到 contextual embeddings。
  5. 通过 ReLU
  6. 对每个 token 输出一个 softmax 分类。

如果输入有 5 个 token,transformer 输出仍有 5 个 contextual embeddings。

然后,每个输出位置都接一个:

text
123-way softmax

在代码中,因为包含特殊 token,实际是:

text
125-way softmax

模型中所有 layer 的权重都会通过:

text
backprop

被优化。

五十八、课堂问答:PositionalEmbedding Layer 是否也要学习

有学生问,Colab 中 import 的 positional embedding 是否就是固定好的。

老师回答,它只是一个 layer。

就像 TextVectorization layer 一样,layer 本身是一段代码或空壳,需要在具体数据上建立 vocabulary 或学习权重。

PositionalEmbedding 中的 weights 仍然需要通过训练学习。

五十九、课堂问答:Transformer 输出之后的维度由谁决定

有学生问,图中黄色 vector layer 维度变化是否有特殊原因。

老师回答,这是 modeler 的选择。

transformer 的职责是输出高层次的 contextual embeddings。

接下来怎么使用这些 embeddings,取决于具体任务。

对于当前任务,可以:

  • 如果 embedding 很长,先用 ReLU 降维或调整表示。
  • 加入 non-linearity。
  • 最后接 softmax 做分类。

老师总结为:

text
When in doubt, throw in a bit of non-linearity.

六十、模型超参数设置

本节 Colab 中,老师从零训练 embeddings,不使用 GloVe

主要设定包括:

text
embedding_dim = 512
dense_dim = 64
num_heads = 5
max_query_length = 30

含义分别是:

  • 每个 embedding vector 长度为 512
  • transformer 内部 feed-forward / dense dimension 为 64
  • attention heads 数量为 5
  • 每条 query 的最大 token 长度为 30

如果输入句子有 35 个 token:

text
last 5 tokens are truncated

如果输入句子有 22 个 token:

text
pad with 8 pad tokens

这样所有输入都变成长度 30

六十一、PositionalEmbedding Layer 内部结构

老师强调,PositionalEmbedding layer 打包了两张不同的表

  1. word embedding table
  2. position embedding table

它们是 distinct tables,只是被包装在同一个 layer 中。

在本节数据中:

word embedding table 的形状是:

text
888 tokens x 512 dimensions

position embedding table 的形状是:

text
30 positions x 512 dimensions

每个输入 token 会取一个 word embedding,再取对应 position 的 embedding,然后相加。

六十二、TransformerEncoder 的参数

TransformerEncoder 对象需要指定三个主要参数:

text
embedding dimension
dense dimension
number of attention heads

在本节中分别是:

  • 512
  • 64
  • 5

经过 transformer encoder 后,输出仍是一组 contextual embeddings。

随后进入传统 DNN 部分:

  1. ReLU layer,128 units。
  2. dropout
  3. Dense output layer。
  4. softmax activation。

输出层大小为:

text
125

也就是 125-way softmax

六十三、参数数量与课后练习

模型 summary 中显示参数量约为:

text
5.3 million

老师建议,在下一节课讲完完整 self-attention 内部参数后,可以手工计算 transformer 中的参数数量,检查是否与 summary 匹配。

这是一个 optional extra credit / personal edification。

老师还说明,可以通过 layer 的:

python
weights

属性查看任意 layer 的权重。

例如查看 PositionalEmbedding layer,可以看到:

  • 888 x 512 的 token embedding table。
  • 30 x 512 的 position embedding table。

训练前也可以查看这些初始权重。

六十四、本节结束位置

由于模型训练需要几分钟,而课堂时间已经接近结束,老师决定停在模型搭建与权重查看这里。

后续内容会在下一节课继续。

老师最后提醒:

如果本节某些细节还不完全清楚,不用担心,下一节课会继续展开,尤其会解释 self-attention 内部到底学习什么。

六十五、本节核心脉络

本节课的主线可以压缩为:

  1. transformer 最初用于 machine translation,但已经扩展到搜索、语音、视觉、强化学习、生成式 AI、多模态模型和 AlphaFold 等场景。
  2. 使用 ATIS travel query 的 slot filling 任务作为动机。
  3. Slot filling 要求对每个 input token 输出一个 slot label。
  4. 该任务要求模型同时满足 context、order 和 same input-output length。
  5. self-attention 用 dot product 和 softmax 为每个词计算 context weights。
  6. weighted average 把 standalone embeddings 转换成 contextual embeddings。
  7. multi-head attention 允许模型学习多种 attention patterns。
  8. concatenate and project 负责合并多个 heads,同时保持 vector length 不变。
  9. Feed-forward / ReLU 层为 transformer block 引入 non-linearity。
  10. positional encoding 通过 position embeddings 注入词序信息。
  11. transformer encoder 保持输入输出 shape 一致,因此可以堆叠成深层 transformer stack
  12. Colab 中用 TransformerEncoderPositionalEmbedding 构建了 ATIS slot filling 模型。

六十六、关键术语表

transformer

一种保持输入输出数量对应、同时将输入表示转换为上下文化表示的深度学习架构。

slot filling

给输入句子中的每个 token 标注任务相关实体类别的序列标注任务。

O

other,表示当前 token 不属于任务关心的实体类别。

B

Beginning,表示某个多 token 实体的开始。

I

Intermediate / inside,表示某个多 token 实体的后续部分。

standalone embedding

不随上下文变化的词向量,例如传统 GloVe 表示。

contextual embedding

结合当前句子上下文后得到的词向量。

self-attention

用输入序列内部 token 之间的相关性来重新计算每个 token 表示的机制。

dot product

衡量两个向量相似度或相关性的基本运算。

softmax

把任意实数分数转换为非负且总和为 1 的权重分布。

attention head

一套 self-attention 机制,可以学习一种 attention pattern。

multi-head attention

并行使用多个 attention heads,再把结果合并的机制。

positional encoding

向 token embedding 中注入位置信息的方法。

transformer encoder

由 input embeddings、positional encodings、multi-head attention、feed-forward network、add and norm 等组件构成的 encoder block。

context window

模型一次能处理的最大 token 长度。

最后更新于: