精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐 原創(chuàng)

發(fā)布于 2025-7-17 14:03
瀏覽
0收藏

注意力機(jī)制是 Transformer 架構(gòu)的靈魂,也是大模型性能與效率平衡的關(guān)鍵。從最初的多頭注意力(MHA)到最新的多頭潛在注意力(MLA),研究者們通過不斷優(yōu)化鍵(Key)、值(Value)與查詢(Query)的交互方式,在模型表達(dá)能力與計(jì)算效率之間持續(xù)探索。本文將系統(tǒng)梳理 MHA、MQA、GQA、MLA 四種主流注意力機(jī)制的理論根基,剖析其設(shè)計(jì)動(dòng)機(jī)、核心原理與代碼實(shí)踐。

一、多頭注意力(MHA):并行特征捕捉的奠基之作

1.1 設(shè)計(jì)動(dòng)機(jī):突破單頭注意力的表達(dá)瓶頸

在 Transformer 提出之前,傳統(tǒng)注意力機(jī)制(如 Bahdanau 注意力)通過單組 Query、Key、Value 計(jì)算序列依賴,難以同時(shí)捕捉不同維度的特征模式(如語法結(jié)構(gòu)、語義關(guān)聯(lián))。MHA 的核心創(chuàng)新在于將輸入映射到多個(gè)子空間并行計(jì)算注意力,使模型能同時(shí)關(guān)注序列中不同位置的多維度特征,從而增強(qiáng)對(duì)復(fù)雜模式的建模能力。

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)圖片

1.2 核心原理:三分三拆,聚合增強(qiáng)

MHA 的計(jì)算過程可概括為 “線性變換 - 多頭拆分 - 注意力計(jì)算 - 聚合投影” 四步:

  • 線性變換:輸入序列通過三個(gè)可學(xué)習(xí)矩陣生成 Query(Q)、Key(K)、Value(V),維度均為(batch_size, seq_len, hidden_size)。
  • 多頭拆分:將 Q、K、V 按頭數(shù)(num_heads)拆分,每個(gè)頭的維度為(head_dim = hidden_size /num_heads),形狀調(diào)整為(batch_size, num_heads, seq_len, head_dim)。
  • 縮放點(diǎn)積注意力:每個(gè)頭獨(dú)立計(jì)算注意力權(quán)重,公式如下,其中根號(hào) d_{k} 為縮放因子,緩解點(diǎn)積過大導(dǎo)致的梯度消失問題。

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

  • 聚合投影:將所有頭的輸出拼接,通過線性層映射回原始維度(hidden_size)。

