训练分词器

5,368 字 · 预计阅读 15 分钟

上一节看到,Qwen3.5 的词表有 24.8 万个 token。如果我们的迷你模型直接用它,会发生什么?

算一下:迷你模型每个 token 用 512 维,词嵌入矩阵就是 248320 × 512,约 1.27 亿个参数。

为什么词表一大,词嵌入就跟着大?上一节讲过,词嵌入是一张表,词表里每个 token 占一行,每行 512 个数字。

词表有多少个 token,这张表就有多少行:248320 行 × 512 列,就是 1.27 亿个数字。

而整个迷你模型计划只有两千多万参数。光是一本"词典",就比整个模型大四五倍。

所以小模型要配一本小词典。这一节我们用上一章下载的预训练语料,训练一个只有 8192 个 token 的分词器。

学完你能做到:讲清楚 BPE 是怎么一步步"学"出词表的,知道词表大小怎么取舍,并且得到一个能直接用于预训练的分词器。


一、BPE:从字节开始,一步步合并

现在主流模型用的分词算法,大多是 BPE(字节对编码)或它的变体。它的思路很朴素:

  1. 一开始,词表里只有 256 个字节。任何文字都能拆成字节,所以从一开始就不会有"不认识的字"。
  2. 统计语料里哪两个相邻的 token 一起出现得最多,把它们合并成一个新 token,加进词表。
  3. 重复第 2 步,直到词表达到预定的大小。

拿中文举个例子。先说清"字节"是什么:电脑里的所有文字,最后都存成一串数字,每个数字就是一个字节,大小在 0 到 255 之间,一共只有 256 种。

文字怎么变成字节,有一套通用的规则,叫 UTF-8:一个英文字母占 1 个字节,比如"A"就是 65;一个汉字通常占 3 个字节,比如"天"是 229、164、169 这三个数。

所以词表一开始放进这 256 个字节,就像拿到了 256 种最小的积木:不管什么字、哪国文字,甚至表情符号,都能用它们拼出来。BPE 接下来做的,就是把经常挨在一起的积木粘成更大的一块。

训练刚开始时,"天"是 3 个字节 token;因为这 3 个字节总是一起出现,很快就会被合并成一个"天"字 token。

再往后,"天"和"气"经常挨着,又被合并成"天气";如果语料里"今天天气"出现得足够多,连这四个字都会合成一个 token。

BPE 从字节开始:3 个字节合成一个字,两个字再合成一个词

合并的顺序就是一张规则表。分词时,按同样的顺序把新句子里能合并的地方合并起来,就得到了 token。

用一个极小的例子走一遍。为了看得清楚,这里把每个汉字当作一个起点,省掉字节合并成汉字那一步。假设语料只有三句话:

天气好   天气冷   今天天气好
轮次 出现最多的相邻组合 合并后的结果
第 1 轮 "天"+"气",出现 3 次 天气 好 / 天气 冷 / 今 天 天气 好
第 2 轮 "天气"+"好",出现 2 次 天气好 / 天气 冷 / 今 天 天气好
第 3 轮 剩下的组合都只出现 1 次,按规则任选一个继续,或者词表满了就停

三轮过后,词表里多了"天气"和"天气好"两个 token。真实的训练要在几十 MB 的语料上做几千次这样的合并,原理完全一样。

画成积木是这样的,每一轮都把挨着出现最多的那一对粘成一块:

BPE 合并过程:每一轮数一数哪两块挨着出现得最多,就把它们粘成一块

这两轮也留下了一张规则表:第 1 条,"天"+"气"→"天气";第 2 条,"天气"+"好"→"天气好"。

前面说"分词时按同样的顺序合并",就是拿新句子照着这张表一条条做。比如来了一句没见过的"明天天气好":

一开始:   明 天 天 气 好
按第 1 条:明 天 天气 好
按第 2 条:明 天 天气好

最后切成"明""天""天气好"三个 token。训练是"学规则",分词是"用规则":用的时候不再数数,只照着表做。

你可能听说过,处理中文要先"分词",比如用 jieba 这类工具把句子切成词语。

BPE 不需要这一步:它不懂什么是词,只看统计,哪些字经常挨在一起就合并哪些。

好处是不依赖任何词典,新词、网络用语、中英混杂的句子都能处理。

代价是它合出来的 token 不一定是语言学意义上的词,比如下面会看到的"我们去""模型的"。对模型来说,这并不影响它学习。


二、词表开多大

词表大小是一个取舍:

词表小 词表大
词嵌入和输出层 参数少 参数多
同一段话切出的 token 多,序列长,算得慢 少,序列短,算得快
生僻词 拆得很碎 更可能是完整的 token
适合 小模型 大模型、多语言模型

表里这几行,各自是怎么来的:

  • 参数多少:词嵌入表每个 token 一行,词表多一个 token,表就多一行 512 个数字。我们的迷你模型,输出层和词嵌入共用这张表,所以两头一起变大。
  • 序列长短:词表小,能收进去的"大积木"就少,同一句话只能用更多小积木拼。第四部分会看到,"大语言模型的推理速度主要受内存带宽限制。"这句话,我们 8192 的词表切出 14 个 token,千问 24.8 万的词表只要 11 个。每个 token 都要走完模型的每一层,token 越多,计算越多;上下文长度也是按 token 算的,token 越多,同样大的窗口装下的字就越少。
  • 生僻词:词表里没有的词,只能拆成更小的块,最碎的时候会拆回单个字,甚至拆回字节。

几个真实模型的词表大小:MiniMind 用 6400,Mistral 早期版本用 32000,Llama 3 用约 12.8 万,Qwen3.5 用约 24.8 万。

模型越大,词嵌入在总参数里占的比例越小,词表就可以开得越大。

本文是会员内容

全文 5,368 字,已试读约 29%。开通专业版可阅读全文,并解锁全部官方课程与后续更新。

开通专业版

支持 7 天无理由退款 · 早鸟价 99 元/年(售完恢复365/年)

课程中涉及的第三方项目,其著作权与商标归各自权利人所有;引用处的署名与许可见《开源与来源说明》。