Vizuara AI Labs 联合创始人、MIT 博士 Raj Dandekar,花 252.35 美元租一张 H200,从零预训练了一个迷你版 Kimi K3,把官方代码训不动的坑也一条条写进日志。这本 30 章、179 张图、约 5 小时读完的免费电子书,核心不是「成功复刻」,而是「完整的工程日志,包括所有失败和踩坑」。
大模型训练这件事,过去几年被讲成了两套话术:要么是「算力即一切」,几张万卡、十亿美元训练完发个 SOTA;要么是「普通人勿碰」,模型架构藏在闭源报告里,连训练入口都不告诉你。
Raj Dandekar 的这本《Pretraining a Mini Kimi K3》(预训练一个迷你 Kimi K3)想打破的就是这个叙事。它把 Moonshot AI 在 2026 年 7 月刚刚发布的 Kimi K3 旗舰架构,逐行拆开、整体缩小、再在自己的脚本里跑通——单卡 252 美元,50 亿 token,一个 10.2 亿参数的复刻版 MoE。
但这本书真正值钱的部分,不是终态那个 33.4% HellaSwag 的模型,而是它记录失败的方式。官方代码跑不起来的 4 个未文档化问题、MoE router 第 20 步就杀掉 94.5% 专家的专家坍塌、3 个不崩溃但悄悄出错的分布式 bug、一整章提速实验只有 3 次成功——全都原样写下来。
《Pretraining a Mini Kimi K3》是 Vizuara Books 上架的免费电子书之一,作者 Raj Abhijit Dandekar 是 MIT 博士、Vizuara AI Labs 联合创始人,也是 YouTube 系列 Build DeepSeek from Scratch 的主讲人。Vizuara Books 一共 49 本插图风格 AI 教材,这本是 2026 年 8 月刚发布的新作。
全书 30 个 capsule(Vizuara 的章节单位),按作者自己的话,是「一份跑完的预训练工作日志」:
00 Start Here 3 capsule 介绍一次能发表的训练与一次不能的训练差在哪里
01 The Model 5 capsule 逐行读 K3 官方 config,再做等比缩小,逐层拆解注意力堆栈与 MoE 路由
02 The Data 5 capsule 104.8B token 语料、13-gram 去污染、shard 格式断点续训、tokenizer 选型
03 Making It Train 5 capsule 官方代码 4 个坑、训练循环设计、专家坍塌检测、checkpoint 容灾
04 Making It Fast 7 capsule MFU 概念、专家循环、profile 定位、提速实验的反直觉结果
05 More Than One GPU 2 capsule FSDP2 分片、3 个不崩溃的分布式 bug
06 Did It Work 3 capsule loss 全曲线、24 个跨训练 benchmark 点、252 美元的最终账本
整本书没有任何公式推导是凑出来的「为了显得专业」的部分,每一节都对应一次具体的训练实验或一次具体的代码改动。读完五小时,但你会在第四章、第五章的踩坑描述里反复回看。
「The released code cannot train. Four undocumented blockers, and a training loop built around them.」—— 摘自 capsule 14 章节标题
想理解 Raj 的「缩小算术」,得先知道他在缩什么。2026 年 7 月 16 日,Moonshot AI 在 WAIC 2026 上海发布了 Kimi K3;7 月 27 日完整权重在 Hugging Face 开源,采用自定义的 Kimi K3 License——并非中文媒体广泛误传的「修改版 MIT」,其中对月活超 1 亿或 MaaS 年营收超 2000 万美元的场景设有额外授权条款。它也是目前参数量最大的开源模型之一。
一句话把它的配置讲清楚:
| 2.8 万亿(2.8T) | ||
| 1040 亿(104B) | ||
| 单张 H200 · 5B token · $252.35 |
表里能看到三件对缩小至关重要的设计选择:第一,93 层的 KDA : Gated MLA = 3 : 1,是 Moonshot 在 Kimi Linear 系列里就坚持的混搭比例,Raj 把它原样搬到 12 层上;第二,top-k 路由(官方 16 / 总 896,复刻 6 / 更小专家池)保留了 MoE 的「稀疏激活」这个核心机制;第三,163,840 词表的 tokenizer 直接沿用官方,省掉重新训练分词器、重新对齐 embedding 的两个月。
另一个常被忽略的细节是 K3 用的不是 RoPE 而是 NoPE(No Positional Embeddings)——直接取消显式位置编码,靠注意力层内部的机制隐式感知位置。Raj 复刻时也保留了这个选择,没有为了「看着像主流」就改回 RoPE。
这是第 4 到第 8 capsule 的核心:怎么把 2.8T 缩到 1.02B,又不缩成「另一个模型」。
很多人的第一反应是「线性缩放」——所有维度除以同一个常数。但 Raj 在 capsule 5 Scaling it down without lying about it 里明确说这种做法会「骗」:最后实际采用的方案,每个维度的缩放比都不一样——hidden 维度缩约 14 倍、层数缩 7.75 倍、专家池只缩 3.5 倍、词表干脆 1 倍不动。没有统一的「缩放系数」,只有一个总参数约 2745 倍的目标,再按各维度对训练行为的实际影响分别定比例。
他的做法是「结构比例原样保留,容量按训练预算剪」:
KDA : MLA = 3 : 1
93 层变 12 层,但每 4 层里仍是 3 个 KDA + 1 个 Gated MLA。这是 Moonshot 的 Kimi Linear 设计选择——线性注意力扛长程依赖,标准注意力保关键位置精度。比例改了,模型性质就变了。
top-k 路由(不是 top-1)
官方每个 token 选 16 / 896(~1.79% 专家),复刻版选 6 个专家 + 共享专家。比例上保持「少数派专家被激活」的稀疏性,但因总专家池也缩小,绝对数量比不是 16:6。重要的是「稀疏激活」这件事保留。
直接沿用官方 tokenizer
163,840 词表是 K3 的「语言世界观」。Raj 没有重新训分词器,而是直接用官方——这意味着输入分布、上下文长度语义、跨模型对比的公平性全部保留。
capsule 8 专门做了一次「Counting the parameters, and checking the counter」:把 KDA、Gated MLA、AttnRes、LatentMoE 各自的参数贡献逐项相加,最后在 PyTorch 里用真实 forward 跑一次参数计数核对。手算和跑出来的数字一致才敢下笔。这个「自检」环节,是他把「不变成另一种模型」落到实处的关键。

