纸上得来终觉浅,须知此事要躬行
“低成本实践”这个名字有两个来由。一是前阵子和孩子看了一部电视剧,叫《低智商犯罪》,觉得这个名字挺有意思;二是这些实验确实是在有限资源下完成的。这里的低成本,不只是少用几张 GPU,也包括尽量利用开源模型、开源语料和公开论文,把一个原本只有大公司才能做的项目,缩小到个人也能跑起来的程度。
训练 GPT 选择的任务是中英机器翻译。
机器翻译大概经历过三个时期。第一代是统计机器翻译,核心可以写成 P(T|S) ∝ P(S|T) × P(T):一边是翻译模型,一边是目标语言模型。第二代是以 RNN、Seq2Seq 和 Transformer 为代表的神经机器翻译,模型能力提高了,但需要海量双语平行语料。第三代则是大语言模型:先通过 Next Token Prediction 学习语言,再通过 Prompt、SFT 和偏好训练,让一个通用模型完成翻译。
前两代机器翻译流行的时候,也都没有真正做过。统计时代在训练 LDA,神经机器翻译时代主要做了 Word2Vec,后来又做了一些 BERT。机器翻译一直更偏 Research,既没有机会做,也确实不会做。到了大语言模型时代,开源模型、训练框架和数据都已经比较成熟,反而给了个人一次补课的机会。
把评估搞明白
机器翻译过去最常用的指标是 BLEU。它大致计算预测译文与参考译文之间的 N-gram 重合度。这个指标简单、稳定,也用了很多年,但它更关心字面是否相似。一个意思正确、甚至表达更自然的译文,只要和参考答案写得不一样,也可能得到较低的分数。
COMET 则是一个学习出来的翻译评估模型。它同时读取源句、参考译文和模型译文,再给出质量分数。到了大语言模型时代,翻译结果越来越多样,仅靠字面重合已经不够,COMET 这类指标的重要性也越来越高。
评估方式并不是实验结束后才补上的报表,它会反过来决定训练方向。CPO 需要从多个候选中选择更好的译文,GRPO 也需要奖励信号。如果没有一个相对可信的自动指标,偏好训练和强化学习就无从谈起。
Interpreter:由 Qwen3 开始
第一条路线放在 Interpreter 仓库里。我参考了 ALMA 的做法,但把任务收缩到中英互译,底座也换成了 Qwen3-1.7B-Base。Qwen3 本身已经见过大量中英文语料,1.7B 的规模又能放进消费级显卡,适合作为低成本实验的起点。
训练分为三个阶段:
- SFT:使用约 3.68 万条清洗后的 ALMA/X-ALMA 平行数据,让模型稳定理解翻译指令。
- CPO:让 SFT 模型为同一源句生成多个候选,再用 COMET 选出较好和较差的译文,构造约 4.4 万条偏好数据。
- GRPO:以 COMET 作为主要奖励,对模型继续做全参数强化学习。
最终在 WMT23 上得到下面的结果:
| Stage | Zh→En BLEU | Zh→En COMET | En→Zh BLEU | En→Zh COMET |
|---|---|---|---|---|
| Qwen3-1.7B-Base(5-Shot) | 21.83 | 0.7950 | 41.15 | 0.8490 |
| + SFT | 19.65 | 0.7863 | 40.74 | 0.8384 |
| + CPO | 19.16 | 0.8017 | 32.69 | 0.8507 |
| + GRPO | 20.31 | 0.8053 | 33.69 | 0.8540 |
| SFT → GRPO(跳过 CPO) | 22.85 | 0.8003 | 41.97 | 0.8540 |
| HY-MT1.5-1.8B(参考) | 17.84 | 0.8052 | 31.74 | 0.8669 |
亲手跑过以后,能很清楚地看到所谓的 Alignment Tax。SFT 之后,模型在四项指标上反而都不如 Base 的 5-Shot;CPO 明显提高了 COMET,却损失了不少 BLEU;GRPO 又把效果往前推了一步。另一个意外结论是,CPO 并不是必需的。调好参数以后,直接走 SFT → GRPO,既能保持较高 BLEU,也能取得相当的 COMET。
这套训练不能说没有成本,但整个流程可以在单张 RTX 4090 上完成。它和大规模预训练当然无法相比,却已经足够让我把 SFT、偏好数据构造、CPO、GRPO 和多测试集评估完整走一遍,而不只是停留在论文和代码片段里。
Summer:动一下底座模型
后训练做完以后,问题又回到了预训练。Qwen3 使用 119 种语言、36T Token 训练,这显然不属于个人能够复现的“低成本”。但底座模型也不是完全没有可以动手的地方。
如果任务只有中英互译,Qwen3 原生词表会显得有些冗余。于是又做了 Summer:把 Qwen3 的原生 Tokenizer 换成面向中英文的 Piece Tokenizer,再通过继续预训练恢复模型能力。这类工作通常叫 ReTok。
ReTok 大概分为三步。第一步,用旧 Tokenizer 拆解新词,用旧词 Embedding 的平均值初始化新词;第二步,冻结 Transformer 主体,先训练新的 Embedding 和 LM Head;第三步,放开全部参数,使用混合语料继续预训练。最终的 v18 模型使用约 10 亿 Token 做第一阶段恢复,再用约 2 亿高质量 Token 退火。
这个实验没有得到一个“换了 Tokenizer 就全面变强”的漂亮结论。换词表会直接破坏底座模型已经学到的能力,恢复过程比预想中困难。ReTok 底座的 5-Shot 翻译明显弱于原始 Qwen3;但继续执行同样的 SFT、CPO 和 GRPO 后,差距又被追回了大半:
| Stage | Zh→En BLEU / COMET | En→Zh BLEU / COMET |
|---|---|---|
| ReTok Base(5-Shot) | 17.44 / 0.7582 | 38.10 / 0.8255 |
| + SFT | 19.34 / 0.7762 | 40.09 / 0.8392 |
| + CPO | 18.11 / 0.7941 | 31.38 / 0.8480 |
| + GRPO | 18.43 / 0.7967 | 31.79 / 0.8511 |
这至少说明两件事。第一,Tokenizer 并不是一个可以随便替换的前处理组件,它已经和模型参数深度绑定;第二,底座模型只要还在某个基本门槛之上,后训练确实能够重新塑造它的任务能力。ReTok 没有超过原始 Qwen3,但它让我真正碰到了预训练中的词表、Embedding 初始化、数据配比、冻结恢复和全参数继续训练。
为什么还要做
其实也经常怀疑这些项目的意义。现在的大语言模型写代码、写文章的能力已经超过绝大多数人,很多用户需求也直接交给模型了。那为什么还要自己训练一个翻译模型?是为了弥补当年没有做过机器翻译的遗憾,还是为了弄清大语言模型的技术细节?
后来觉得,人还是有非理性的一面。机器可以天然地 Loop 下去,但人会怀疑、会厌倦,也会因为不认输而再试一次。也许正是这种不够理性的部分,才会让人去做一些明明不合算、也不一定成功的事情。
项目与模型
- GitHub:Interpreter
- GitHub:Summer
- Hugging Face:Interpreter-Qwen3-1.7B
- Hugging Face:Qwen3-1.7B-Base-ReTok
- Hugging Face:Interpreter-Qwen3-1.7B-ReTok