feat: add bootstrapped DeepSeek routing corpus

This commit is contained in:
wuyang
2026-07-29 15:32:03 +08:00
parent b7fef2350f
commit 5bcfd58452
12 changed files with 158485 additions and 32 deletions
+386
View File
@@ -0,0 +1,386 @@
# DeepSeek-V2-Lite 多域路由语料审计
> 状态:第三轮真实权重执行 / 固定公开语料 / prompt-level bootstrap
> 捕获时间:2026-07-29T07:45:00+00:00
> 证据身份:X(本机真实执行)+ O(官方工件)+ S(统计摘要)
> 输出:
> `src/data/deepseek-v2-lite-routing-corpus.json` 与独立重跑
> `src/data/deepseek-v2-lite-routing-corpus-repro.json`
## 1. 这轮到底补了什么
上一轮 `v2_lite_trace.py` 的任务是做“显微镜”:4 条手写 prompt、90 个有效
token,逐 token 保存 top-6 expert ID 与 gate weight。它适合解释 router 实际输出
什么,却不适合回答“换一批文本,这个现象还在不在”。
本轮把问题改成:
1. 固定四种可公开重建的文本域;
2. 每域固定 32 条,共 128 条 prompt;
3. 对官方 DeepSeek-V2-Lite 的 embedding 与 layer 0–6 做连续 BF16 forward;
4. 在 layer 1–6 捕获每个有效 token 的真实 top-6 routed-expert ID;
5. 先聚合到 prompt,再以 prompt 为单位做 2,000 次分层 bootstrap;
6. 同时报告点估计、95% 区间、两种聚合口径和明确停止线。
正式运行包含:
| 数量 | 值 |
| --- | ---: |
| prompt | 128 |
| 有效 token | 8,460 |
| 每个 MoE 层的 routed-expert 选择 | 50,760 |
| 实测 MoE 层 | 6 |
| routed-expert 选择总数 | **304,560** |
| routed experts / layer | 64 |
| active routed experts / token | 6 |
| bootstrap replicates | 2,000 |
这里的 304,560 是 `8,460 tokens × top-6 × 6 MoE layers`,不是模型参数量、
训练 token 数或线上请求量。
## 2. 语料合同
### 2.1 四个公开来源
| 域 | 公开来源 | 只使用的字段 | 固定 revision / 文件 SHA-256 |
| --- | --- | --- | --- |
| 英文百科 | [Salesforce WikiText-2 raw validation](https://huggingface.co/datasets/Salesforce/wikitext/tree/b08601e04326c79dfdd32d625aee71d232d685c3/wikitext-2-raw-v1) | `text` | revision `b08601e…685c3`; parquet `204929b7…11c4c` |
| 中文新闻 | [CLUE TNEWS](https://github.com/CLUEbenchmark/CLUE/tree/9e61ddd3659ddb57ed82b4d0ba0a8613dfb55a2e) | `sentence` | repo `9e61ddd…55a2e`; archive `77c476e7…33462`; test `74f19932…a0ca8` |
| Python 代码 | [OpenAI HumanEval](https://github.com/openai/human-eval/tree/6d43fb980f9fee3c892a914eda09951f772ad10d) | `prompt` | revision `6d43fb9…ad10d`; gzip `b796127e…979ef` |
| 小学数学 | [OpenAI GSM8K](https://github.com/openai/grade-school-math/tree/3101c7d5072418e28b9008a6636bde82a006892c) | `question` | revision `3101c7d…6892c`; test JSONL `3730d312…d14` |
边界:
- HumanEval 的 `canonical_solution`、`test` 没有进入模型,也没有执行代码;
- GSM8K 的 `answer` 没有进入模型;
- TNEWS 的标签和关键词没有进入模型;
- WikiText 只取 raw validation 的正文候选,不连接其他 split;
- 这四个来源被当作“探针语料”,不是任务正确率评测。
### 2.2 确定性选样
固定 salt:
```text
llm-atlas-deepseek-routing-v1
```
每域候选按下式升序排列,再取前 32 条:
```text
SHA256(salt | domain | source_id), then source_id
```
这比 `random.sample` 多保留了两层可复现性:
- 不依赖 Python / NumPy 随机实现;
- 每条输出都保留 source ID、selection rank、原文 SHA-256、字符数与 token 数,
可以从固定源文件重新定位。
文本使用官方 DeepSeek-V2-Lite tokenizer,加入 special tokens,从右侧截到 96
tokens。最低长度过滤为:
| 域 | 最低 token | 文本过滤后的候选 | 长度合格 | 选中 | 选中 token |
| --- | ---: | ---: | ---: | ---: | ---: |
| 英文百科 | 24 | 1,841 | 1,655 | 32 | 2,882 |
| 中文新闻 | 8 | 10,000 | 9,415 | 32 | 573 |
| Python 代码 | 24 | 164 | 164 | 32 | 2,983 |
| 小学数学 | 16 | 1,319 | 1,319 | 32 | 2,022 |
英文与代码经常触到 96-token 截止线;中文新闻标题明显更短。因此后续不能只给
一份“把所有 token 倒进桶里”的汇总。
## 3. 模型与执行边界
### 3.1 官方工件
```text
deepseek-ai/DeepSeek-V2-Lite
revision 604d5664dddd88a0433dbae533b7fe9472482de0
```
关键 SHA-256:
| 工件 | SHA-256 |
| --- | --- |
| `config.json` | `f346286b0f1c8b044252fd54cb4fa78b9fab6472a6e8bebb9edfe03d414ea03d` |
| `modeling_deepseek.py` | `7d8e5221095286eea991137760893fd7ba52727c0b4ebf48ec09e8bc56b45b9c` |
| `tokenizer.json` | `41f3bf64213da8c012d8bd0871a58a1fdf70463e8f08f110ddbb1082f529f669` |
| checkpoint index | `d2cdb2f325f6682cf3ad1ad2526a9f979d857390b579380c0331d975136e0acf` |
| shard 1 | `0d7e9f39bde40111a4c0f390b87497dce4565cf578d916395e6b2c7851f1e8da` |
第一分片完整包含 embedding 与 decoder layer 0–6;layer 7 跨分片,因此继续遵守
原有停止线。Layer 0 是 dense FFN,layer 1–6 是本次统计的六个 MoE 层。
### 3.2 批处理不会把 padding 算进统计
128 条样本按 token 数、domain、source ID 稳定排序,batch size 为 16。每个 batch
右侧 padding,并使用官方 eager attention 与 causal/padding mask。
gate hook 会看到 padded positions 的输出,但统计时只切:
```text
topk_ids[sample, :valid_length, :]
```
所以每条 prompt 的 route 总数必须严格等于:
```text
valid_tokens × 6
```
六层均通过这个不变量检查;每层都是 50,760 routes。
### 3.3 未执行的对象
- 未下载或执行 layer 7–26;
- 未做完整模型生成;
- 未测回答正确率;
- 未测训练期间 router load;
- 未测线上 serving 流量;
- 未执行 FlashMLA 优化 kernel;
- 未给 expert ID 赋语义名称。
## 4. 为什么 bootstrap 的单位必须是 prompt
一个 prompt 中相邻 token:
- 共享主题、语言与格式;
- 共享相同前缀 hidden state;
- 在 causal attention 下相互依赖;
- 不是独立同分布样本。
如果把 8,460 个 token 当成 8,460 个独立样本,区间会虚假变窄。这里先为每个
prompt 保存 64 维 route-count vector,再在每个 domain 的 32 条 prompt 内有放回
抽取 32 条。四个 domain 分层进行,固定:
```text
replicates = 2000
seed = 20260729
interval = percentile [2.5%, 97.5%]
```
它回答的是:
> 如果仍从这个固定探针来源与选样合同附近换一批 prompt,统计量会怎样波动?
它不回答:
> 真实训练分布或线上流量的总体参数是什么?
## 5. 两种聚合口径
### 5.1 Token weighted
先汇总一个 domain 内所有 prompt 的 route counts,再归一:
```text
p_e = Σ_i count(i,e) / Σ_i Σ_e count(i,e)
```
长 prompt 贡献更多,适合回答“本批实际 token 流向哪里”。
### 5.2 Prompt balanced
先把每条 prompt 的 64 维分布归一,再让 32 条 prompt 等权:
```text
p_e = mean_i [count(i,e) / Σ_e count(i,e)]
```
适合跨格式比较,因为一条短新闻标题与一条被截到 96 token 的代码 prompt 各有一票。
网站默认展示这一口径,并允许切换。
在本次四域内部,CV 的两种口径最大绝对差为 0.027(Layer 1 数学)。这说明主要
层级图景不是某一条特别长 prompt 单独制造的;但两套数字仍完整保留,不能据此假设
未来语料也不敏感。
## 6. 指标是什么
对当前层、当前 domain 的 64 维 expert share `p`:
### CV
```text
CV = population_std(p) / mean(p)
```
越大表示 share 越分散。它不是训练损失,也不直接等于“不均衡惩罚”。
### Gini
64 个 share 的 Gini coefficient。0 表示完全均匀;越大表示质量集中到更少 expert。
### Effective experts
```text
H(p) = -Σ p_e log p_e
effective = exp(H)
```
完全均匀时为 64;越小表示“按熵折算”的有效 expert 数越少。
### Top-expert share
64 个 share 的最大值。完全均匀基线为 `1/64 = 1.5625%`。
### Jensen–Shannon divergence
同层两个 domain 分布 `P,Q`:
```text
M = (P + Q) / 2
JSD(P,Q) = 1/2 KL(P||M) + 1/2 KL(Q||M)
```
使用自然对数,范围 `[0, ln(2)]`。0 表示两条 64 维分布完全相同。
## 7. 主要结果
以下均为 **prompt-balanced** 点估计;括号内是 effective experts。网站可切换到
token-weighted 并查看完整 95% 区间。
| layer | 英文百科 CV(effective) | 中文新闻 CV(effective) | 代码 CV(effective) | 数学 CV(effective) |
| ---: | ---: | ---: | ---: | ---: |
| 1 | 0.439(59.0) | 0.754(53.3) | 0.566(55.4) | 0.613(56.3) |
| 2 | 0.363(60.2) | 0.460(58.4) | 0.400(59.1) | 0.403(59.0) |
| 3 | 0.398(59.2) | 0.469(57.9) | 0.440(57.9) | 0.525(57.0) |
| 4 | 0.424(58.6) | **0.910(47.2)** | 0.610(54.0) | 0.527(56.0) |
| 5 | 0.418(58.5) | 0.551(55.0) | 0.524(56.0) | **0.848(49.7)** |
| 6 | 0.496(56.7) | 0.594(53.1) | 0.556(54.7) | **0.770(50.7)** |
### 7.1 Layer 2 在四域都相对平
Layer 2 的 prompt-balanced CV 为 0.363–0.460,effective experts 为
58.4–60.2,是六个被测 MoE 层中四域共同最平的一段。
“相对平”只指这 64 维 route-count distribution;不等于 expert 权重相同、计算量
完全相同或训练全局均衡。
### 7.2 Layer 4 的中文新闻更集中
Layer 4 中文新闻:
```text
CV = 0.910, 95% CI [0.857, 0.993]
effective experts = 47.2, 95% CI [44.4, 48.5]
top share = E29 9.06%, 95% CI [8.41%, 9.78%]
```
同层英文百科 CV 为 0.424、代码为 0.610、数学为 0.527。正确表述是:
> 在这 32 条 TNEWS 句子、这个 tokenizer、这个 layer 的固定探针中,route counts
> 比另外三域更集中。
错误表述是:
> E29 是“中文专家”。
### 7.3 Layer 5/6 的数学更集中
Layer 5 数学:
```text
CV = 0.848, 95% CI [0.794, 0.911]
effective experts = 49.7, 95% CI [48.1, 50.7]
top share = E14 8.04%, 95% CI [7.38%, 8.64%]
```
Layer 6 数学:
```text
CV = 0.770, 95% CI [0.728, 0.826]
effective experts = 50.7, 95% CI [49.3, 51.5]
top share = E28 7.54%, 95% CI [6.79%, 8.26%]
```
E14 与 E28 位于不同层,是不同参数;不能连成一个跨层“数学专家轨迹”。
### 7.4 同层域间 JSD
每层最大的 prompt-balanced pair:
| layer | 最大 pair | JSD point | 95% bootstrap interval |
| ---: | --- | ---: | ---: |
| 1 | 中文新闻 ↔ 代码 | 0.0587 | [0.0549, 0.0703] |
| 2 | 中文新闻 ↔ 代码 | 0.0345 | [0.0306, 0.0466] |
| 3 | 中文新闻 ↔ 代码 | 0.0569 | [0.0519, 0.0713] |
| 4 | **中文新闻 ↔ 代码** | **0.1502** | **[0.1376, 0.1715]** |
| 5 | 中文新闻 ↔ 数学 | 0.1113 | [0.0990, 0.1368] |
| 6 | 中文新闻 ↔ 代码 | 0.1161 | [0.1054, 0.1351] |
Layer 4 的中文新闻↔代码是本探针最大的同层距离,但仍只有理论上界
`ln(2)≈0.693` 的约 21.7%。
必须特别注意:普通 percentile bootstrap 是围绕经验分布重采样,不是“两个总体完全
相同”的 null bootstrap。区间不含 0 不能被偷换成经过校正的显著性检验。
## 8. 可复现性
正式运行和独立重跑的完整 JSON:
```text
4678a1d15395de93ffba757598cc3642bf35e9e07f71d82ddd87c27fc38a09e4
```
两个文件 byte-for-byte identical。确定性范围包括:
- 128 条选样身份、token 数与原文 SHA-256;
- 六层、每条 prompt 的 64 维 integer route counts;
- 两种聚合口径;
- 2,000 次 bootstrap 导出的所有 metric / expert-share / JSD 区间;
- 模型、语料、环境与统计合同。
没有记录 wall-clock timing,因此复跑一致性没有把 GPU warm-up、频率或系统噪声混进
证据闸门。
### 8.1 运行入口
```bash
PYTHONPATH=/path/to/transformers-4.41.2-deps \
python -B experiments/deepseek/v2_lite_routing_corpus.py \
--artifact-dir /path/to/deepseek-v2-lite \
--human-eval /path/to/HumanEval.jsonl.gz \
--gsm8k /path/to/gsm8k/test.jsonl \
--tnews /path/to/tnews/test.json \
--tnews-archive /path/to/tnews_public.zip \
--wikitext /path/to/wikitext-validation.parquet \
--output src/data/deepseek-v2-lite-routing-corpus.json \
--per-domain 32 \
--max-tokens 96 \
--batch-size 16 \
--bootstrap 2000 \
--seed 20260729 \
--captured-at 2026-07-29T07:45:00+00:00
```
官方 2024 remote code 在本机 Transformers 5.5 上会因已移除的
`is_torch_fx_available` 失败;与前两轮相同,本实验使用隔离的 Transformers 4.41.2
依赖,并把官方模型代码作为只读本地 package 导入,不给源码打补丁。
## 9. 仍然不能说什么
本实验没有授权以下结论:
- “DeepSeek 训练时专家全局负载就是这样”;
- “线上中文请求一定路由到 E29”;
- “E48 是代码专家、E14 是数学专家”;
- “某个 domain 的任务性能更好”;
- “router 的分布差异来自语义,而不是长度、tokenization、格式或共享前缀”;
- “六个早期 MoE 层代表完整 27 层”;
- “bootstrap CI 已经完成假设检验或多重比较控制”。
更稳妥的结论只有:
> 在固定、可重建的 128 条公开 prompt 上,DeepSeek-V2-Lite 的六个早期 MoE 层
> 确实呈现可测量的层间与域间 route-count 差异;prompt-level bootstrap 让我们能同时
> 看见差异和换 prompt 时的波动,但不能把参数索引直接解释成语义角色。
## 10. 下一步
1. 在受支持的 SM90 / SM100 环境执行 FlashMLA 优化 kernel,而不只运行算法参考路径;
2. 扩展到完整 layer 0–26,需要下载并校验其余 checkpoint shards;
3. 加入长度匹配与 tokenizer-fragmentation 对照,拆开 domain 和长度因素;
4. 预注册更少的主要比较,或使用 permutation / null bootstrap 与多重比较校正;
5. 研究 shared expert 与 routed expert 的激活规模,而不只看 routed IDs;
6. 若讨论性能,另建生成质量与吞吐合同,不与本路由描述实验混在一起。