Files
llm-atlas/research/DEEPSEEK_V2_LITE_TRACE.md
2026-07-29 14:18:45 +08:00

13 KiB
Raw Permalink Blame History

DeepSeek-V2-Lite 真实权重执行审计

状态:DeepSeek 专题第三轮工件;2026-07-29
目的:把“MLA 会压缩缓存”“MoE 会选择专家”从论文概念推进到固定官方权重、真实 tokenizer、真实 hidden states 和逐 token 路由记录。
边界:这不是完整模型 benchmark、训练 trace、生产服务复现、专家语义分析或总体负载估计。

0. 一页结论

这次实验固定官方 deepseek-ai/DeepSeek-V2-Lite revision 604d5664dddd88a0433dbae533b7fe9472482de0,使用官方 tokenizer、配置、模型代码和 BF16 checkpoint 第一分片,在 RTX 5090 上依次执行 embedding 与 decoder layer 0–6。 第 0 层是 dense FFN,第 1–6 层是完整 MoE 层;第 7 层横跨第一、第二分片,因此明确停止。

四条最重要的结果:

  1. 4 条人工固定 prompt 共 90 个有效 token,在 6 个 MoE 层产生 6 layers × 90 tokens × top-6 = 3,240 次真实 routed-expert 选择。
  2. 每个执行层都实际观测到 MLA 的 [B,T,576] 压缩投影;其中 512 是 KV latent,64 是 decoupled RoPE key。
  3. 官方 Hugging Face eager 实现仍把 cache 物化为 key [4,16,27,192] 和 value [4,16,27,128]。以 BF16 计, 每 token、每层是 10,240 bytes;按配置保存 latent + RoPE key 只需 1,152 bytes, 相差 8.8889×,后者相对前者减少 88.75%。
  4. 两次独立执行的来源、配置、tokenization、hidden-state hashes、MLA shapes、 aggregate loads 与全部 token routes 共 31/31 项完全一致;计时明确不参与一致性检查。

这里最反直觉的发现不是某个“神奇专家”,而是:

  • 覆盖不等于均衡。 90 个 token 在单层可触达 60–64/64 个专家,但各层 CV 为 0.549–0.925,Gini 为 0.303–0.420。
  • 路由 ID 不等于语义标签。 E8 只表示某一层内部数组的第 8 号专家;跨层的 E8 是不同参数,四条 prompt 也不足以赋予“代码专家”等语义。
  • 算法压缩不等于实现已经压缩存储。 MLA 的低秩状态合同与 HF eager cache 的实际物化格式是两张账,必须同时报告。

1. 证据身份

1.1 官方工件

工件 固定值
Hugging Face model deepseek-ai/DeepSeek-V2-Lite
revision 604d5664dddd88a0433dbae533b7fe9472482de0
checkpoint tensor bytes 31,412,968,448,约 29.261 GiB
shard 1 bytes 8,594,887,408,约 8.005 GiB
config SHA-256 f346286b0f1c8b044252fd54cb4fa78b9fab6472a6e8bebb9edfe03d414ea03d
modeling code SHA-256 7d8e5221095286eea991137760893fd7ba52727c0b4ebf48ec09e8bc56b45b9c
tokenizer SHA-256 41f3bf64213da8c012d8bd0871a58a1fdf70463e8f08f110ddbb1082f529f669
index SHA-256 d2cdb2f325f6682cf3ad1ad2526a9f979d857390b579380c0331d975136e0acf
shard 1 SHA-256 0d7e9f39bde40111a4c0f390b87497dce4565cf578d916395e6b2c7851f1e8da

第一分片完整容纳 embedding、layer 0–6 和 layer 7 的一部分。为了不把缺参数的 layer 7 冒充完整执行,本实验把证据边界钉在 layer 6。

原始 checkpoint 分片不进入 Git;仓库只提交:

  • 可复现执行脚本;
  • 机器可读 trace;
  • 独立复跑比较结果;
  • 研究审计与网页可视化。

1.2 模型配置

对象 官方配置
reported total / active 15.7B / 2.4B
decoder layers 27
hidden size 2048
attention heads 16
qk NoPE / RoPE head dim 128 / 64
value head dim 128
KV LoRA rank 512
routed experts / active 64 / 6
shared experts 2
expert intermediate 1408
dense prefix 1 layer
router softmax + greedy top-k
selected top-k normalization false

max_position_embeddings=163840 与 YaRN 配置属于 checkpoint config; 官方发布表中的上下文口径不应被本实验自行改写成同一个数字。

1.3 软件与硬件

