最近后台收到不少私信,都在问同一个问题:"我想搞 AI,但不想只会调 API,想真正从零开始(from scratch)做一个模型,这条路怎么走?"有人想复现 Llama 的架构,有人想训练自己的 7B 模型,还有人看到 DeepSeek-R1 出来之后,直接问能不能自己蒸馏一个推理模型。信息很杂,问题很多。我断断续续踩了三年的坑,从单卡训练跑通 GPT-2 规模的小模型,到多卡分布式训练,再到把模型部署上线,算是把"ai engineering"这条链路完整走了一遍。我想把这段经历里真正有价值的经验写出来——不是概念科普,而是实打实的工程路线:先判断你到底需不需要从零开始,然后从最小可复现的模型做起,再到数据工程、训练调试、推理部署,每一步都告诉你为什么这么选、有哪些可以绕开的坑。
如果你是想做应用层开发,大多数时候用开源权重就够了,这没问题。但如果你做过一个从零训练的小模型,你对学习率、数据配比、损失函数、显存分布的理解,会跟只看文档的人完全不在一个层次。这篇文章就是写给这些人的:想做推理模型的、想训练大语言模型的、想真正理解 AI 系统内部机制的,以及准备上车但还没找到合适切入点的工程师。
1. 先冷静回答:你到底是需要"从零开始",还是只需要"一张更清晰的图纸"
很多人一听到"from scratch"就兴奋,觉得从头预训练一个大语言模型很酷。但你得先想清楚,这个"从零"指的是哪一层。是连矩阵乘法的梯度都要手写?是从头实现一个 Transformer?是从随机初始化开始预训练?还是在 PyTorch 里搭一个自己的模型结构,加载公开数据集从零训练?
我的经验是,绝大多数人的真实需求并不是字面意义的"从零复现一切",而是"我不想只做调包侠,希望对自己用的模型有完全的掌控权"。这两个需求对应的路线差别很大。如果你只是自己研究,或要写论文、做毕业设计,那从零训练一个 1 亿到 10 亿参数量的小模型已经足够让你理解几乎全部核心机制。如果你想做真正能落地的产品,那更合理的路线是:用开源底座模型做继续预训练和微调,重点把数据工程和评测体系做深——这才是工业界最缺的能力。
先给一个判断标准:如果你的目标是"发布一个能盈利、能被用户天天使用的 AI 产品",不要从预训练起步,直接从开源模型开始做领域训练和垂直优化,成本能差两个数量级。如果你的目标是"深度理解 AI 系统、为科研打底、或者现有开源模型满足不了数据合规/领域要求",那你确实需要走一遍完整的数据处理、预训练、评估闭环。
时间预算上也要有预期:一个 124M 参数的 GPT-2-scale 模型,用 8 张 A100 预训练到接近收敛,需要跑几天;一个 1.5B 参数模型,数据量按 100B token 计算,就需要上百张卡的级别。这个成本不是每个人都有条件承受的,所以第一步不是买卡,而是先明确你的"从零"到底有多零。
2. 最小可复现的 Transformer:把 GPT-scale 模型真正跑起来
想从零训练,最合理的起点不是直接上 Llama-7B,而是复现一个你完全吃得透的小模型。我建议以 GPT-2 small 的规模(124M 参数,约 1.5B token 数据)作为目标,理由很实在:单张高端消费级显卡或一张 A100 就能在可接受时间内跑完一个完整的训练闭环,观察 loss 下降、过拟合、学习率的影响。
2.1 架构选型上,我做过的几个关键决定
标准 Transformer decoder-only 架构就够了,但有几个细节别忽略。
第一是 tokenizer。很多人觉得直接拿别人训练好的 tokenizer 用就行,但如果是"从零开始",希望你至少了解它的机制。GPT-2 用的是字节级 BPE,词表大小 50257。字节级 BPE 的优点是任何文本都不会出现 OOV(out-of-vocabulary)问题,对多语言和代码都友好。不建议自己从零训练 BPE 再往里加 special token,后续扩展性很差。你可以直接用 HuggingFace 的 GPT2Tokenizer,也可以训练一个自己的 BPE,但一定保持字节级。
第二是位置编码。如果你按原始 Transformer 的实现用正弦位置编码,也不是不行,但建议直接用 RoPE。原因是 RoPE 天然有更好的外推能力,后续你做序列长度扩展时会轻松很多。从实现成本来说,RoPE 只是在前向传播里加一个旋转矩阵,代码量并不比传统位置编码多。
第三是归一化层。原始的 GPT-2 用的是 LayerNorm 放在子层之后(post-norm),Llama 风格把它挪到了子层之前(pre-norm)。从稳定训练的角度,pre-norm 更省心。归一化层建议用 RMSNorm,不改变输出均值但省去均值和方差的完整计算,在长序列上能省不少显存和计算。
2.2 初始化与超参数,直接抄作业
很多人栽在初始化上。这里我给一组经过实践检验的参数,你可以直接抄:
- 权重初始化:均值 0、标准差 0.02 的正态分布。对最后一层和 embedding 层,标准差建议缩小到 0.005。
- 残差分支初始化:对每个残差分支,输出乘上一个 1/sqrt(层数) 的缩放,避免深层模型激活值爆炸。这个技巧在 T5 和很多现代模型里都有用到。
- 学习率:峰值 3e-4,配合 warmup 和 cosine 衰减。这个值对 124M 到 1B 参数的模型都适用,7B 以上要下调到 1.5e-4 左右。
- 优化器:AdamW,beta1=0.9,beta2=0.95,weight decay=0.1,梯度裁剪到 1.0。
- 批次大小:按 token 数算,0.5M 个 token 起步。如果显存不够,梯度累积来凑,但累积步数建议不超过 8。
我自己踩过的坑是:一开始模仿现代大模型的超大 batch size(例如 4M token),在 124M 小模型上反而收敛得更慢。小模型在过大的 batch 下,每步的梯度含信息量不足,loss 曲线的下降很迟缓。
2.3 分布式训练的最低配置
先单卡跑通,再上分布式,这是铁律。单卡阶段用 PyTorch 的 FSDP(Fully Sharded Data Parallel)或者干脆先不用任何并行,先把数据加载、前向、反向、更新这四步跑通。之后切到多卡时,我推荐直接用 FSDP,配置不复杂,对注意力层和 MLP 层分别设置 sharding 策略即可。
一个可参考的工程配置是:
- 后端:PyTorch 2.x + FSDP
- 混合精度:bf16(如果是 A100/H100),FP16 需要在 loss 缩放上多花很多调试时间
- 检查点:每 500 步存一次,至少保留最近三个,防止训练中断
- 日志:用 W&B 或本地 tensorboard,记录 learning rate、gradient norm、loss、throughput
3. 数据工程:模型学不学得会,九成看这里
我在这个项目上踩过最深的坑都在数据上。很多人的第一反应是去网上下载一堆开源数据集拼接起来,但训练大语言模型的真正难点是数据配比和数据质量,这个环节做不好,模型结构再先进也白搭。
3.1 数据配比决定模型性格
预训练数据一般包含网页文本、书籍、代码、数学、论文等。不同配比直接塑造模型的"性格":
- 网页文本占比高,模型通用性、对话流畅度好,但逻辑推理偏弱。
- 代码和数学占比高,模型在结构化推理、步骤拆解上更有潜力,但早期 loss 降得慢,训练曲线会比较难看。
- 书籍数据过多,模型会变得"文绉绉"——长句表达华丽但不够简洁,指令遵循能力也容易跑偏。
对于一个小规模的预训练尝试,我建议配比是:网页文本 60%~70%,代码 15%,数学/科学 10%,书籍 5%~10%。后续如果想做推理能力强的模型,再逐步调高代码和数学的比例,但一定要一步步观察评估结果,不要一次性大改。
3.2 清洗和去重是没人愿意讲但最关键的细节
在公开数据集上,你会发现大量重复文本:同一个代码片段出现几万次,同一篇新闻被改写多次。如果不做去重,模型会把重复内容背下来,表现为生成时无意义地复读,在验证集上的困惑度虚低。我用过效果最稳定的工具组合是:MinHash 做近似去重,加上精确哈希做全量去重。先按 5-gram 计算 MinHash 签名,相似度超过 0.8 的文本聚类后只保留一个代表样本,然后把剩下的做严格逐字去重。中文数据还要额外注意 utf-8 编码里的全角、半角字符统一,否则"A"和"A"会被当成两个不同的 token,白白浪费词的表示空间。
清洗的时候,我也会做几个看起来不起眼的操作:
- 把所有 URL、邮件地址替换成占位符,减少无关 token 消耗。
- 过滤掉文档长度小于 200 字符的碎片,这类文本大多是格式残留。
- 对代码数据按文件扩展名过滤,尽量保留 .py、.js、.go、.cpp 等主流语言,去掉大量配置文件。
3.3 构造 thinking 数据:推理模型的入口在哪里
从 DeepSeek-R1 走红之后,大家最关心的就是怎么做出会"思考"的模型。这里要分清两件事:复现一个 R1 级别的强化学习流程不是小工程;但让一个小模型具备初步的推理能力,有一个更简单的路径——用现有推理模型的输出做蒸馏。
具体做法是:准备一批高质量问题,把问题和参考答案喂给 DeepSeek-R1 或 Qwen 的模型,让它输出完整的思考链(chain of thought),然后把这些思考链文本清洗后直接作为训练数据。实际上,OpenAI 在论文里也提到过类似的思路,用教师模型生成长思维链,再让学生模型学习,能让小模型在数学、代码任务上的准确率大幅提升。这不是玄学,本质上是把复杂的搜索和验证过程压缩进了参数量里。
蒸馏时有一个关键点:不要让模型直接学太长太啰嗦的思考链。训练时如果你的数据里思考链平均长度超过 5000 token,显存和训练时长都会翻倍,而且小模型会养成"没话找话"的毛病。我的做法是,先设定 2000 token 的思考链上限,把多余部分截断,再在 loss 计算时对非思考部分(比如用户输入、最终答案)做 weight decay 或直接 mask 掉——重点让孩子模型把精力放在学习推理路径上。
3.4 训练集和验证集要防止"污染"
评估模型时必须保证验证集和训练集没有重叠。最常见的意外是:验证集里的代码片段来自 GitHub 仓库 A,训练集里恰好也包含同一仓库的其他文件。文本指纹不同,但语义高度重叠。我建议用 MinHash 把训练集和验证集一起做去重,做到"验证集任意 8-gram 都不在训练集中出现"。这样评估出来的 loss 才是真实泛化能力的体现。
4. 训练循环与 Loss 调试:把"玄学"变成可解释的信号
训练大语言模型的过程里,你会发现网上说的很多东西跟实际操作起来不一样。Loss 不降,很多人第一反应是调学习率——但我在实际调试中发现,大多数时候问题根本不在学习率。
4.1 第一个观察窗口:梯度范数
启动训练后的前 200 步里,你应该重点盯梯度范数(gradient norm),而不是 loss 曲线。如果梯度范数在 0.1 到 10 之间波动,模型状态健康。如果梯度范数飙升到 100 以上,多半是某个层的输出出现了数值溢出。这时调低学习率只是掩耳盗铃,正确做法是检查数据里是否有异常样本(比如全角字符乱码导致的极长 token 序列),以及 LayerNorm 的 epsilon 是否过小。我在 2024 年踩过一次坑:某个数据集中混入了一份 20MB 的 hex dump 文本,BPE 之后 token 序列长度异常,峰值 loss 直接涨到 20+,排查了一天才定位到是数据问题。
4.2 Loss 曲线处于"平台期",正确的应对方式
预训练到一定步数,loss 不降是正常现象,不要慌张。在 100B token 级别的大模型训练里,你会看到 loss 长期横盘,然后突然跳降。这在术语里叫 phase transition,跟物理系统里晶格结构重排非常类似。训练初期模型在学词法和句法,中期在学事实性知识,后期在学复杂模式。对一个小模型来说,loss 平台期可能就是它在消化现有数据里的结构信息。
真正需要干预的信号是这几类:
- 验证 loss 开始上升,而训练 loss 还在下降——过拟合,说明训练数据多样性不足,或模型容量相对于数据量太大。
- loss 下降速度显著慢于同规模公开实验——检查数据配比,大概率是代码类数据比例太低。
- 梯度范数持续为 0——权重初始化严重错误,整个网络死掉了。
4.3 推理能力评估不能只看 loss
loss 低了,不代表模型会推理。想验证模型是否学到了逻辑能力,我在小模型阶段会跑四个快速测试:
- 加减法:随机生成一万个三位数以内的加减乘除,看模型输出的正确率。
- 代码补全:给定一个 Python 函数的 docstring 和前几行,看能否补出正确的后续代码。
- 中文常识问答:拿一些常识性 QA 数据做零样本测试。
- 指令遵循:用"请用一句话回答……"、"先总结,再解释"这类指令模板,看模型是不是把指令也当成了续写文本。
一个小模型的正确答案率可能只有 30%~50%,这没关系,关键是看它是"完全乱答"还是"思路对但计算错"。如果是后者,说明模型已经学到了推理模式的骨架,继续加数据和调学习率就能见效。如果是前者,你大概率把前两章里的某一步做错了,回炉查数据的配比和清洗流程。
4.4 从 0 到收敛的时间预期
拿单张 A100 80G 来说,训练一个 124M 参数、1.5B token 数据的模型,大约需要 12 到 20 小时。训练一个 350M 参数模型,同样数据量要 60 到 100 小时。如果你还没有这个算力条件,我建议先从 124M 开始,把数据管道、训练代码、评估脚本全部跑通,然后再买卡或者租卡放大。用小模型把流程跑通,是在为接下来的所有大模型工程攒经验值,这个步骤看着慢,实际上是最快路径。
5. 从训练完成到上线:推理工程里的那些坑
模型训完了,loss 也降下去了,但这只是完成了 60% 的工程。剩下的是推理服务化:模型的推理速度能不能支撑真实流量?显存占用能不能扛住并发请求?量化之后精度掉了多少?做这些时你会发现,训练时很顺手的大模型工具链,到了推理阶段要重新适配。
5.1 推理服务选型
开源推理框架里,vLLM 是我目前最推荐的。它在长序列推理上做得很好,PagedAttention 的核心思路是把 KV cache 拆成物理块,按需分配,显存利用率比传统方案高很多。在 serving 场景下,vLLM 的 continuous batching 机制也能让吞吐量上一个台阶。如果你部署的是 7B 级别模型,vLLM 是省心的选择;如果是 70B 级别,就要考虑 TensorRT-LLM 这类重度优化的方案了,不过它上手成本也高,需要你手动配置算子融合和精度策略,建议从 vLLM 起步。
5.2 显存估算公式,别再翻文档了
很多人问我:"我的 8 卡 A100 能部署多大的模型?"我直接给一个经验公式:推理时每 1B 参数约占 2GB 显存(FP16 权重),加上 KV cache 和激活,实际需要再乘 1.2 到 1.5。所以:
- 7B 模型 FP16 部署:约 14GB 权重,安全显存预算 24GB,单张 A100 80G 可以支撑两副本或一个较长上下文的副本。
- 14B 模型 FP16 部署:约 28GB 权重,单卡 80G 有富余,建议配 vLLM 开大 batch。
- 70B 模型:不用想了,单卡放不下,必须做张量并行,至少需要 2 张 80G 卡起步。
做量化时也要注意:GPTQ 的 4bit 量化在多数任务上精度损失很小(会有困惑度提升 0.5 以内的表现),但代码生成类的结构化输出往往放大误差。所以,对代码、数学类模型,我建议用 AWQ 或者干脆保 FP16,只做 bf16 转换;对通用对话类模型,INT8/GPTQ 就够用。
5.3 评测闭环是工程里最容易漏的一环
模型上线前还要做评测。很多人训完模型只看验证 loss,这不全面。我分享一下自己搭建的最小评测集,覆盖性能、质量和安全三类:
- 准确性类:数学(GSM8K 的抽样或自建算术题集)、代码(MBPP 的子集)、知识(MMLU 子集)。
- 质量和一致性:回答的中文流畅度、长度控制、上下文是否自洽。
- 稳定性和安全性:指示性拒绝(比如拒绝生成有害内容)、敏感话题的回复是否合规。
评测集不需要大,几十到几百条均匀覆盖即可,重点是每轮训练迭代后都跑一遍,记录变化趋势。如果某次训练后准确性提升但安全性下降,不要盲目追求前者,需要回头调整数据配比或采样率。
5.4 上线前的最后一公里
最后一步是把模型封装成外部的 API 服务。这里有两个容易忽略的工程细节。一个是动态 batch:vLLM 默认的 continuous batching 已经能应对大多数场景,但你需要设定 max_num_seqs 和 max_model_len,建议把 max_model_len 设置在训练时序列长度的 1.5 倍以内,超出会出错或显存溢出。另一个是流式输出:对对话类场景,必须启用 streaming,否则首 token 延迟会吓跑用户。流式输出在 vLLM 里就是加一个参数的事,但很多人到上线测试才发现前端已经等了几秒没反应,才知道要开,提前做就能省一次事故。
如果你把 seq len 拉长到 32K 或更长,还需要面对位置编码外推的问题。RoPE 在这类情况下通常会直接掉精度,你需要做 position interpolation 或用 YaRN 这类扩展方法微调。这也是我建议训练阶段就用 RoPE 的原因——后续扩展工具链更成熟,NTK 的兼容性也更好,传统正弦位置编码在这个阶段会比较难办。
6. 一个完整的日程参考:从小白到跑通全流程
很多朋友私信我,说看了几十篇教程还是不知道第一步干什么。我给一个 4 周计划的参考,它是我自己能完成闭环的最短时间,也适合有一定 PyTorch 基础的人。
- 第 1 周:环境与数据。搭好训练环境,跑通数据清洗和去重流程,构建 1.5B token 的预训练数据。
- 第 2 周:写训练脚本。用 PyTorch 从零实现一个 GPT-2 规模的模型,完成单卡训练、日志记录、checkpoint 存储。
- 第 3 周:训练与调参。用 124M 模型跑一轮完整训练,盯着梯度范数和 loss 曲线记录问题,完成两组学习率对比实验。
- 第 4 周:评估与部署。搭建推理服务,跑完最小评测集,如果数据里有思考链蒸馏数据,再做一轮蒸馏并对比评估结果。
每周末回顾:是否已经能解释自己模型的每个行为?如果评估结果不符合直觉,是否能从数据、超参、代码三个层面给出假设并验证?这是我判断学习是否真正发生在自己身上的标准,比网上任何课程和证书都真实。
从零训练一个模型,本质上是在训练你自己的判断力:判断什么数据值得喂给模型,判断 loss 曲线的细微变化意味着什么,判断部署流程里哪个环节会成为瓶颈。没有一个既定模板能保证成功,但我希望这篇文章能让你看到——ai engineering 的"从零开始"并不抽象,它是一系列具体决策的累积,而每个决策都可以通过小规模实验找到依据。如果你现在正要开始,从 124M 这个小目标起步,跑通闭环之后再谈规模,这会是让你少走最多弯路的那一步。