8. DeepSeek-V3(V2)详读 2(架构 + MLA)

DeepSeek-V3(V2)详读 2 (架构 + MLA)

这个部分是讲 架构 + MLA 的内容,补充了一些在 DeepSeek-V2 的内容,Attention,Multi-head Attention,softmax,KV cache,比较不同注意力变种(MHA, GQA, MQA, MLA)的 KV cache差异,RoPE,Decoupled RoPE。

2. 架构

DeepSeek‑V3 采用多头潜在注意力(MLA)提升推理效率,结合 DeepSeekMoE 降低训练成本,并引入多令牌预测(MTP)训练目标,整体性能进一步提升。其余细节基本延续自 V2。


主要讲3个东西

  • MLA (多头潜在注意力:在推理方面资源减少)
  • DeepSeekMoE (MoE架构:在整个架构上的设计,瞄准在training)
  • MTP (多Token预测:增强模型性能)

图2来自DeepSeek-V2,学术上严禁复用,属于学术摽窃,即使是自己的

图2,DeepSeek主要的改进就是

  • Feed forword层:使用MoE 架构
  • Attention层:使用MLA 架构。

2.1 基础架构

基础上仍采用 Transformer 框架,同时集成 MLA 和 DeepSeekMoE,实现高效推理与经济训练。新版本还加入无辅助损失的负载均衡策略,减少性能损失。


先补充一些 Deepseek-V2 就提及的内容:

  • Attention: Intuitive understanding 可以说是做 Inner Product 来衡量相似度,虽然有时被类比为 correlation,二者数值和含义都不同,只是直觉上都在做“相似度”比较,但数学上不是一回事
  • Multi-head Attention: 把输入向量分割成多个子空间(heads),每个 head 独立计算 attention,再把所有的结果拼接起来,从而让模型可以在不同“子视角”下关注不同的信息,提升表达能力。
  • Softmax: 就是做归一化attention scores(即 QKT 结果),方便用来加权平均 Value(V),方便在同一个 scale 上面可以做比较。

  • KV cache:

    • top-down:GPT 这类 LLM 属于 Decoder-only 架构,是典型的自回归模型。在推理/生成时,每次只生成一个 token,生成 n 个 token 需要迭代 n 次,每次的输入序列都包含之前所有已生成的 token。这种方式每次都要重复计算前面所有 token 的 Key、Value,产生大量冗余计算,而 KV cache 的本质:就是“用空间换时间”,将前面的 K/V 存起来,下次直接复用,提升推理速度。
      • <s> → 【LLM】 → 欢
      • <s> 欢 → 【LLM】 → 迎
      • <s> 欢 迎 → 【LLM】 → 来
  • 没有 KV cache 的情况下(存在冗余):

    • LLM每次都完整重新算一遍 self-attention,每步都对历史的K、V重复运算。Step 1:y1=softmax(Q1K1Tdk)V1Step 2:y2=softmax(Q2[K1,K2]Tdk)[V1,V2]Step 3:y3=softmax(Q3[K1,K2,K3]Tdk)[V1,V2,V3]
    • 可以看到,前面的 K1K2 …会被多次重复计算,这就是“冗余”。
    • 灰色部分(被 mask)用 填充,softmax 后输出为 0,防止未来 token “偷看”。
    • 参考图:

  • 有 KV cache 的情况下:
    • 只计算当前步的 KnVn,其余历史 K<nV<n 直接从 cache 取,concatenate拼接即可,极大减少重复算力消耗(注意只cache K/V,不cache Q)。
    • 对比如下图,紫色部分表示复用 cache:
    • 缺点:KV cache 需要存下每步的 K/V,推理到后面序列变长时,对 GPU 显存压力会很大。常用优化有:
      1. 量化 KV,降低精度以减少存储(如 INT4/INT8 quantization)
      2. 裁剪、压缩历史 KV(如 Deepseek V2,定期只保留部分 KV)通过减少输入,来减少它cache的数据。

GPT-2代码实现 KV cache 合并(核心片段)

1
2
3
4
5
6
7
8
9
10
# 如果layer_past被缓存过,就提取出来和当前 K,V 合并(按序列长度 dim=-2 拼接)
if layer_past is not None:
past_key, past_value = layer_past
key_states = torch.cat((past_key, key_states), dim=-2)
value_states = torch.cat((past_value, value_states), dim=-2)
# 如果使用了cache就把K,V存一下
if use_cache is True:
present = (key_states,value_states)
else:
present = None

