目录
2. 为什么要拆分成多头?
拆分多头的核心目的是增强注意力机制的表达能力,具体体现在以下几点:
总结
单头注意力是基础的注意力计算单元,而多头注意力通过 "分而治之" 的策略,在不显著增加计算量的前提下,让模型能学习到更丰富、更多样的注意力模式,从而提升对序列数据的理解能力。这也是 Transformer 模型在 NLP 等领域取得成功的核心原因之一。
-
初步对tranform的结构以及源码理解
可以先参考知乎文章理解大概结构,不懂的多读几遍,书读百遍词义自现
transformer中的Q,K,V到底是什么? - 陈碎的回答 - 知乎
https://www.zhihu.com/question/427629601/answer/1948381787672785377 -
针对源码的每一行的理解
def forward(self, x): # x 的形状: (batch_size, num_tokens, d_in) # batch_size: 批次大小,num_tokens: 序列长度,d_in: 输入特征维度 b, num_tokens, d_in = x.shape # 1. 提取 Q, K, V 向量 keys = self.W_key(x) # 用线性层提取 key 向量,形状: (b, num_tokens, d_out) queries = self.W_query(x) # 提取 query 向量,形状同上 values = self.W_value(x) # 提取 value 向量,形状同上 # 2. 重塑并拆分多头 keys = keys.view(b, num_tokens, self.num_heads, self.head_dim) values = values.view(b, num_tokens, self.num_heads, self.head_dim) queries = queries.view(b, num_tokens, self.num_heads, self.head_dim) # 现在形状变为: (b, num_tokens, num_heads, head_dim) # 3. 转置维度,将多头维度提前 keys = keys.transpose(1, 2) # 形状: (b, num_heads, num_tokens, head_dim) queries = queries.transpose(1, 2) # 同上 values = values.transpose(1, 2) # 同上 # 4. 计算注意力分数 # Q和K的点积,形状变为: (b, num_heads, num_tokens, num_tokens) attn_scores = queries @ keys.transpose(2, 3) # K转置最后两个维度 # 5. 应用掩码(主要用于 decoder 防止未来信息泄露) mask_bool = self.mask.bool()[:num_tokens, :num_tokens] # 截取有效长度掩码 attn_scores.masked_fill_(mask_bool, -torch.inf) # 掩码位置填充负无穷 # 6. 计算注意力权重 # 除以 head_dim 的平方根进行缩放,再做 softmax attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1) attn_weights = self.dropout(attn_weights) # 应用 dropout 防止过拟合 # 7. 计算上下文向量(加权求和) # 注意力权重与V相乘,形状: (b, num_heads, num_tokens, head_dim) context_vec = (attn_weights @ values).transpose(1, 2) # 转置回原顺序 # 8. 拼接多头结果 context_vec = context_vec.contiguous().view(b, num_tokens, self.d_out) # contiguous() 确保内存连续,view() 重塑为 (b, num_tokens, d_out) # 9. 输出投影 context_vec = self.out_proj(context_vec) # 通过线性层输出最终结果 return context_vec其中的疑问:多头注意力和单头注意力的区别是什么?为什么要拆分成多头?
=====豆包答案 ===多头注意力(Multi-Head Attention)和单头注意力(Single-Head Attention)是 Transformer 模型中注意力机制的两种实现形式,它们的核心区别和拆分多头的原因可以从以下几个方面理解:
1. 结构上的核心区别
-
单头注意力:
- 整个注意力计算是一个整体,将输入通过一组线性变换得到 Q、K、V 向量(维度相同)。
- 计算一组注意力权重,并对 V 进行加权求和,得到单一的上下文向量。
- 公式上可表示为:
Attention(Q,K,V) = softmax((QK^T)/√d_k)V
-
多头注意力:
- 将输入通过多组独立的线性变换得到多组 Q、K、V 向量(通常分为
h组,即h个头)。 - 每组 Q、K、V 单独计算注意力(类似单头机制),得到
h个独立的上下文子向量。 - 最后将
h个子向量拼接,再通过一个线性层整合为最终输出。 - 公式上可表示为:
MultiHead(Q,K,V) = Concat(head_1, head_2, ..., head_h)W^O
其中每个head_i = Attention(QW_i^Q, KW_i^K, VW_i^V)
- 将输入通过多组独立的线性变换得到多组 Q、K、V 向量(通常分为
-
捕捉多样化的注意力模式
单头注意力只能学习一种全局的注意力分布,而多头可以并行学习不同的 "子注意力模式"。例如:- 某些头可能关注局部相邻的 token(如语法依赖)。
- 某些头可能关注长距离的语义关联(如指代关系)。
- 这种多样性让模型能从不同角度理解序列,提升特征表达的丰富性。
-
扩展模型的 "感知野"
多头机制相当于将注意力的计算分散到多个低维度子空间(每个头的维度为d_model/h),而不是一个高维度空间。这使得模型能更高效地学习到不同子空间中的关联模式,避免单一高维空间中可能出现的信息冗余或干扰。 -
提高并行计算效率
虽然多头看似增加了计算量,但每个头的维度降低(d_model/h),整体计算复杂度与单头(O(d_model^2))相当(实际为O(d_model^2/h * h) = O(d_model^2))。同时,多头计算可以天然并行,适合 GPU 加速。 -
实验验证的有效性
在 Transformer 的原始实验中,多头注意力(如 8 头)在机器翻译等任务上的表现显著优于单头注意力,证明了其在捕捉复杂依赖关系上的优势。 -
==================个人的一些总结========
-
其实,tranform 就是三个全连接层+一个输出投影全连接层,参数量就这些
-
然后, 整个流程就是
Attention(Q,K,V) = softmax((QK^T)/√d_k)V
1万+

被折叠的 条评论
为什么被折叠?



