大模型中的注意力机制——MHA、GQA、MQA

文章探讨了Transformer模型中的注意力机制优化,主要介绍了MHA(多头注意力)、MQA(多查询注意力)和GQA(分组查询注意力)三种模式。MHA允许不同头的Key和Value独立,MQA共享Key和Value以减少参数,而GQA则是介于两者之间,通过分组来平衡效率与性能。GQA-1与MQA等价,GQA-H与MHA等价。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意力机制是Transformer模型的核心组件。考虑到注意力机制的计算效率问题,研究人员也进行了许多研究。代表的就是以下三种模式:

MHA(Multi-head Attention)是标准的多头注意力机制,包含h个Query、Key 和 Value 矩阵。所有注意力头的 Key 和 Value 矩阵权重不共享

MQA(Multi-Query Attention,Fast Transformer Decoding: One Write-Head is All You Need)是多查询注意力的一种变体,也是用于自回归解码的一种注意力机制。与MHA不同的,MQA 让所有的头之间共享同一份 Key 和 Value 矩阵,每个头只单独保留了一份 Query 参数,从而大大减少 Key 和 Value 矩阵的参数量。

GQA(Grouped-Query Attention,GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints)是分组查询注意力,GQA将查询头分成G组,每个组共享一个Key 和 Value 矩阵。GQA-G是指具有G组的grouped-query attention。GQA-1具有单个组,因此具有单个Key 和 Value,等效于MQA。若GQA-H具有与头数相等的组,则其等效于MHA。

显然,GQA介于MHA和MQA之间。下图展示了他们的具体结构:
在这里插入图片描述

### 多头自注意力机制MHATransformer架构中,多头自注意力机制(Multi-Head Self-Attention, MHSA)是一个核心组件。该机制允许模型在同一序列的不同位置关注不同部分的信息,从而增强表达能力。 #### 单头自注意力机制概述 单头自注意力机制通过查询矩阵\(Q\)、键矩阵\(K\)和值矩阵\(V\)来计算注意力权重。具体过程如下: 1. \(Q\), \(K\), 和 \(V\) 是输入数据经过线性变换后的三个向量表示; 2. 计算相似度得分:\[ A = softmax(\frac{QK^T}{\sqrt{d_k}}) \][^1]; 3. 得到加权求和的结果作为最终输出:\[ Z = AV \][^1]; 其中,\( d_k \) 表示键维度大小,用于缩放点积以稳定梯度传播。 #### 多头自注意力机制详解 为了捕捉更丰富的特征关系,在单一头部的基础上引入了多个平行的注意层——即所谓的“多头”。每个独立的头都执行相同的自注意力操作,但是参数彼此之间互不共享。这样做的好处是可以让网络学会从不同的表征空间提取信息。 对于一个多头结构来说,其整体流程可描述为: 1. 将原始输入分别映射至若干组新的\( Q_i,K_i,V_i \)(对应第 i 个head); 2. 对每一对\( (Q_i,K_i,V_i)\),按照上述提到的方式单独做一次标准的自注意力运算; 3. 把所有这些结果拼接起来形成一个更大的张量,并再次投影回期望尺寸的空间内; 公式化表述就是: \[ MultiHead(Q,K,V)=Concat(head_1,...,head_h)V'W_O \] 这里 h 指的是总的heads数目; W_O 则是用来调整最后组合后维度的一个全连接层权重矩阵. 因此,“MHSA”实际上指的就是这种带有多个并行工作的自注意力单元的整体设计模式。“MHA”通常是指实现了这个概念的具体模块或函数名称,二者本质上是一致的概念但在称呼上有所区别. ```python import torch.nn as nn class MultiHeadSelfAttention(nn.Module): def __init__(self, embed_size, num_heads): super(MultiHeadSelfAttention, self).__init__() self.embed_size = embed_size self.num_heads = num_heads assert embed_size % num_heads == 0, "Embed size must be divisible by heads" self.depth = embed_size // num_heads self.wq = nn.Linear(embed_size, embed_size) self.wk = nn.Linear(embed_size, embed_size) self.wv = nn.Linear(embed_size, embed_size) self.dense = nn.Linear(embed_size, embed_size) def split_heads(self, x, batch_size): """Split the last dimension into (num_heads, depth). Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth) """ x = x.view(batch_size, -1, self.num_heads, self.depth).transpose(1, 2) return x def forward(self, q, k, v, mask=None): batch_size = q.size(0) q = self.wq(q) k = self.wk(k) v = self.wv(v) q = self.split_heads(q, batch_size) k = self.split_heads(k, batch_size) v = self.split_heads(v, batch_size) scaled_attention, attention_weights = scaled_dot_product_attention( q, k, v, mask) concat_attention = scaled_attention.transpose(1, 2)\ .contiguous()\ .view(batch_size, -1, self.embed_size) output = self.dense(concat_attention) return output, attention_weights def scaled_dot_product_attention(q, k, v, mask): matmul_qk = torch.matmul(q, k.transpose(-2,-1)) dk = torch.tensor([k.shape[-1]], dtype=torch.float32).sqrt() logits = matmul_qk / dk if mask is not None: logits += (mask * -1e9) attention_weights = F.softmax(logits, dim=-1) output = torch.matmul(attention_weights, v) return output, attention_weights ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hilbob

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值