2.1.1 多头潜在注意力(Multi-Head Latent Attention,MLA)

对于注意力机制,DeepSeek-V3 采用了 MLA 架构。设 d 表示嵌入维度,nh 表示注意力头的数量,dh 表示每个头的维度,htRd 表示第 t 个 token 在某一注意力层的输入。MLA 的核心在于使用低秩联合压缩来对注意力的 Key 和 Value 进行压缩,以减少推理时 Key-Value (KV) 缓存的大小:

(1)ctKV=WDKVht(2)[kt,1C,kt,2C,...,kt,nhC]=ktC=WUKctKV(3)ktR=RoPE(WKRht)(4)kt,i=[kt,iC;ktR](5)[vt,1C,vt,2C,...,vt,nhC]=vtC=WUVctKV

其中,ctKVRdc 是对 Key 和 Value 进行联合压缩后的潜在向量,dcdhnh 表示 KV 压缩后的维度;

  • WDKVRdc×d 是降维投影矩阵;
  • WUK,WUVRdhnh×dc 是 Key 和 Value 的升维矩阵;
  • WKRRdR×d 用于生成带有旋转位置嵌入(RoPE)的 Key 向量;
  • RoPE(·) 表示应用 RoPE 矩阵的操作;
  • [;] 表示拼接。

注意:对于 MLA,只需要缓存蓝色框出的 ctKVktR,从而极大减少了生成时 KV 缓存的存储量,同时性能与标准多头注意力机制相当。

对注意力查询(Query)同样采用低秩压缩,从而减少训练时的激活内存占用:

(6)ctQ=WDQht(7)[qt,1C;qt,2C;;qt,nhC]=qtC=WUQctQ(8)[qt,1R;qt,2R;;qt,nhR]=qtR=ROPE(WQRctQ)(9)qt,i=[qt,iC;qt,iR]

其中,ctQRdc 是 Query 的压缩潜在向量,dc(dhnh) 表示查询压缩维度;WDQRdc×dWUQRdhnh×dc 分别为 Query 的降投影和升投影矩阵;WQRRdhRnh×dc 用于生成带有 RoPE 的解耦查询。

最终,注意力的查询(qt,i)、键(kj,i)和值(vj,iC)被组合,得到最终的注意力输出 ut

(10)ot,i=j=1tSoftmaxj(qt,iTkj,idh+dhR)vj,iC(11)ut=WO[ot,1;ot,2;...;ot,nh]

其中 WORd×dhnh 表示输出投影矩阵。


Deepseek-V2 作者比较了不同注意力变种(MHA, GQA, MQA, MLA)的 KV 缓存差异:

  • MHA:所有 head 都有独立的 K/V,推理时需要cache全部,显存开销最大。
  • GQA:多个 Q head 共享一组 K/V,可减少 cache 大小。
  • MQA:所有 Q head 共享同一组 K/V,极端方法 cache 最小化。
  • MLA:将所有的 K/V 用线性变换映射到低维 latent space,推理时只需缓存这个 latent 向量 ctKV,大幅减少 KV 缓存的存储量。
    • 这种结构类似 autoencoder 的 bottle-neck:将高维输入(K/V)压缩到低维 latent 表示,再按需升维还原。
    • 类似 stable diffusion、DiT 等大模型中的 latent trick:例如把一个高分辨率图像先 encode 到 latent space,再在低维空间做计算,最后 decode 回原始尺寸,既快又省显存。

KV 的压缩与重建过程,参考式子 (1, 2, 5):

  • MLA 的流程如下:
    1. 首先对输入 ht 进行线性投影降维:ctKV=WDKVht
    2. 然后通过升维矩阵 WUK,WUV 重建出各 head 的 K/V 表示:
      • [kt,1C,...,kt,nhC]=WUKctKV
      • [vt,1C,...,vt,nhC]=WUVctKV
    3. 位置信息通过旋转位置编码(RoPE)动态注入 Key:
      • ktR=RoPE(WKRht)
      • 最终 Key:kt,i=[kt,iC;ktR]
  • 推理时,只需缓存框出的 ctKVktR,其余部分可以按需即时计算,降低缓存成本。
  • 注意:WUK, WUV 是实际存在的矩阵,用于“延迟计算”,而不是被吸收到其他矩阵或完全省略。