1.3 理論優(yōu)勢(shì)與局限

  • 優(yōu)勢(shì):多頭并行機(jī)制使模型能捕捉多尺度特征(如局部句法與全局語義),是大模型強(qiáng)表達(dá)能力的核心來源。
  • 局限:參數(shù)量與計(jì)算量隨頭數(shù)線性增長(僅 Q、K、V 的線性層參數(shù)量就達(dá)

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

,且推理時(shí)需緩存所有頭的 K、V,導(dǎo)致 KV 緩存占用過高(每 token 緩存

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

,限制長序列與大規(guī)模部署。

二、多查詢注意力(MQA):極致效率的參數(shù)共享方案

2.1 設(shè)計(jì)動(dòng)機(jī):破解 KV 緩存的內(nèi)存瓶頸

MHA 的 KV 緩存隨頭數(shù)線性增長,在長序列場(chǎng)景(如文檔理解)中極易引發(fā)顯存溢出。MQA 的核心思路是通過共享 K、V 參數(shù)減少冗余計(jì)算與存儲(chǔ),在犧牲部分表達(dá)能力的前提下?lián)Q取效率提升。

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

2.2 核心原理:單組 KV,多頭 Query

MQA 對(duì) MHA 的改進(jìn)體現(xiàn)在參數(shù)共享策略:

  • Query 保持多頭獨(dú)立:Q 仍通過多頭線性層生成,確保每個(gè)頭的查詢能力差異化。
  • Key 與 Value 全局共享:所有頭共享一組 K、V 參數(shù),即 K、V 的線性層輸出維度為(batch_size, seq_len, head_dim),而非 MHA 的(batch_size, seq_len, hidden_size)。
  • 廣播擴(kuò)展:通過??unsqueeze???與??expand??操作將共享的 K、V 擴(kuò)展到所有頭,實(shí)現(xiàn)多頭注意力計(jì)算。

2.3 理論優(yōu)勢(shì)與局限

  • 優(yōu)勢(shì):參數(shù)量大幅降低(K、V 的線性層參數(shù)量從
  • 大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

  • 降至

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

,KV 緩存量僅為 MHA 的 1/num_heads,推理速度提升顯著。

  • 局限:K、V 的全局共享導(dǎo)致頭間特征區(qū)分度下降,可能損失模型表達(dá)能力(尤其長序列任務(wù)中對(duì)細(xì)微差異的捕捉能力)。

三、分組查詢注意力(GQA):性能與效率的折中之道

3.1 設(shè)計(jì)動(dòng)機(jī):平衡表達(dá)與效率的中間方案

MQA 雖高效但損失過多表達(dá)能力,MHA 雖強(qiáng)但成本過高。GQA 通過分組共享 KV 參數(shù),在兩者間找到平衡:將 Query 頭劃分為若干組,每組共享一組 K、V,既減少冗余又保留一定的頭間差異。

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

3.2 核心原理:分組共享,局部獨(dú)立

  • 分組策略:設(shè)總頭數(shù)為num_heads,每組包含group_size個(gè)頭,則組數(shù)為num_groups = num_heads / group_size
  • KV 按組生成:K、V 的線性層輸出維度為(batch_size,seq_len,num_groups,head_dim),每組對(duì)應(yīng)一組獨(dú)立的 K、V。
  • 擴(kuò)展計(jì)算:通過??unsqueeze???與??expand??將每組 K、V 擴(kuò)展到組內(nèi)所有頭,實(shí)現(xiàn)分組注意力計(jì)算。

3.3 理論優(yōu)勢(shì)與局限

  • 優(yōu)勢(shì):參數(shù)量與 KV 緩存量為 MHA 的num_groups / num_heads(如 8 頭分為 4 組,成本降至 50%),同時(shí)保留組間差異,表達(dá)能力優(yōu)于 MQA。
  • 局限:性能依賴分組大小group_size 的選擇,過小則接近 MHA(效率低),過大則接近 MQA(表達(dá)弱),需根據(jù)任務(wù)調(diào)優(yōu)。

四、多頭潛在注意力(MLA):低秩壓縮與位置解耦的創(chuàng)新融合

4.1 設(shè)計(jì)動(dòng)機(jī):低秩分解與位置編碼的協(xié)同優(yōu)化

MHA、MQA、GQA 均未突破 “顯式生成 K、V 并緩存” 的范式,而 MLA 通過低秩參數(shù)化壓縮 KV 維度,并解耦內(nèi)容與位置信息,實(shí)現(xiàn)效率與性能的雙重突破,尤其適合長序列與大規(guī)模模型部署。

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

4.2 核心原理:低秩壓縮 + 位置解耦,雙線并行

MLA 的創(chuàng)新體現(xiàn)在兩個(gè)關(guān)鍵設(shè)計(jì):

大模型注意力機(jī)制:MHA GQA MQA MLA理論與實(shí)踐-AI.x社區(qū)

4.3 理論優(yōu)勢(shì)與局限

  • 優(yōu)勢(shì):參數(shù)量(約為 MHA 的 42%)與 KV 緩存量(壓縮至 GQA 的 1/5~1/10)大幅降低,同時(shí)通過低秩分解保留關(guān)鍵特征,表達(dá)能力接近 MHA。
  • 局限:低秩投影與位置解耦增加了模型復(fù)雜度,實(shí)現(xiàn)難度高于前三種機(jī)制,且需針對(duì)性優(yōu)化矩陣合并(如 “吸收” 操作)以避免計(jì)算冗余。

五、四種機(jī)制的理論對(duì)比:從參數(shù)到能力的全面權(quán)衡

機(jī)制

核心創(chuàng)新

參數(shù)量(相對(duì)值)

KV 緩存量(相對(duì)值)

表達(dá)能力

適用場(chǎng)景

MHA

多頭并行

1.0

1.0

最強(qiáng)

預(yù)訓(xùn)練、高性能需求

MQA

全局共享 KV

0.56

1/num_heads

較弱

邊緣部署、高并發(fā)推理

GQA

分組共享 KV

0.75

num_groups/num_heads

較強(qiáng)

通用大模型、平衡需求

MLA

低秩壓縮 + 位置解耦

0.42

~0.1

強(qiáng)

長序列、大規(guī)模部署

六、實(shí)踐代碼實(shí)現(xiàn)

下面代碼來自:??https://mp.weixin.qq.com/s/j5J2qRCNDa7NTOHirx4kvA?? 侵刪

6.1 多頭注意力(MHA)實(shí)現(xiàn)

import torch
import torch.nn as nn


class MultiHeadAttention(nn.Module):
    def __init__(self, hidden_size, num_heads, dropout=0.0):
        super(MultiHeadAttention, self).__init__()
        assert hidden_size % num_heads == 0, "hidden_size 必須能被 num_heads 整除"


        self.hidden_size = hidden_size
        self.num_heads = num_heads
        self.head_dim = hidden_size // num_heads # 每個(gè)頭的維度


        # 定義Q、K、V的線性變換層
        self.query = nn.Linear(hidden_size, hidden_size)
        self.key = nn.Linear(hidden_size, hidden_size)
        self.value = nn.Linear(hidden_size, hidden_size)


        self.dropout = nn.Dropout(dropout)
        self.out_projection = nn.Linear(hidden_size, hidden_size)


    def forward(self, hidden_state, attention_mask=None):
        batch_size, seq_len, _ = hidden_state.size()


        # 生成Q、K、V
        query = self.query(hidden_state) # [batch_size, seq_len, hidden_size]
        key = self.key(hidden_state) # [batch_size, seq_len, hidden_size]
        value = self.value(hidden_state) # [batch_size, seq_len, hidden_size]


        # 拆分多頭
        # [batch_size, num_heads, seq_len, head_dim]
        query = query.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
        # [batch_size, num_heads, seq_len, head_dim]
        key = key.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
        # [batch_size, num_heads, seq_len, head_dim]
        value = value.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)


        # 計(jì)算注意力權(quán)重
        # [batch_size, num_heads, seq_len, seq_len]
        attention_weights = torch.matmul(query, key.transpose(-2, -1)) / (self.head_dim **0.5)


        # 應(yīng)用掩碼
        if attention_mask is not None:
            attention_weights = attention_weights.masked_fill(attention_mask[:, None, None, :] == 0, float('-inf'))


        # [batch_size, num_heads, seq_len, seq_len]
        attention_weights = torch.softmax(attention_weights, dim=-1)
        attention_weights = self.dropout(attention_weights)


        # 計(jì)算上下文向量
        context = torch.matmul(attention_weights, value)


        # 合并多頭 # [batch_size, seq_len, hidden_size]
        context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_size)


        # 輸出投影 # [batch_size, seq_len, hidden_size]
        output = self.out_projection(context)
        return output


