13 KiB
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 层横跨第一、第二分片,因此明确停止。
四条最重要的结果:
- 4 条人工固定 prompt 共 90 个有效 token,在 6 个 MoE 层产生
6 layers × 90 tokens × top-6 = 3,240次真实 routed-expert 选择。 - 每个执行层都实际观测到 MLA 的
[B,T,576]压缩投影;其中 512 是 KV latent,64 是 decoupled RoPE key。 - 官方 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%。 - 两次独立执行的来源、配置、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:
- 用官方 tokenizer 一次编码 4 条 prompt;
- 从第一分片读取官方 embedding;
- 每次在 meta device 构造一个官方 decoder layer;
- 为这一层绑定真实 safetensors 参数并传到 GPU;
- 用上层输出作为下一层输入;
- 通过 hook 捕获实际
kv_a_proj_with_mqa与实际 MoE gate 输出; - 释放当前层,再加载下一层。
因此得到的是真实权重、真实层类、真实连续 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.mdexperiments/deepseek/v2_lite_trace.pyexperiments/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 与确定性复跑,但仍有四块未闭合:
- 用真正只保存 latent 的 MLA kernel 对照 HF eager materialization;
- 扩大公开语料样本,给 aggregate load 置信区间,并考察 batch / padding / sequence 对 expert parallel 的影响;
- 复跑 FP8、pipeline 或通信 trace,而不是继续用教学 schedule;
- 做可审计的 R1-like 小模型训练实验,记录 rollout、reward、KL、长度与梯度统计。
在这些闸门完成之前,DeepSeek 专题保持“第三轮进行中”,不写成完整独立复现。