5 多头注意力
-
当给定相同的查询、键和值的集合时,我们希望模型可以基于相同的注意力机制学习到不同的行为,然后将不同的行为作为知识组合起来,捕获序列内各种范围的依赖关系(例如,短距离依赖和长距离依赖关系)。因此,允许注意力机制组合使用查询、键和值的不同 子空间表示(representation subspaces)可能是有益的。
-
多头注意力(multihead attention):为此,与其只使用单独一个注意力汇聚,我们可以用独立学习得到的h组不同的线性投影来变换查询、键和值。然后,这h组变换后的查询、键和值将并行地送到注意力汇聚中。最后,将这h个注意力汇聚的输出拼接在一起,并且通过另一个可以学习的线性投影进行变换,以产生最终输出。对于h个注意力汇聚输出,每一个注意力汇聚都被称作一个头(head)。

5.1 模型
- 给定查询$ \mathbf{ q } \in \mathbb{ R }^{ d _ { q } }
\mathbf{ k } \in \mathbb{ R }^{ d _ { k } } \mathbf{ v } \in \mathbb{ R }^{ d _ { v } } \mathbf{ h } _ { i } i = 1,2, \ldots , h $)的计算如下:
- 其中$ \mathbf{ W }
\mathbf{ W } _ { o } $来得到最终输出:
- 基于这种设计,每个头都可能会关注输入的不同部分,可以表示比简单加权平均值更复杂的函数。
1 | import math |
5.2 实现
- 通常选择缩放点积注意力作为每一个注意力头。为了避免计算代价和参数代价的大幅增长,设定
,其中 、 、 和 分别是查询、键、值和输出的维度。如果将查询、键和值的线性变换的输出数量设置为 ,则可以并行计算h个头。
1 | #@save |
- 使用键和值相同的小例子来测试
1 | num_hiddens, num_heads = 100, 5 |
MultiHeadAttention(
(attention): DotProductAttention(
(dropout): Dropout(p=0.5, inplace=False)
)
(W_q): Linear(in_features=100, out_features=100, bias=False)
(W_k): Linear(in_features=100, out_features=100, bias=False)
(W_v): Linear(in_features=100, out_features=100, bias=False)
(W_o): Linear(in_features=100, out_features=100, bias=False)
)
1 | batch_size, num_queries, num_kvpairs, valid_lens = 2, 4, 6, torch.tensor([3, 2]) |
torch.Size([2, 4, 100])