# 示例用法
if __name__ == '__main__':
    batch_size = 2
    seq_len = 10
    hidden_size = 256
    num_heads = 8


    mha = MultiHeadAttention(hidden_size, num_heads)
    hidden_state = torch.randn(batch_size, seq_len, hidden_size)
    attention_mask = torch.ones(batch_size, seq_len)
    attention_mask[:, 5:] = 0  # 屏蔽后5個(gè)位置


    output = mha(hidden_state, attention_mask)
    print("MHA輸出形狀:", output.shape)  # torch.Size([2, 10, 256])

6.2 多查詢注意力(MQA)實(shí)現(xiàn)

import torch
import torch.nn as nn


class MultiQueryAttention(nn.Module):
    def __init__(self, hidden_size, num_heads, dropout=0.0):
        super(MultiQueryAttention, self).__init__()
        assert hidden_size % num_heads == 0, "hidden_size 必須能被 num_heads 整除"


        self.hidden_size = hidden_size
        self.num_heads = num_heads
        self.head_dim = hidden_size // num_heads


        # Q保持多頭獨(dú)立,K和V共享
        self.query = nn.Linear(hidden_size, hidden_size)
        self.key = nn.Linear(hidden_size, self.head_dim)
        self.value = nn.Linear(hidden_size, self.head_dim)


        self.dropout = nn.Dropout(dropout)
        self.out_projection = nn.Linear(hidden_size, hidden_size)


    def forward(self, hidden_state, attention_mask=None):
        batch_size, seq_len, _ = hidden_state.size()


        # 生成Q、K、V
        # [batch_size, seq_len, hidden_size]
        query = self.query(hidden_state)
        # [batch_size, seq_len, head_dim]
        key = self.key(hidden_state)
        # [batch_size, seq_len, head_dim]
        value = self.value(hidden_state)


        # 拆分Q為多頭
        # [batch_size, num_heads, seq_len, head_dim]
        query = query.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)


        # 擴(kuò)展K和V到多頭
        # [batch_size, num_heads, seq_len, head_dim]
        key = key.unsqueeze(1).expand(-1, self.num_heads, -1, -1)
        # [batch_size, num_heads, seq_len, head_dim]
        value = value.unsqueeze(1).expand(-1, self.num_heads, -1, -1)


        # 計(jì)算注意力權(quán)重 # [batch_size, num_heads, seq_len, seq_len]
        attention_weights = torch.matmul(query, key.transpose(-2, -1)) / (self.head_dim **0.5)


        # 應(yīng)用掩碼
        if attention_mask is not None:
            attention_weights = attention_weights.masked_fill(attention_mask[:, None, None, :] == 0, float('-inf'))


        # [batch_size, num_heads, seq_len, seq_len]
        attention_weights = torch.softmax(attention_weights, dim=-1)
        attention_weights = self.dropout(attention_weights)


        # 計(jì)算上下文向量
        # [batch_size, num_heads, seq_len, head_dim]
        context = torch.matmul(attention_weights, value)


        # 合并多頭 # [batch_size, seq_len, hidden_size]
        context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_size)


        # 輸出投影 # [batch_size, seq_len, hidden_size]
        output = self.out_projection(context)
        return output


# 示例用法
if __name__ == '__main__':
    batch_size = 2
    seq_len = 10
    hidden_size = 256
    num_heads = 8


    mqa = MultiQueryAttention(hidden_size, num_heads)
    hidden_state = torch.randn(batch_size, seq_len, hidden_size)
    attention_mask = torch.ones(batch_size, seq_len)
    attention_mask[:, 5:] = 0


    output = mqa(hidden_state, attention_mask)
    print("MQA輸出形狀:", output.shape)  # torch.Size([2, 10, 256])

6.3 分組查詢注意力(GQA)實(shí)現(xiàn)

import torch
import torch.nn as nn


