← 返回文章与项目

记录

从零训练一个中文语言模型 - 详细版

从随机参数开始,训练一亿参数的中文模型,到能写出通顺短句。

从随机参数开始,训练一亿参数的中文模型,到能写出通顺短句。一共只花了四天,用了一张 RX 6800 XT 16G。从语料选择、预训练、到后训练(SFT、LoRA、DPO、GRPO),都可以实际做一遍。

感谢这个时代,让我能只用几天的工作量,就领略改变人类的历史的LLM。全程由Codex执行操作。

椅子、核弹、爆炸、瘫坐。

起因是我看到新闻,说质谱创始人唐杰在清华开课,课程需要学生需亲手走一遍大模型全链路,具体包括:从零编写Tokenizer和Transformer,端到端训练一个0.1B模型;手写Triton attention kernel并自行测试多卡训练和推理增益;从raw dump清洗语料,拟合scaling law并进行外推;在同一基座上对SFT、DPO、RLVR进行对照实验;最后搭建可验证环境和harness,训练长程Agent并鼓励self-judge loop。

有这一句报道就够了,AI时代只需要问题和好奇心。

训练概况

图片

先放最终效果,预训练和后训练后的对比:

图片

=== 训练前准备 ===

训练速度和规模

按 Chinchilla 的计算预算最优经验,“每个参数约 20 个训练 token” [1],0.1B 模型对应约 2B tokens。

稠密 Transformer的主要训练计算量约为 C ≈ 6 × N × D。N 是参数数,D 是累计训练 token 数。

6ND 包含前向计算2 ND(每个输入1次乘法1次加法,输出 = 输入₁×权重₁ + 输入₂×权重₂ + ……)和反向计算4ND 倍的(计算权重梯度、输入梯度各两个矩阵乘法,每个2ND运算)。6 × 0.1B × 2B = 1.2×10¹⁸ 次浮点运算,也就是1.2e6 TFLOP,我的6800XT 算力为20 TFLOP/s(要16小时),5090 是200 TFLOP/s

因此,语料随模型规模线性增长,计算量也就随之平方增长。

RTX 5090能训多大的模型

除了训练计算量,显存也会随模型增加而增加。

0.1B模型虽然最终 FP16 权重只有约200 MB。单训练显存中,则需要参数占FP32 400M,梯度400M,AdamW保存的两份梯度统计量800M,模型状态共1.6G,这部分随参数量线性增长。其它中间计算结果等实测是6.4GB,随参数量非线性增长。

normal;">项目 RX 6800 XT 16G RTX 5090 32G
约0.1B训练2B tokens 34小时 本机实测 约3.9~7.8小时假设利用率20%~40%
最大可训练容量 0.1B实测6.4GB 0.3B约14.8 GB,306小时 0.7B约28.6 GB0.8B约31.8 GB,320小时

 

小模型能做什么

典型例子就是OCR,付费OCR现在完全没有生存的意义了。

OpenDoc参数只有0.1B,部署下来只占1.2G内存,CPU可跑,几秒一页pdf。可以看我上一篇文章

图片

OCR识别Attenion Is All You Need

图片

=== 预训练 ===

预训练让模型不断练习“根据前文预测下一个 token”。训练时把真实后文作为答案,预测越偏离它,损失越大;反向传播据此调整参数。训练完成后,就可以输入文字,让模型续写。

中文语料选择

语料 公开规模或本次用量 适合做什么
Ultra-FineWeb 中文 [4] 约120B tokens 已筛选的网页,带来源与评分,便于抽样对照
Ultra-FineWeb-L3 中文 [5] 超过200B tokens 网页转问答、多文体改写,适合比较合成增强效果
MiniMind 配套语料 [6] 本次清洗编码后1.476B tokens 获取门槛低,适合先完成中文训练与续写实验
CCI 3.0 HQ [7] 约500 GB 多来源中文互联网正文,适合研究来源配比
ChineseWebText 2.0 [8] 约3,800 GB 带质量、领域标签,适合按领域筛选

图片

图片

预训练过程和效果

