GQA (group query attention)

什么是GQA?

多个head的Query共用一组K和V。llama模型就用到该技术。

需要明确几点:

1.group有几组

2.每个group对应几个head

3.q以head为单位 k,v以group为单位 每个head/group特征维度都是head_dim

代码实现

python 复制代码
import torch.nn as nn
import torch
import math

# 自注意力
class GroupQueryAttention(nn.Module):
  def __init__(self, d_model, n_heads, n_groups):
    super().__init__()
    self.d_model = d_model
    self.n_heads = n_heads
    self.n_groups = n_groups

    assert d_model % n_heads == 0
    self.head_dim = d_model // n_heads
    # 每个group对应几个head
    self.heads_per_group = n_heads // n_groups

    # 以head为单位
    self.w_q = nn.Linear(d_model, n_heads*self.head_dim)  # n_heads*head_dim=d_model
    # 以group为单位
    self.w_k = nn.Linear(d_model, n_groups*self.head_dim)
    self.w_v = nn.Linear(d_model, n_groups*self.head_dim)

    self.w_combine = nn.Linear(d_model, d_model)
    self.softmax = nn.Softmax(dim=-1)
  
  # 给k,v进行复制,假设每个组对应3个head,那就要把每个组的数据复制3遍
  def expand(self, data): # data:k/v [b, group, seq_len, head_dim]
    b,_,seq_len,_ = data.shape
    data = data[:,:,None,:,:].expand(b, self.n_groups, self.heads_per_group, seq_len, self.head_dim)
    data = data.contiguous().view(b, -1, seq_len, self.head_dim)
    return data  # [b, group*heads_per_group, seq_len, head_dim]

  def forward(self, x, use_mask=False): # x: [b, seq_len, d_model]
    b, seq_len, _ = x.shape
    q,k,v = self.w_q(x), self.w_k(x), self.w_v(x)
    q = q.view(b, seq_len, self.n_heads, self.head_dim).permute(0,2,1,3)  # 以head为单位
    k = k.view(b, seq_len, self.n_groups, self.head_dim).permute(0,2,1,3) # 以group为单位
    v = v.view(b, seq_len, self.n_groups, self.head_dim).permute(0,2,1,3)

    # 复制
    k,v = self.expand(k), self.expand(v)
    score = q @ k.transpose(-1,-2) / math.sqrt(self.head_dim)
    if use_mask:
      mask = torch.tril(torch.ones(seq_len, seq_len))
      score = score.masked_fill(mask==0, float('-inf'))
    
    score = self.softmax(score) @ v
    score = score.permute(0,2,1,3).contiguous().view(b, seq_len, self.n_heads*self.head_dim)

    out = self.w_combine(score)
    return out

x = torch.rand(2,100,384)
model = GroupQueryAttention(384, 4, 2)
out = model(x)
print(out.shape)
相关推荐
benchmark_cc7 小时前
如何用 Python + QuantDash 快速构建高胜率“配对交易(Pairs Trading)”策略?
开发语言·人工智能·python·pandas·量化交易·quantdash
Python+999 小时前
Java 枚举类(Enum)详解:从基础到高级应用
java·开发语言·python
华盈生物9 小时前
从bulk数据到组织原位观察:超多重免疫荧光成像如何为转化研究提供蛋白层线索?
深度学习·pcf·多模态数据·空间单细胞蛋白组·单细胞组织原位空间蛋白组学·组织原位空间蛋白组学·超多重蛋白成像技术
dunge20269 小时前
2026年7月最新ChatGPT Plus / Pro 与 Codex:当 AI Agent 最新5.6版本来袭,必须理解事务、幂等与补偿
开发语言·人工智能·python
这张生成的图像能检测吗10 小时前
(论文速读)CLUSTER-GCN:一种训练深度和大图卷积网络的有效算法
人工智能·深度学习·图神经网络·聚类算法
Omics Pro10 小时前
深度学习多组学互作:组内+组间
数据库·人工智能·深度学习·mysql·搜索引擎·自然语言处理
txg66611 小时前
机器人领域简报(2026年7月9日—16日)
人工智能·深度学习·机器人
小白学大数据11 小时前
两周完成爬虫技术栈升级:Scrapy 迁移 Crawlo 的路径与取舍
爬虫·python·scrapy
用户83562907805111 小时前
使用 Python 在 Excel 中添加和自定义文本框
后端·python
饼饼学习空间智能12 小时前
2026数字孪生选型避坑指南:如何避免项目沦为3D大屏展示
人工智能·深度学习