class GroupedQueryAttention(nn.Module):
    def __init__(self, hidden_size, num_heads, group_size=2, dropout=0.0):
        super(GroupedQueryAttention, self).__init__()
        assert hidden_size % num_heads == 0, "hidden_size 必須能被 num_heads 整除"
        assert num_heads % group_size == 0, "num_heads 必須能被 group_size 整除"


        self.hidden_size = hidden_size
        self.num_heads = num_heads
        self.group_size = group_size
        self.group_num = num_heads // group_size
        self.head_dim = hidden_size // num_heads


        # Q保持多頭獨(dú)立,K和V按組共享
        self.query = nn.Linear(hidden_size, hidden_size)
        self.key = nn.Linear(hidden_size, self.group_num * self.head_dim)
        self.value = nn.Linear(hidden_size, self.group_num * self.head_dim)


        self.dropout = nn.Dropout(dropout)
        self.out_projection = nn.Linear(hidden_size, hidden_size)


    def forward(self, hidden_state, attention_mask=None):
        batch_size, seq_len, _ = hidden_state.size()


        # 生成Q、K、V
        # [batch_size, seq_len, hidden_size]
        query = self.query(hidden_state)
        # [batch_size, seq_len, group_num * head_dim]
        key = self.key(hidden_state)
        # [batch_size, seq_len, group_num * head_dim]
        value = self.value(hidden_state)


        # 拆分Q為多頭
        query = query.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)


        # 拆分K和V為組并擴(kuò)展到多頭 
        # [batch_size, group_num, seq_len, head_dim]
        key = key.view(batch_size, seq_len, self.group_num, self.head_dim).transpose(1, 2)
        # [batch_size, num_heads, seq_len, head_dim]
        key = key.unsqueeze(2).expand(-1, -1, self.group_size, -1, -1).contiguous().view(batch_size, -1, seq_len, self.head_dim)


        # [batch_size, group_num, seq_len, head_dim]
        value = value.view(batch_size, seq_len, self.group_num, self.head_dim).transpose(1, 2)
        # [batch_size, num_heads, seq_len, head_dim]
        value = value.unsqueeze(2).expand(-1, -1, self.group_size, -1, -1).contiguous().view(batch_size, -1, seq_len, self.head_dim)


        # 計(jì)算注意力權(quán)重
        attention_weights = torch.matmul(query, key.transpose(-2, -1)) / (self.head_dim **0.5)


        # 應(yīng)用掩碼
        if attention_mask is not None:
            attention_weights = attention_weights.masked_fill(attention_mask[:, None, None, :] == 0, float('-inf'))


        attention_weights = torch.softmax(attention_weights, dim=-1)
        attention_weights = self.dropout(attention_weights)


        # 計(jì)算上下文向量
        context = torch.matmul(attention_weights, value)


        # 合并多頭
        context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_size)


        # 輸出投影
        output = self.out_projection(context)
        return output


# 示例用法
if __name__ == '__main__':
    batch_size = 2
    seq_len = 10
    hidden_size = 256
    num_heads = 8
    group_size = 2  # 每組2個(gè)頭,共4組


    gqa = GroupedQueryAttention(hidden_size, num_heads, group_size)
    hidden_state = torch.randn(batch_size, seq_len, hidden_size)
    attention_mask = torch.ones(batch_size, seq_len)
    attention_mask[:, 5:] = 0


    output = gqa(hidden_state, attention_mask)
    print("GQA輸出形狀:", output.shape)  # torch.Size([2, 10, 256])

6.4 多頭潛在注意力(MLA)實(shí)現(xiàn)

import torch
import torch.nn as nn
import math


class RotaryEmbedding(nn.Module):
    def __init__(self, hidden_size, num_heads, base=10000, max_len=512):
        super().__init__()
        self.head_dim = hidden_size // num_heads
        self.hidden_size = hidden_size
        self.num_heads = num_heads
        self.base = base
        self.max_len = max_len
        self.cos_pos_cache, self.sin_pos_cache = self._compute_pos_emb()


    def _compute_pos_emb(self):
        theta_i = 1. / (self.base **(torch.arange(0, self.head_dim, 2).float() / self.head_dim))
        positions = torch.arange(self.max_len)
        pos_emb = positions.unsqueeze(1) * theta_i.unsqueeze(0)


        cos_pos = pos_emb.sin().repeat_interleave(2, dim=-1)
        sin_pos = pos_emb.cos().repeat_interleave(2, dim=-1)


        return cos_pos, sin_pos


    def forward(self, q):
        bs, seq_len = q.shape[0], q.shape[2]
        # [seq_len, head_dim]
        cos_pos = self.cos_pos_cache[:seq_len].to(q.device)
        # [seq_len, head_dim]
        sin_pos = self.sin_pos_cache[:seq_len].to(q.device)


        # [1, 1, seq_len, head_dim]
        cos_pos = cos_pos.unsqueeze(0).unsqueeze(0)
        # [1, 1, seq_len, head_dim]
        sin_pos = sin_pos.unsqueeze(0).unsqueeze(0)


        # RoPE變換
        q2 = torch.stack([-q[..., 1::2], q[..., ::2]], dim=-1)
        q2 = q2.reshape(q.shape).contiguous()


        return q * cos_pos + q2 * sin_pos