很多人以为「预训练 = 把数据塞进去训」,于是对数据这一章期待不高。Raj 用 5 个 capsule(capsule 9–13)证明这是个错觉。
训练前准备的语料是 104.8B token,从 6 个公开来源混合:FineWeb-Edu(62.1B token)、FineWeb web-diverse(13.4B)、StarCoder2 的 code-python(14.9B)、FineMath(6.4B)、OpenWebMath(4.4B)、Cosmopedia(3.7B)。实际真正跑完的是 5,000,003,584 token(约 50 亿)——为什么没把 104.8B 跑完?就是预算:按 $252 的租金和实测吞吐,能跑到头的正好就是这个量级。
真正出彩的是 去污染(decontamination)。Raj 用 13-gram 匹配,对 8 个 benchmark(MMLU、ARC-Challenge、HellaSwag、GSM8K、HumanEval、PIQA、WinoGrande、TriviaQA)的测试集做了滑动窗口去重。这套做法从 GPT-3 论文传下来、SmolLM 团队也在用,但工程细节上有几个魔鬼:
还有一个很工程但很关键的细节——shard 格式与 checkpoint 容灾。语料切成 1,063 个 shard,训练状态配齐 state.pt、loader.json、meta.json 和 COMPLETE 完整性标记,任何一次中断都能从最近的完整检查点无损续训。这不是可选项——Raj 用的 Modal 平台单次运行上限 24 小时,5B token 的训练必须主动切成 3 段、靠检查点接力跑完,每段之间一旦失败需要重算的风险窗口从 32 分钟压到 15 分钟。在云租卡的世界里,「断点续训」是设计出来的,不是靠运气。
第三章 5 个 capsule(capsule 14–18)是全书最值钱的章节。capsule 14 标题只有一句话:「The released code cannot train.」
Moonshot 在 7 月 27 日开源 K3 权重的同时,也把 modeling_kimi_linear.py、modeling_kimi_moe.py 等建模代码放到了 GitCode / Hugging Face 仓库。但 Raj 很快撞上一个没人明说的事实:这份发布的建模代码,根本不能直接拿来训练——不是缺依赖、不是显存不够,而是 4 个藏在代码里的未文档化问题:
1. 路由 gate 里写着训练断言 KimiMoEGate 代码里赫然是 assert not self.training——一进训练模式就断言失败,这份代码压根没打算让你从训练路径走;2. MoE 前向被 @torch.no_grad 包住moe_infer 整条路径不进 autograd 计算图,forward 能跑,backward 无梯度可传;3. noaux_tc 的 e_score_correction_bias 没有初始化 负载均衡偏置注册成了 buffer,却没给初始值,路由从一开始就处于「薛定谔状态」;4. dt_bias 用 torch.empty 创建 empty 不清零,读到的直接是未初始化显存里的随机数。
Raj 没有去改 Moonshot 的源码(毕竟那是官方权威版本),而是自己写了一个训练循环绕开这 4 个点。capsule 15 标题就叫 The training loop(WSD)——他用了 WSD 学习率调度(Warmup-Stable-Decay,MiniCPM 团队推广的方案),自己手写 forward、backward、optimizer.step、gradient clipping、checkpoint 保存。
这一节的真正价值在于:它把「开源权重 ≠ 可复现」这件事戳破了。GitHub 上 8 千多 star 的旗舰模型仓库(Kimi-K3 目前约 8.4k star),README 写得很漂亮,但「直接 clone 下来跑」和「能跑出数字」之间,还隔着 4 个未文档化的工程坑。这条经验放到任何一个新模型上——DeepSeek、Qwen、Mistral——都成立。
第 16 capsule 是全书最让人紧张的一节:「Expert collapse, and the metric that missed it.」
MoE 的理想状态是「不同 token 走不同专家,专家利用率均匀」。但 Raj 在训练跑到第 20 step 时发现:94.5% 的专家被 router「杀死」——也就是所有 token 都集中到了剩下 5.5% 的专家头上,剩下的专家们一次都没被选过。
最可怕的是:路由熵(router entropy)的读数还是 0.9999——一个接近「完美均匀」的数字。专家已经死了一大半,监控却告诉你一切正常。这就是 capsule 16 标题里那个「the metric that missed it」的真正含义:不是没有监控,是监控指标本身在这种坍塌模式下失灵了。
修复方法不是「打开 aux loss 系数」——K3 的负载均衡本来就是 aux-loss-free 设计。真正的修复是把 noaux_tc 的 bias 更新规则接对:每个专家的偏置按 bias += gamma × sign(平均负载 − 自身负载) 动态调整,gamma 取 1e-2。DeepSeek-V3 论文用的是 1e-3,但 batch size 不同不能照抄——书里干脆做了一组 gamma 扫描实验,把这个超参的取舍过程也原样写了进去。
第五章(05 More Than One GPU)的 capsule 27 记了更阴险的「Three distributed bugs that do not crash」。这类 bug 在多卡训练时悄悄存在:训练不崩、loss 正常下降、checkpoint 一切完好,但模型就是错的。它们的共同审计原则是——「哪些量在定义时是跨整个 batch 的,哪些现在只是按 rank 算的」:
SourceStream 接受 seed 却从不保存,所有 rank 都从 shard 0、offset 0 确定性遍历——等效 batch 被缩成名义值的 1/world(双卡时直接减半)。修复用 round-robin 发牌 sorted(found)[rank::world]。sign(平均负载 − 负载) 并各自更新自己的 bias 副本,导致「同一 token 走哪个专家取决于它在哪张卡上」;修复需在 early-return 之前加一次 all_reduce。opt.step()、另一个调 zero_grad(),权重从此分叉却无人报错。书中还顺带记了两个同类问题:router bias 被 fully_shard 变成 DTensor 后 in-place 加法直接报错(这是这群 bug 里唯一会崩的一个),以及 Decoder 层返回 view 张量需 clone——不在正文但同族,延伸阅读可翻原书。
这三个 bug 都不会让训练崩,跑完的模型只是一个「安静的错」——loss 正常收敛、benchmark 数字看上去能复现,但你拿去对比官方评测时总会差几个点。原因就是这种「悄悄出错」。
第四章 7 个 capsule(capsule 19–25)记的是整本书最容易让人「反共识」的部分。Raj 把 MFU(Model FLOPs Utilization,模型算力利用率)作为「单位时间到底换到了多少有效计算」的核心指标——按 6 × 激活参数 × tokens/s ÷ 峰值算力来算——并把整个优化写成 16 次编号实验(attempt 1–16),其中只有 3 次真正成功(其余失败也原样记录)。
关键数字:只有 3 次成功——17.5x、1.38x、3.2x,其余失败也原样记录,capsule 21 还专门写了一节六个没成功的想法。17.5x 来自 capsule 20 的专家循环:MoE 的专家分发原本要在 Python 里循环启动 3,840 次,改成 3 次批量矩阵乘后,单步时间从 3.999 秒降到 0.228 秒,MFU 从 0.1% 拉到 4.1%。1.38x 来自 capsule 23:把 SiTU 激活链上的一串零碎算子融合成一个 Triton kernel,MFU 5.6%→7.7%。3.2x 来自 capsule 25 的 silent fallback:dispatch 缓冲区超限时会静默回退到慢路径,auto-chunking 把这个「无声的慢」消掉(这个倍数在旗舰运行上测得)。
反直觉发现 #1:FP8 反而更慢
朴素地切到 FP8,实测只有 bf16 的 0.19x~0.09x——慢 5 倍以上,精度损失也是 bf16 的约 5 倍。低精度不是「开了就快」:在这个规模下,量化的额外开销远大于计算节省。官方 K3 的 MXFP4 能成立,靠的是 QAT 量化感知训练,不是推理时随手切低精度。
反直觉发现 #2:更大 GPU 上 MFU 腰斩
从 H200 换到单张 B200,MFU 从 7.7% 掉到 4.0%——利用率几乎腰斩;但绝对吞吐量提升了约 20%。峰值算力涨得比吞吐快,意味着「花的钱有多少变成了有效计算」在下降。capsule 24 的结论很冷静:更大 GPU 不是免费午餐,成本效率要按 MFU × 单价重新算一遍。
capsule 22 用 PyTorch profiler 做了一次全流程 profile,结果相当意外:matmul 只占 GPU 时间的 11.6%,elementwise 操作占 41.9%,copy 占 24.7%——矩阵乘才是少数派,GPU 的大量时间花在搬运数据和琐碎算子上。这就是为什么 MoE 在小 batch 下单纯堆 GPU 没用:瓶颈根本不在「算」。
capsule 23 Two kernels that worked, and one that did not 是这章少有的甜点:两个手写 kernel 成功、一个失败。最有效的一次不是重写什么大算子,而是把 SiTU 激活链上的一串零碎算子融合成一个 Triton kernel——1.38x 的提速(MFU 5.6%→7.7%)就是这么来的。

