01
分词与 token
能解释模型为什么按 token 处理文本,能用代码数出 token,能说清中文为什么更费 token
前置:无预计:45 分钟
模型看到的东西
模型不读字符,读整数。文本先被切成 token,每个 token 对应词表里的一个 ID;embedding、注意力、上下文上限和计费都按 ID 的数量算。
- token 不等于字:常见英文词可能只占一个 token,汉字常被拆成两三个。
- token 也不等于词:低频词会被拆成更小的片段,极端情况落到 UTF-8 字节。
- 同一个字符串,换一套词表,token 数就会变。token 数只在同一模型内可比。
BPE 怎么切
BPE 从字节开始。训练时反复统计相邻字节对,把出现最多的一对合并成新符号,记下规则;编码时按训练得到的顺序重放这些规则。
训练:l o w e r → 合并 (l,o) → lo w e r → 合并 (lo,w) → low e r
编码:新文本按同样的顺序套规则,命中的合并,没命中的保持字节。
词表大小 = 256 个字节 + 学到的规则数。规则越多,常见片段越完整,token 越少,词表也越大。
试一下
code/tokenizer.py 是一个只用标准库的最小 BPE,code/test_tokenizer.py 用它训练并打印几段文本的 token 数:
python3 code/test_tokenizer.py
输出有三列:文本、UTF-8 字节数、token 数。英文常见词会明显压缩,中文几乎不动。
为什么中文更贵
词表主要被英文语料占据,中文常用词拿不到足够的合并规则,最后退回字节:一个汉字在 UTF-8 里占 3 字节,常见是 1–3 个 token。英文一个词往往一个 token。同样的意思,中文的 token 数通常更高。
具体差多少取决于词表,要用目标模型的 tokenizer 实测,不能拿别的模型的结果换算。
边界
- 不同模型的词表不同,token 数不能跨模型直接比较。
- 这里只讲机制,不讲训练分词器时怎么选语料、怎么定词表大小。
- 词表大小会反过来影响模型:词表大,序列短,但 embedding 和输出层更占参数。
验收
python3 code/test_tokenizer.py
看到每段文本的 token 数、最后的 ok,并能解释中英文两列差距的来源。