class MultiHeadLatentAttention(nn.Module):
    def __init__(self, hidden_size=256, down_dim=64, up_dim=128, num_heads=8, rope_head_dim=26, dropout_prob=0.0):
        super(MultiHeadLatentAttention, self).__init__()
        self.d_model = hidden_size
        self.down_dim = down_dim
        self.up_dim = up_dim
        self.num_heads = num_heads
        self.head_dim = hidden_size // num_heads
        self.rope_head_dim = rope_head_dim
        self.v_head_dim = up_dim // num_heads


        # 降維投影
        self.down_proj_kv = nn.Linear(hidden_size, down_dim)
        self.down_proj_q = nn.Linear(hidden_size, down_dim)


        # 升維投影
        self.up_proj_k = nn.Linear(down_dim, up_dim)
        self.up_proj_v = nn.Linear(down_dim, up_dim)
        self.up_proj_q = nn.Linear(down_dim, up_dim)


        # 解耦Q/K投影
        self.proj_qr = nn.Linear(down_dim, rope_head_dim * num_heads)
        self.proj_kr = nn.Linear(hidden_size, rope_head_dim)


        # RoPE位置編碼
        self.rope_q = RotaryEmbedding(rope_head_dim * num_heads, num_heads)
        self.rope_k = RotaryEmbedding(rope_head_dim, 1)


        # 輸出層
        self.dropout = nn.Dropout(dropout_prob)
        self.fc = nn.Linear(num_heads * self.v_head_dim, hidden_size)
        self.res_dropout = nn.Dropout(dropout_prob)


    def forward(self, h, mask=None):
        bs, seq_len, _ = h.size()


        # 低秩轉(zhuǎn)換
        # [bs, seq_len, down_dim]
        c_t_kv = self.down_proj_kv(h)
        # [bs, seq_len, up_dim]
        k_t_c = self.up_proj_k(c_t_kv)
        # [bs, seq_len, up_dim]
        v_t_c = self.up_proj_v(c_t_kv)
        # [bs, seq_len, down_dim]
        c_t_q = self.down_proj_q(h)
        # [bs, seq_len, up_dim]
        q_t_c = self.up_proj_q(c_t_q)


        # 解耦Q/K處理
        # [bs, seq_len, rope_head_dim*num_heads]
        q_t_r = self.proj_qr(c_t_q)
        # [bs, num_heads, seq_len, rope_head_dim]
        q_t_r = q_t_r.view(bs, seq_len, self.num_heads, self.rope_head_dim).transpose(1, 2)
        # RoPE投影處理
        q_t_r = self.rope_q(q_t_r)


        # [bs, seq_len, rope_head_dim]
        k_t_r = self.proj_kr(h)
        # [bs, 1, seq_len, rope_head_dim]
        k_t_r = k_t_r.unsqueeze(1)
        # 應(yīng)用RoPE編碼
        k_t_r = self.rope_k(k_t_r)


        # 注意力計(jì)算
        # [bs, num_heads, seq_len, up_dim/num_heads]
        q_t_c = q_t_c.view(bs, seq_len, self.num_heads, -1).transpose(1, 2)
        # [bs, num_heads, seq_len, (up_dim+rope_head_dim)/num_heads]
        q = torch.cat([q_t_c, q_t_r], dim=-1)


        # [bs, num_heads, seq_len, up_dim/num_heads]
        k_t_c = k_t_c.view(bs, seq_len, self.num_heads, -1).transpose(1, 2)
        # [bs, num_heads, seq_len, rope_head_dim]
        k_t_r = k_t_r.expand(bs, self.num_heads, seq_len, -1)
        # [bs, num_heads, seq_len, (up_dim+rope_head_dim)/num_heads]
        k = torch.cat([k_t_c, k_t_r], dim=-1)


        # [bs, num_heads, seq_len, seq_len]
        scores = torch.matmul(q, k.transpose(-1, -2))
        scores = scores / (math.sqrt(self.head_dim) + math.sqrt(self.rope_head_dim))


        if mask is not None:
            # [bs, num_heads, seq_len, seq_len]
            scores = scores.masked_fill(mask[:, None, None, :] == 0, float('-inf'))


        # [bs, num_heads, seq_len, seq_len]
        attn_weights = torch.softmax(scores, dim=-1)
        attn_weights = self.dropout(attn_weights)


        # V維度調(diào)整 # [bs, num_heads, seq_len, v_head_dim]
        v_t_c = v_t_c.view(bs, seq_len, self.num_heads, self.v_head_dim).transpose(1, 2)


        # 計(jì)算上下文向量
        # [bs, num_heads, seq_len, v_head_dim]
        context = torch.matmul(attn_weights, v_t_c)


        # 合并多頭 # [bs, seq_len, num_heads*v_head_dim]
        context = context.transpose(1, 2).contiguous().view(bs, seq_len, -1)


        # 輸出投影
        # [bs, seq_len, d_model]
        output = self.fc(context)
        output = self.res_dropout(output)


        return output


# 示例用法
if __name__ == '__main__':
    batch_size = 2
    seq_len = 10
    hidden_size = 256


    h = torch.randn(batch_size, seq_len, hidden_size)
    mla = MultiHeadLatentAttention(hidden_size=hidden_size)


    mask = torch.ones(batch_size, seq_len)
    mask[:, 5:] = 0


    output = mla(h, mask)
    print("MLA輸出形狀:", output.shape)  # torch.Size([2, 10, 256])

七、總結(jié)與建議

從 MHA 到 MLA 的演進(jìn),本質(zhì)是 “表達(dá)能力 - 計(jì)算效率” 的權(quán)衡藝術(shù):MHA 奠定了多頭并行的基礎(chǔ),MQA 與 GQA 通過參數(shù)共享優(yōu)化效率,MLA 則通過低秩分解與位置解耦實(shí)現(xiàn)了質(zhì)的突破。

