在 Transformer 模型中,多头注意力机制(multi-head attention)是一种关键技术,它允许模型从多个不同的“头”中学习不同的注意力模式。为了实现这一点,输入的特征向量需要被分成多个“头”,每个头都有独立的投影。下面是代码片段的具体解释:
keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
详细解释
这行代码的作用是将输入张量
keys
重塑为一个包含多头维度的张量,以便在多头注意力机制中使用。背景
在多头注意力机制中,输入特征(例如
keys
)通常有以下维度:- \( b \):批次大小(batch size)
- \( \text{num\_tokens} \):序列中的令牌(token)数量
- \( d_{\text{out}} \):输出特征维度
为了进行多头注意力操作,我们需要将特征维度 \( d_{\text{out}} \) 分解成多个头,每个头有自己的维度。这通过以下两个参数实现:
- \( \text{num\_heads} \):头的数量
- \( \text{head\_dim} \):每个头的特征维度,通常 \( \text{head\dim} = \frac{d{\text{out}}}{\text{num\_heads}} \)
具体操作
假设
keys
的原始形状是 \((b, \text{num\tokens}, d{\text{out}})\),那么 keys.view(b, num_tokens, self.num_heads, self.head_dim)
的作用如下:- 初始形状:假设
keys
的形状为 \((b, \text{num\tokens}, d{\text{out}})\)。
- 重塑形状:
keys.view(b, num_tokens, self.num_heads, self.head_dim)
将keys
重塑为形状 \((b, \text{num\_tokens}, \text{num\_heads}, \text{head\_dim})\)。
这相当于将最后一个维度 \( d_{\text{out}} \) 分解为两个维度:头的数量 \( \text{num\_heads} \) 和每个头的维度 \( \text{head\_dim} \)。
代码示例
假设我们有以下参数和张量:
import torch b = 2 # 批次大小 num_tokens = 4 # 序列中的令牌数量 d_out = 8 # 输出特征维度 num_heads = 2 # 头的数量 head_dim = d_out // num_heads # 每个头的特征维度 # 创建一个示例张量 keys,形状为 (b, num_tokens, d_out) keys = torch.randn(b, num_tokens, d_out) # 将 keys 重塑为 (b, num_tokens, num_heads, head_dim) keys = keys.view(b, num_tokens, num_heads, head_dim) print(keys.shape) # 输出:torch.Size([2, 4, 2, 4])
为什么这样做
通过将张量重塑为 \((b, \text{num\_tokens}, \text{num\_heads}, \text{head\_dim})\),我们可以在计算注意力时对每个头独立地进行操作。每个头有自己的键(key)、查询(query)和值(value),可以捕捉输入序列的不同方面。这种方法使模型能够并行地计算多个注意力分数,从而提高了模型的表示能力和计算效率。
总结
keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
这行代码的主要作用是将输入张量
keys
重塑为适合多头注意力机制的形状,以便对每个头独立地进行操作。通过这种重塑,我们可以有效地实现并行计算多个头的注意力分数,从而增强模型的表现力。