对象 值
GPU NVIDIA GeForce RTX 5090,32,607 MiB
driver 595.84
Python 3.10.14
PyTorch 2.11.0+cu128
CUDA runtime 12.8
Transformers 4.41.2
safetensors 0.8.0
TF32 matmul disabled

官方 2024 remote code 在当前 Transformers 5.5 环境中会因已移除的 is_torch_fx_available 入口而导入失败。因此实验使用隔离的 Transformers 4.41.2。 模型源码保持只读、不打补丁;runner 只通过本地 package 方式导入官方 configuration_deepseek.py 与 modeling_deepseek.py。

这条版本边界很重要:“模型代码公开”不等于“任意未来依赖版本都可直接运行”。

2. 实验设计

2.1 为什么选择截断的精确 forward

完整 15.7B BF16 权重与运行时状态虽然可能勉强接近单卡边界,但没有必要为了观察 前六层真实路由而把“全模型能否高效生成”混进同一实验。本 runner:

  1. 用官方 tokenizer 一次编码 4 条 prompt;
  2. 从第一分片读取官方 embedding;
  3. 每次在 meta device 构造一个官方 decoder layer;
  4. 为这一层绑定真实 safetensors 参数并传到 GPU;
  5. 用上层输出作为下一层输入;
  6. 通过 hook 捕获实际 kv_a_proj_with_mqa 与实际 MoE gate 输出;
  7. 释放当前层,再加载下一层。

因此得到的是真实权重、真实层类、真实连续 hidden states,而不是随机初始化、 只读 config 或合成 router;但它仍不是完整 27 层生成。

2.2 固定 prompt

ID 标签 token
zh_explanation 中文解释 26
en_architecture English architecture 18
code Python code 19
math 数学推理 27

batch padding 后形状为 B=4, T=27,有效 token 共 90。prompt 是用于建立可复现 探针的人工样本,不是自然语料分布、benchmark 数据集或统计代表样本。

3. MLA:一张算法状态账,一张实现物化账

3.1 实际观测

每个执行层的 kv_a_proj_with_mqa 输出都是:

[batch, sequence, kv_lora_rank + qk_rope_head_dim]
= [4, 27, 512 + 64]
= [4, 27, 576]

这 576 个元素可以分为:

  • c_t^KV:512 维 joint latent;
  • k_t^R:64 维 decoupled RoPE key。

后者不能因为体积小就从缓存公式中消失。

3.2 HF eager 实际保存了什么

本次 use_cache=True 的官方 Hugging Face eager 路径实际返回:

key   [4, 16, 27, 192]
value [4, 16, 27, 128]

所以每 token、每层的缓存元素是:

expanded eager = 16 × (192 + 128) = 5,120 elements
latent contract = 512 + 64 = 576 elements

在 BF16 下:

eager bytes  = 5,120 × 2 = 10,240
latent bytes =   576 × 2 =  1,152
ratio        = 10,240 / 1,152 = 8.8889×
reduction    = 1 - 1,152 / 10,240 = 88.75%

3.3 为什么这不是论文 93.3% 的复跑

V2 报告的 93.3% 是完整 V2 相对 DeepSeek 67B、在论文指定配置和比较口径下的 作者报告结果。本实验的 88.75% 是 V2-Lite 配置中:

  • HF eager 展开 K/V 元素;
  • 与 latent + RoPE key 理论存储元素;

之间的逐 token、逐层 BF16 算术比较。模型、维度、基线和实现口径都不同, 二者不能互相替代。

进一步说,低秩架构只定义“可以保存什么最小状态”;生产系统是否真的只保存 latent, 还取决于 attention kernel、权重吸收、RoPE 分叉、paged cache 和服务框架。

4. MoE:真实路由显微镜

4.1 总量守恒

每个 MoE 层都满足:

90 valid tokens × top-6 = 540 routed selections

6 个层合计 3,240 次。两条 shared expert 等价路径始终运行,但它们不属于 router 输出的 0–63 routed expert ID,因此不写进 top-6 列表。

4.2 六层聚合负载

layer selections used / 64 zero CV Gini effective experts top expert
1 540 63 1 0.925 0.420 46.66 E8 · 48
2 540 64 0 0.549 0.303 55.08 E62 · 23
3 540 62 2 0.569 0.322 53.51 E54 · 19
4 540 62 2 0.866 0.417 47.03 E48 · 40
5 540 60 4 0.642 0.332 52.14 E14 · 32
6 540 61 3 0.765 0.378 49.48 E25 · 40

三个指标回答不同问题:

  • used experts:这批 token 是否至少触达某专家一次;
  • CV = std / mean:计数离散程度;
  • effective experts = exp(entropy):若把当前熵换算成均匀分布,相当于多少个专家。