四種注意力機(jī)制各有優(yōu)劣,在實(shí)際應(yīng)用中需根據(jù)具體場(chǎng)景選擇:

  • MHA:適用于對(duì)性能要求高、資源充足的場(chǎng)景,如預(yù)訓(xùn)練階段。
  • MQA:適用于資源受限、對(duì)推理速度要求高的場(chǎng)景,如邊緣設(shè)備部署。
  • GQA:大多數(shù)情況下的優(yōu)選,在性能與效率間取得平衡,適合通用大模型。
  • MLA:適用于長序列任務(wù)和大規(guī)模模型部署,在顯存有限的情況下表現(xiàn)出色。

隨著大模型向更大參數(shù)量、更長序列發(fā)展,注意力機(jī)制的優(yōu)化將持續(xù)推進(jìn)。開發(fā)者應(yīng)根據(jù)實(shí)際需求選擇合適的機(jī)制,并關(guān)注最新研究進(jìn)展,不斷提升模型的性能與效率。

參考文獻(xiàn)

  1. 宋志學(xué),《手撕大模型 Attention:MLA、MHA、MQA 與 GQA (含實(shí)現(xiàn)代碼)》,??https://mp.weixin.qq.com/s/j5J2qRCNDa7NTOHirx4kvA??,2025-05-20,微信公眾號(hào)
  2. 蘇劍林,《Transformer 升級(jí)之路:多頭潛在注意力機(jī)制 (MLA) 究竟好在哪里?》,??https://mp.weixin.qq.com/s/KdOjWF4n5gNtQxKKvkG5Mw??,2025-05-22,微信公眾號(hào)
  3. 姜富春,《DeepSeek 技術(shù)解讀 1: 徹底理解 MLA》,??https://mp.weixin.qq.com/s/yL_Z8zcAfWDcviZwApdL_w??,2025-01-15,微信公眾號(hào)
  4. 算法狗,《DeepSeek MLA: 高效推理的省錢之道,全流程剖析》,??https://mp.weixin.qq.com/s/yNxjgQMl2LKzpGOoCWRRcw??,2025-02-19,微信公眾號(hào)
  5. 羽說 AI 研究圈,《從 MHA→MQA→GQA→MLA》,??https://mp.weixin.qq.com/s/S9dfOCrWeru6zGjOjchV7Q??,2025-02-12,微信公眾號(hào)