关于缓存优化和计算 trick:

  • 传统 attention 要 cache 每个 step 的完整 K/V:kt,i,vt,i
  • MLA 中,推理时只需要 cache:
    • ctKV:用于还原出所有 head 的 kCvC
    • ktR:用于位置信息的旋转编码
  • 实际上,K/V 的升维矩阵并没有被省略,而是在解码过程中即时使用(不是预计算好的)
  • 进一步优化时的数学 trick:
    • 以前 attention 要先重建出 kC 再跟 q 做点积,现在作者发现可以直接“跳过还原这一步”。
    • 推理思路是这样的:
    qTkC=(WQh)T(WUKcKV)=hT(WQ)TWUKcKV=hTWcKV
    • 这就等于少存一个 kC,少算一步升维,注意力得分直接用 latent 向量计算,显存和算力都省。
    • 类似的 trick 也适用于 vC
    • 本质是:在数学结构允许的前提下,提前合并多个线性层,跳过中间变量生成,直接上结果。

现在来讲 Decoupled Rotary Position Embedding(RoPE 解耦版)

Position Embedding(PE)分类the cat is chasing another cat

  • Absolute PE(绝对位置)
    - 给每个 token 一个固定位置编号,例如:[0, 1, 2, 3, 4, 5]
    - 缺点:在训练时序列较短的情况下能很好工作,但在 inference 时序列长度变长时会出现泛化问题,因为位置编码(PE)的维度不再对齐。
  • Relative PE(相对位置)
    - 以当前 token 为锚点,相对位置:[-1, 0, 1, 2, 3, 4]
    - 更关注的是“相对谁”,具备更好的泛化能力,但计算更复杂

RoPE 位置旋转编码 = Absolute + Relative

  • RoPE** 使用二维旋转的方式将绝对位置相对位置同时编码到 Q、K 向量中。
  • 向量角度 = 相对位置,长度 = 绝对位置
  • 图解总结:
    • Absolute PE:同一个词(如 “cat”)在不同位置的向量具有相同的方向,但长度不同
    • Relative PE:方向会根据不同的相对位置发生变化,但长度保持一致
    • RoPE:两者结合,既有角度差异又统一长度,编码更合理

数学上怎么做的?

  • 传统 Attention:attn=qTk
  • RoPE 中是先将 Q 和 K 都加上旋转矩阵:attn=(Rqq)T(Rkk)=qTRqTRkk=qTRk
  • 合成矩阵 R=RqTRk,是 RoPE 的核心:
    • 说的是如何从「绝对位置」编码出「相对位置」的
    • 是一个跟位置差有关的旋转矩阵,也就是说它其实就是 encode「相对位置」的信息;
    • 所以虽然 RqRk​ 是基于「absolute PE」生成的,但最终的 R 就是 encode 「relative PE」 的方式。
  • 注意:不同位置的 Q/K 有不同的旋转矩阵,Key 的旋转会随着 token 推进不断变化;所以,RoPE 下的 K 是无法 cache 的!

RoPE 的问题:打破了数学 trick

  • 之前我们说过 MLA 的优化 trick 是:qTkC=hT(WQ)TWUKcKV
  • 但用了 RoPE 后,K 前面多了一个旋转矩阵 Rattn=qTRWUKcKV=hT(WQ)TRWUKcKV
  • 这时候 R 是跟位置相关的,而两个 W 是位置无关的
  • 所以这个 R 没法提前吸收到 (WQ)TWUK 中去,优化就失败了
  • 也因此:RoPE 无法使用之前省计算图的数学简化公式,做 inference 的时候就得在把k 重新算一遍。

解决:用 Decoupled RoPE 把 RoPE 拆到另一个分支里单独算,然后再拼回来

  • Query 分为两部分(公式 6-9):
    • qC:是从 latent vector 来的,没有加 RoPE,方便优化
    • qR:是从另一个分支生成的,专门为了加 RoPE
    • 最终:qt,i=[qt,iC;qt,iR] → 拼起来
  • Key 同理(公式 1-4):
    • kC 从 latent cKV 变换来
    • kR 是直接从 ht 来,用 RoPE 编码
    • 最终:kt,i=[kt,iC;ktR] → 拼起来

可以看图2 中MLA部分:

  • 左侧是 Q 路径:qC, qR → concatenate
  • 右侧是 K 路径:kC, kR → concatenate
  • 推理时,只缓存了 cKVkR,节省空间
  • 中间的 RoPE 操作是即时应用在 kRqR 上的

参考资料


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

8. DeepSeek-V3(V2)详读 2(架构 + MLA)
http://neurowave.tech/2025/06/21/11-8.2-Deepseek-V3/
作者
Artin Tan
发布于
2025年6月21日
更新于
2025年8月16日