capsule 28 给出了 loss 全曲线:从初始 12.10 收敛到最终 2.62,稳定下降,没有诡异凸起(说明专家坍塌等 bug 都已经被修好)。
capsule 29 记了 24 个跨训练过程的 benchmark 点——不是「训完跑一次」,而是在训练过程中的多个节点各评一遍,画出 benchmark 分数随 token 量生长的曲线。这个做法在论文里叫 intermediate evaluation,工程意义远大于最终那一个数字。
最后 HellaSwag 33.4%(训练早期约 27.0%),对比激活参数量级相当的 GPT-2 124M(约 28%–32%)——145M 激活的稀疏 MoE,超过了 124M 全激活的稠密 Transformer。这不证明它比 GPT-2「更好」(GPT-2 也没有指令微调),但证明 K3 的稀疏架构在 1B 这个量级上能跑通、能学到东西。
最后一章 capsule 30 直接回答一个很硬的问题:「What $252 buys」。账本列得很细:
r1 训练运行(H200 @ $4.54/小时 × 约 55.6 小时) $252.35
数据下载与去污染算力 约 $17
benchmark 评估算力 约 $3
checkpoint 存储 $0.09 / GiB / 月
旗舰配置的一次失败运行(另计) $48.33
主训练运行实付:$252.35
252 美元买到的不是一个「拿来就能商用的 LLM」(激活 145M 的稀疏模型离能干活的助手还很远),而是一份从读配置到写训练循环到跑出 benchmark 的完整工程资产——所有代码、所有失败、所有数据、所有的踩坑都打包成 30 个 capsule,免费在线阅读。
这本书适合谁
想自己从零预训练 MoE 模型的工程师;想真正理解 Kimi K3 / DeepSeek V3 / Mixtral 这类稀疏架构的研究者;做模型推理优化、对 MoE 通信瓶颈有第一手兴趣的人;以及——任何觉得「开源模型 = 能跑」的人。
这本书不适合谁
只想拿 LLM 写文案的人;想找现成下游应用的人;觉得 1.02B 模型能跑赢 7B 指令微调模型的人;以及对「失败也是内容」这件事不耐烦、只想看最终数字的人。
怎么读这本书最有效
先跳读第 1–8 章搞清架构,再回头细读第 14–18 章把「官方代码跑不动」这件事刻进脑子;第 19–25 章是 MFU 工程精华,至少通读两遍;第 26–27 章分布式部分是选读,但每个 bug 都建议手抄一遍。最后第 28–30 章当作汇总。
什么时候不该用这本书的结论
书中所有数字(HellaSwag 33.4%、MFU 7.7%、FP8 的 0.19x)都建立在「1.02B / 12 层 / 单 H200 / 5B token」这个特定规模上。当你的模型规模、token 量、GPU 拓扑变化时,不要直接外推。例如:千亿模型上 FP8 反而是必须的;换到更大的 GPU 或多卡拓扑,MFU 与通信的平衡点也完全不同。
01「算力即一切」叙事的第一次松动
用 252 美元复现 2.8T 模型的架构骨架,这件事本身比数字更重要。它意味着:即便没有万卡集群,个人研究者也能在 5 小时内读懂一个旗舰模型的「骨骼」,并在单卡上把每个组件单独跑通。算力垄断从「看不见」变成了「可拆解」。
02「开源 = 可复现」是一个危险的简化
Raj 用 4 个未文档化问题证明:模型权重开源 ≠ 训练过程开源 ≠ 能复现出 paper 上的数字。把「能跑」当成「可复现」的同义词,是当下开源 LLM 最大的认知陷阱。每次新模型发布,下游都该有 1-2 周的「复现坑」窗口期。
03专家坍塌不是「MoE 的问题」,是「监控的盲区」
94.5% 专家被 router「杀死」这件事,路由熵读数却还是 0.9999。单一指标会失灵,监控体系必须有冗余。这给所有 MoE 实践者的提醒:per-expert 命中率、负载分布这类细粒度指标必须上 dashboard——书里失效的,恰恰是看起来最合理的那个指标(路由熵)。
04「更大就是更好」的反面:硬件规模不匹配模型规模
换上更大的 B200,吞吐只涨约 20%,MFU 却从 7.7% 腰斩到 4.0%。这种「越大越亏」的现象在 MoE 小规模训练里相当普遍。选硬件不能只看算力峰值,要看这个模型规模下的实际利用率——峰值算力买回来了、用不满,就是纯浪费。
05把失败写进文档的复利,比成功写进文档大得多
失败的提速实验、3 个静默的分布式 bug、4 个未文档化的官方代码问题——这些东西加起来的知识价值远大于 33.4% 的 HellaSwag 数字。希望每个写技术博客、做开源项目的人,都能像 Raj 这样把失败原样写下来。我们这个社区太缺「失败友好」的内容了。
参考阅读
《Pretraining a Mini Kimi K3》电子书(Vizuara Books)
https://books.vizuara.ai/book/pretraining-a-mini-k3
Kimi K3 官方技术仓库(MoonshotAI/Kimi-K3)
https://gitcode.com/MoonshotAI/Kimi-K3
DeepWiki:Kimi K3 Model Specifications 详细参数表
https://deepwiki.com/MoonshotAI/Kimi-K3/1.2-model-specifications
Hugging Face:Kimi K3 Model Overview(MXFP4 / 开源权重解读)
https://huggingface.co/blog/ResterChed/kimi-k3-model-overview-mxfp4-quantization-open-wei
新浪财经:Kimi K3 开源与三大基础设施 MoonEP / FlashKDA / AgentEnv
https://finance.sina.com.cn/roll/2026-07-28/doc-inikiewr0451740.shtml
Reddit r/LocalLLaMA 原帖:I just built a mini Kimi-K3 from scratch under $250
https://www.reddit.com/r/LocalLLaMA/comments/1vth1c3/i_just_built_a_mini_kimik3_from_scratch_under_250/
Vizuara Books 主页(49 本 AI 插图电子书)
https://books.vizuara.ai/