先用 10M 参数的小模型做了四组对照,每组训练 0.2B tokens:Ultra-FineWeb、 Ultra-FineWeb L3、MiniMind,前两个因为token很多,做了随机采样和选取高分。

试完以后MiniMind损失更低一些。所以决定正式训练,先训练MiniMind 1.476B tokens;然后再尝试Ultra-FineWeb L3继续训练2B tokens。

MiniMind训练完以后效果最好,再继续用 Ultra-FineWeb L3,反而综合困惑度上升了。第三方是从网上找的第三方语料。

图片

=== 后训练 ===

有了会续写的模型,下一步是让它按问题作答、遵守格式,并提高好答案的概率。我从同一个 MiniMind 基座开展 SFT 和 LoRA 对照,再从同一个 SFT 保存点分别开展 DPO、GRPO。这样能区分每种方法带来的变化。

图片

监督微调SFT

SFT 给模型看“问题—标准回答”示范,例如输入“只输出计算结果:7+8”,目标回答为“15”。训练主要对回答部分计算损失,提高目标回答逐个token出现的概率。与预训练相比,输入结构和被要求学习的文本位置发生了变化。

图片

我的训练集共25,000条:20,000条来自 BELLE 中文指令数据,覆盖问答、分类和改写;另外5,000条自建示范包含2,500条加减法、1,250条字符串提取、1,250条JSON输出。BELLE提供中文指令多样性,自建题提供能严格判分的任务。[9]

normal;">实验 数据与训练方式 保存点 训练耗时/峰值显存
SFT 5k 4,000条BELLE+1,000条规则题全参数更新 每遍1份,共3份 4.87分钟/4.69 GiB
SFT 25k 完整25,000条全参数更新 每遍1份,共3份 21.84分钟/5.73 GiB
LoRA 25k 相同25,000条更新589,824个低秩参数 每遍1份,共3份 21.77分钟/4.62 GiB

 

三组都训练3遍。两组全参数SFT均在第1遍取得最低验证损失;LoRA在第3遍最低。

LoRA低秩微调,是为了减少训练量和显存消耗。它冻结已经训练好的参数,只训练额外的低秩矩阵,真正推理时,用原有参数计算出的,和微调参数计算出的相加,来获得最终输出。 本次LoRA相对25k全参数SFT,节省19.34%的峰值显存,耗时只减少0.32%。我还没看为啥只节省这么点。

直接偏好优化DPO

DPO给同一道题配两个答案,并标出较好和较差。它通过对比当前模型与固定参考模型对这两个答案的相对概率,强化指定偏好。数据直接提供答案之间的优劣关系。

图片

我使用2,000对数据:1,000对选自 LLaMA Factory 的 DPO-En-Zh-20k 中文部分,另1,000对自建算术和格式题。自建题用正确答案作优选,再通过错误数字、漏字段或多余文本构造较差答案。公开数据补充自然语言偏好,自建题让优劣依据可验证。[10]

组相对策略优化GRPO

GRPO让模型对同一道题现场生成多个答案,再在这组答案内部比较奖励。比如一道加法题生成4个答案,有1个正确、3个错误,就强化正确答案相对其它答案的生成倾向;更新时加上约束,限制模型一次变化过大。

图片

这次GRPO实际上效果很一般。最初准备7,000道题;启动试验中,100道题仅7道出现“同组既有对也有错”。对这种小模型,题目太难时,四个答案经常全错,组内比较提供不了有效的好坏差异。

随后从原训练池筛出301道较易题:215道操作数0~20的算术题、43道提取题、43道JSON题。重新检查达到19/100,才开始正式训练;

结果是,独立测试算术从SFT起点的16/200提高到19/200,仅增加1.5个百分点,没什么用,属于意思意思走个流程。

后训练效果

把预训练基座和5个后训练模型放到同一套评估中:每个模型各回答500道验证题、500道独立测试题,并完成100条续写。每套500题中,200道算术、50道字符串提取、50道JSON可自动判分;其余200道开放中文题保留原文另评。

图片

=== 附录 ===

图片

最后,我问:

“请用一句话介绍春天”

模型耗时0.375秒,生成16 tokens回答:

“春天是一年中最美好的季节之一,它带来了温暖、新生和希望。”