因此 layer 1 触达 63 个专家,却只有 46.66 个 effective experts,且 E8 承担 48/540 次选择。只报“63/64 被使用”会掩盖负载长尾。

4.3 prompt 之间看到的差异

同一层内,四条 prompt 的 used-expert set Jaccard 与 CV 会变化。例如:

  • layer 1:中文 prompt 使用 54 个专家、CV 0.898;英文架构 prompt 使用 40 个、 CV 1.360;代码 prompt 44 个、CV 1.263;数学 prompt 45 个、CV 1.184。
  • layer 4:聚合 top expert 是 E48;英文和代码各把 E48 路由 11 次, 中文 prompt 的 top expert 却是 E29、16 次。
  • layer 6:英文 prompt 使用 42 个专家、CV 1.439;中文为 49 个、1.031; 数学为 48 个、0.915。

这些是描述性 route traces,说明 token 与上下文确实改变 gate 输出;它们不证明 “E48 是代码专家”,更不允许以四条 prompt 推断训练语料上的领域分工。

4.4 top-6 权重没有重新归一

配置 norm_topk_prob=false。router 先对 64 个专家做 softmax,再选 top-6; 被选中的 6 个概率不会重新缩放到和为 1。各层选中权重和的均值:

layer mean selected top-6 weight sum
1 0.3949
2 0.4801
3 0.4898
4 0.4749
5 0.4832
6 0.4440

所以网页显示某 token 的六个权重和小于 1 是真实配置行为,不是漏算。

5. 可复现性闸门

正式 trace:

src/data/deepseek-v2-lite-trace.json
SHA-256 81ff4ab34d20121fe42219c566dd4780f4c7f74252a31b596f90e5280e1f1aef
captured 2026-07-29T05:55:35.599912+00:00

第二次独立执行:

SHA-256 b5e2e7567e17765195313473499522a4529b9d37ea96963ba2b9455c3c0b86e6
captured 2026-07-29T05:56:32.527770+00:00

比较结果:

31 / 31 exact
timing compared: false

精确检查覆盖:

  • provenance、configuration、prompt tokenization;
  • initial / final hidden hashes;
  • layer 0–6 hidden hashes 与 MLA shapes;
  • layer 1–6 aggregate loads;
  • layer 1–6 全部 token routes。

计时会受首次 kernel、频率、温度、后台进程与同步位置影响,因此没有伪装成 deterministic evidence。本轮只把计时保留在原始 trace,网站不把它包装成性能 benchmark。

6. 绝对禁止的外推

本实验能够说 本实验不能说
固定 revision 的前 7 层产生了这些 hidden states 完整模型会生成什么回答
四条 prompt 在 6 层产生这些 top-6 routes 训练集或线上请求的总体专家负载
某层某 expert ID 被选中多少次 该专家具有什么稳定语义
HF eager 物化了展开 K/V 所有 MLA serving kernel 都这样缓存
V2-Lite 配置可导出 576 元素 latent state 完整 V2 的 93.3% 已被复跑
两次相同环境执行 31/31 exact 跨 GPU、依赖版本和 kernel 仍 bitwise identical
layer 0–6 在第一分片内完整 layer 7 或 layer 8–26 已执行

跨层连线也被禁止:layer 1 的 E8 与 layer 2 的 E8 是不同参数对象。可视化只能在同一层内 比较 expert load,不能画一条 “E8 专长” 纵贯 6 层。

7. 复现入口

环境与命令见:

  • experiments/deepseek/README.md
  • experiments/deepseek/v2_lite_trace.py
  • experiments/deepseek/compare_v2_lite_traces.py

执行一次:

python experiments/deepseek/v2_lite_trace.py \
  --artifact-dir /path/to/deepseek-v2-lite \
  --output /path/to/trace.json

比较两次:

python experiments/deepseek/compare_v2_lite_traces.py \
  --first /path/to/trace-1.json \
  --second /path/to/trace-2.json \
  --output /path/to/repro.json

8. 下一道研究闸门

本轮已经把 DeepSeek 第三轮从“计划真实 trace”推进到真实 tokenizer、MLA state、 MoE routes 与确定性复跑,但仍有四块未闭合:

  1. 用真正只保存 latent 的 MLA kernel 对照 HF eager materialization;
  2. 扩大公开语料样本,给 aggregate load 置信区间,并考察 batch / padding / sequence 对 expert parallel 的影响;
  3. 复跑 FP8、pipeline 或通信 trace,而不是继续用教学 schedule;
  4. 做可审计的 R1-like 小模型训练实验,记录 rollout、reward、KL、长度与梯度统计。

在这些闸门完成之前,DeepSeek 专题保持“第三轮进行中”,不写成完整独立复现。