本文轉(zhuǎn)載自??鴻煊的學(xué)習(xí)筆記??,作者:乘風(fēng)破浪jxj

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請(qǐng)注明出處,否則將追究法律責(zé)任
已于2025-7-17 14:14:47修改
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦
欧美成人国产精品高潮| 日日摸天天爽天天爽视频| 国产精品主播一区二区| 亚洲天堂一区二区三区四区| 欧美成人a视频| 久久无码高潮喷水| 午夜视频在线看| 国产精品一区二区在线观看不卡 | 欧美夫妻性生活| 日本黄大片在线观看| 蜜桃视频在线观看网站| 精品一区二区三区视频在线观看| 欧美精品激情blacked18| 自拍偷拍中文字幕| 久久精品免视看国产成人| 精品久久香蕉国产线看观看亚洲 | 好吊日视频在线观看| 国产1区2区3区精品美女| 国产99久久精品一区二区 夜夜躁日日躁| 欧美日韩生活片| 任你弄精品视频免费观看| 欧美日韩1234| 日韩欧美在线播放视频| av中文字幕在线观看| 91在线精品一区二区| 91九色视频导航| 免费的毛片视频| 国内精品美女在线观看| www.美女亚洲精品| 中文字幕一区二区三区人妻不卡| 国产成人视屏| 欧美性色黄大片手机版| 一二三四视频社区在线| 亚洲丝袜一区| 国产精品美女一区二区三区| 久久精品aaaaaa毛片| 亚洲国产精品久久久久爰性色| 日本人妖一区二区| 2019av中文字幕| 黄色片在线观看网站| 日韩欧美字幕| 亚洲人成电影网| 国产精品久久久免费观看| a看欧美黄色女同性恋| 91精品欧美久久久久久动漫| 视频二区在线播放| 欧美极品影院| 欧美日韩国产色| 欧美视频免费看欧美视频| 在线中文字幕视频观看| 亚洲欧洲精品一区二区精品久久久 | 日韩在线精品视频| 国内精品卡一卡二卡三| 亚洲bt欧美bt精品777| 亚洲国产精品成人精品| 日本人妻一区二区三区| 视频二区欧美毛片免费观看| 欧美一区二区三区免费| 久久精品一卡二卡| 国产日韩欧美中文在线| 日韩亚洲欧美在线| 久久久久无码国产精品一区李宗瑞| 精品国产一区二| 欧美zozo另类异族| 中文写幕一区二区三区免费观成熟| 成人网av.com/| 欧美一级二级三级蜜桃| 精品国产一二区| 高潮按摩久久久久久av免费| 亚洲国产成人精品电影| 中文字幕无码人妻少妇免费| 久久a级毛片毛片免费观看| 亚洲精品久久久久久久久久久久| 亚洲天堂资源在线| 日韩免费电影在线观看| 亚洲欧美国产精品专区久久 | 成人一级毛片| 最近2019中文免费高清视频观看www99 | 阿v天堂2018| 岛国av免费在线观看| 欧美日韩国产页| 久久久久狠狠高潮亚洲精品| 超薄肉色丝袜脚交一区二区| 欧美日韩一区二区三区视频| 中文字幕丰满乱码| 一区二区中文字幕在线观看| 精品欧美黑人一区二区三区| 免费看黄色aaaaaa 片| jlzzjlzz亚洲女人| 欧美老女人性生活| 国产精品久久久免费视频| 久久一二三四| 亚洲自拍另类欧美丝袜| 天天操天天舔天天干| 国产精品美女视频| 国产免费裸体视频| 欧美日韩不卡| 精品乱人伦小说| 免费看污片的网站| 国产专区一区| 国产精品爱啪在线线免费观看| 99久久精品无免国产免费| 成人av在线观| 一区二区视频在线播放| 国产黄色大片在线观看| 欧美日韩一区在线观看| 亚洲成年人av| 欧美残忍xxxx极端| 欧美一级成年大片在线观看| 在线观看免费视频一区| 99精品视频在线观看| 综合一区中文字幕| 欧美黑人一区| 精品国产免费一区二区三区四区 | 国产91在线播放精品91| 99视频免费看| 国产欧美一区二区三区沐欲| 隔壁人妻偷人bd中字| yiren22亚洲综合| 亚洲激情第一页| 男人操女人的视频网站| 久久亚洲综合| 国产在线播放一区二区| 26uuu亚洲电影在线观看| 色综合久久久久| xfplay5566色资源网站| 外国成人免费视频| 国产精品国语对白| 五月天激情开心网| 一二三四社区欧美黄| 亚洲一区二区三区四区五区| 国产精品免费99久久久| 久久久久成人网| 国产精品探花视频| 国产精品无人区| 国产精品亚洲αv天堂无码| 精品综合久久88少妇激情| 欧美床上激情在线观看| 一级全黄裸体免费视频| 国产日产欧产精品推荐色| 欧美 国产 综合| 欧美黑人巨大videos精品| 欧美精品在线免费播放| 国产毛片毛片毛片毛片| 中文字幕一区三区| 不卡av免费在线| 欧美三级伦理在线| 国产精品白嫩初高中害羞小美女| 欧美美女色图| 色婷婷久久99综合精品jk白丝| 亚洲成av人片在线观看无| 国产综合欧美| 狠狠色综合色区| 在线天堂资源| 亚洲无av在线中文字幕| 黄色av一级片| 国产欧美日韩一区二区三区在线观看| 青青在线视频观看| 国产日产精品_国产精品毛片| 国产成人精品av在线| 免费在线看v| 欧美天堂亚洲电影院在线播放| 阿v天堂2014| 美女视频一区在线观看| 一区二区三区偷拍| 国产在线不卡一区二区三区| 欧美猛交ⅹxxx乱大交视频| 精品国产乱码一区二区三| 亚洲国产中文字幕| a级在线观看视频| 三级不卡在线观看| 在线免费观看成人网| 玖玖精品一区| 午夜精品一区二区三区在线视| 天堂a√中文在线| 图片区小说区国产精品视频| 公侵犯人妻一区二区三区| 日本v片在线高清不卡在线观看| 手机看片福利永久国产日韩| 欧美风情在线视频| 欧美精品一区二区免费| 免费看av毛片| 91国内精品野花午夜精品| 91禁男男在线观看| 国产一区二区电影| 人妻激情另类乱人伦人妻| 大伊香蕉精品在线品播放| 欧美一区二区三区免费观看| 亚洲1卡2卡3卡4卡乱码精品| 日韩精品一区二区三区视频| 日韩综合在线观看| 亚洲免费在线视频一区 二区| 2一3sex性hd| 麻豆精品视频在线观看视频| 国产日韩欧美精品在线观看| 欧美日韩伦理在线免费| 国产91aaa| 国产精品黄色片| 欧美激情xxxx| 自拍视频在线网| 亚洲国产精品中文| 国产又粗又黄又爽的视频| 婷婷中文字幕综合| 久久国产高清视频| 久久婷婷久久一区二区三区| 日本少妇一区二区三区| 日韩成人一级大片| 久色视频在线播放| 伊人情人综合网| 日韩精品久久久毛片一区二区| 中文字幕一区二区三区中文字幕 | 日韩精品一区在线视频| 不卡中文字幕| 久久久久久一区| 精品一区二区三区四区五区| 国产成人免费av| 丝袜美腿av在线| 色综合伊人色综合网| 清纯唯美亚洲色图| 欧美大片在线观看一区| 在线观看国产成人| 色爱区综合激月婷婷| 日韩av一二三区| 亚洲女人****多毛耸耸8| 级毛片内射视频| 久久奇米777| 国产激情视频网站| 国产99久久久国产精品| av亚洲天堂网| 另类中文字幕网| 国产一级不卡毛片| 久久三级福利| 日韩av片在线看| 国产免费成人| 日日摸日日碰夜夜爽无码| 欧美国产三区| 国产精品88久久久久久妇女| 欧美freesextv| 色综合久久av| 国产探花在线精品| 欧美一区国产一区| 欧美丝袜足交| 国产一区免费观看| 麻豆一区二区| 久久国产精品亚洲va麻豆| 欧美自拍视频| 另类小说综合网| 中文字幕伦av一区二区邻居| 久久99精品国产一区二区三区| 欧美三级电影在线| 久久精彩视频| 国产中文字幕一区二区三区| 日本在线观看一区| 日韩成人a**站| 亚洲一区二区三区精品动漫| 91九色精品| 四虎4hu永久免费入口| 中文字幕免费一区二区三区| www婷婷av久久久影片| 欧美天天视频| 中文字幕日本最新乱码视频| 视频一区二区国产| 尤蜜粉嫩av国产一区二区三区| 日本成人超碰在线观看| 亚洲欧美久久久久| 国产美女精品在线| 中文字幕人妻熟女在线| 91在线免费视频观看| 干b视频在线观看| 中文字幕第一区第二区| 成人免费精品动漫网站| 亚洲国产日韩在线一区模特| 91浏览器在线观看| 欧美影院一区二区三区| 国产精品伦一区二区三区| 精品久久一区二区三区| 日本天堂影院在线视频| 日韩在线国产精品| 免费看电影在线| 日韩免费观看视频| 国产激情一区| 就去色蜜桃综合| 日韩黄色大片| 精品人妻人人做人人爽| 在线综合亚洲| 日本不卡一区在线| 成人午夜免费av| 制服 丝袜 综合 日韩 欧美| 亚洲人成7777| 久久国产视频播放| 在线91免费看| 日本中文字幕电影在线观看| www国产精品com| 自拍网站在线观看| 91九色对白| 精品国产精品国产偷麻豆| 视色,视色影院,视色影库,视色网| 99精品欧美| 午夜精品免费看| 99热精品国产| 欧美风情第一页| 欧美性色xo影院| 99在线观看免费| 亚洲天堂免费在线| 里番在线播放| 成人黄色网免费| 欧美人与物videos另类xxxxx| 国产精品视频一二三四区| 石原莉奈在线亚洲三区| 久久久久亚洲AV成人无码国产| 亚洲天堂成人在线观看| 中文字幕精品视频在线观看| 亚洲成成品网站| caopo在线| 国产狼人综合免费视频| 天堂网av成人| 亚洲高潮无码久久| 久久国产精品99久久久久久老狼| 性色av蜜臀av色欲av| 亚洲一卡二卡三卡四卡无卡久久 | 久草热8精品视频在线观看| av直播在线观看| 亚洲第一主播视频| 99久久婷婷国产一区二区三区| 国产亚洲欧洲黄色| 永久免费毛片在线播放| 国产精品久久久对白| 中文在线播放一区二区| 在线观看日本一区二区| 国产欧美一区二区三区在线老狼| 国产精品视频久久久久久久| 亚洲第一精品夜夜躁人人爽 | 亚洲国产成人av网| 精品毛片一区二区三区| 欧美成人自拍视频| 欧美电影在线观看一区| 最新中文字幕久久| 精品一区二区三区蜜桃| 国产免费一区二区三区网站免费| 欧美日韩亚洲精品内裤| 污视频在线免费观看| 国内自拍欧美激情| 欧美激情久久久久久久久久久| 日韩av在线播放不卡| 成人在线一区二区三区| 久久人人爽人人爽人人| 欧美精品色一区二区三区| 欧美激情黑人| 91精品网站| 亚洲国产裸拍裸体视频在线观看乱了中文 | av在线一区二区三区| 久久视频免费在线观看| 亚洲国产成人久久综合| 欧产日产国产精品视频| 欧美精品一区在线| 青青草成人在线观看| 国产精品无码在线| 日韩欧美在线视频日韩欧美在线视频| 你懂的在线视频| 国产精品国语对白| 99久久精品费精品国产风间由美| www.偷拍.com| 亚洲福中文字幕伊人影院| 婷婷丁香一区二区三区| 亲子乱一区二区三区电影 | 日韩精品三级| 国产精品久久久久7777| 2021国产精品久久精品| 欧美性受xxx黑人xyx性爽| 久久影院中文字幕| 激情小说亚洲图片| 欧美日韩在线免费播放| 中文字幕色av一区二区三区| 亚洲av无码一区二区三区dv| 91精品国产高清| 色乱码一区二区三区网站| 人妻av一区二区三区| 色婷婷av一区| 国产精品一区二区三区视频网站| 国产伦精品一区二区三区高清版| 国产精品女主播一区二区三区| 欧美熟妇激情一区二区三区| 日韩一区二区三区在线视频| 亚洲欧洲高清| 自拍偷拍一区二区三区| 99国产精品久久久久久久久久| 久久精品视频2| 欧美日韩国产二区| 国产一区二区三区91| 911av视频| 欧美日在线观看| 国产激情在线| 日本黄网免费一区二区精品| 国产成人av一区二区三区在线观看| 亚洲不卡视频在线观看| 九色精品免费永久在线| 日韩一区二区三区免费播放| 欧产日产国产精品98| 678五月天丁香亚洲综合网| 中国色在线日|韩|