分词器和大模型的关系
很多人觉得分词器是大模型的一部分,其实它有自己的训练流程。简单说:先拿正则把原始文本整理一下,再统计出一套词表,把文字片段和数字ID对应起来。 这个对应方式决定了模型看到的是字、词,还是更碎的片段。直接影响后面模型学得好不好。
训练分词器的四步
1. 准备语料
- 多找不同类型的文本:小说、散文、不同语言(中英法韩...)
- 清洗:去掉乱码、统一成UTF-8、删掉重复的内容。
- 脱敏 :把姓名、电话、邮箱换成
[NAME]、[PHONE]。
这不光是为了合规,还能减少那些只出现一次的低频词,让分词器专心学常见模式。 - 多语言的平衡 :如果中文200G、英文150G、法语仅5G,不可直接混在一起训练。
可以少点中文,或者多加点法语,让比例均衡一点(比如4:4:1:1)。留1%当验证集,看看各语言切的情况。
2. 初始单元(预分词)
三种常见做法:
- 按空格和标点切:把标点单独拆开。适合英语这类用空格分词的语言。
- 按Unicode类别切:连续汉字、连续字母、连续数字、标点各成一块。多语言混合时很好用。
- 字节级切 :每个字符转成UTF-8的字节(英文1字节,中文3字节)。
好处是永远不会遇到不认识的字,任何字符都能处理。但一开始切得太细,要多合并几轮才能变成合理的token。
字节级预分词的好处:合并更自由、支持多语言、几乎没有未知词、推理更快。
3. 统计、合并、迭代
不同算法:
- BPE:每次都找出现次数最多的相邻字符对,把它俩合并。简单高效。GPT、LLaMA在用。
- WordPiece:不是光看频率,而是看合并后能不能让整个语料更像自然语言。BERT在用。
- Unigram:先搞一个大词表,然后一步步淘汰概率低的token。对低频词更友好。T5、Gemma在用。
- SentencePiece:这不是新算法,是个框架。它连空格都当成一个特殊字符,自己就能分词。内部可以用BPE或Unigram。LLaMA、DeepSeek都在用。
训练的时候要保护好特殊token(比如<PAD>、<UNK>),不能让它们被合并或删掉,不然就乱了。
什么时候停:词表够了,或者再合并也省不了几个token了,就停。
4. 输出
- vocab文件:token和ID的对照表。
- merges文件:合并规则(BPE)或者概率模型。
以后想加新词,最好增量训练或加几条合并规则,不用从头训。 管好版本,训练和推理必须用同一个分词器。
四种分词器对比
- 字符级:太细,句子会变得很长,模型看不过来。
- 字节级:每个字节就是一个token,压缩比永远是1,完全不压缩。但很稳。
- 词级 :一个词一个token,语义完整。但词表太大(look、looks、looked都是不同ID),遇到新词就变
<UNK>。 - BPE:折中方案。把常见的子词合并,既能压缩文本,又很少遇到未知词。GPT-4、Llama 3
DeepSeek的分词器的特别
DeepSeek Coder用的是字节级BPE,词表大概32022。 如果用convert_ids_to_tokens看中文,会看到一堆乱码一样的东西(比如注æĦı)。这不是bug。 因为词表装不下所有汉字,它对中文用了UTF-8字节级兜底。用decode就能变回正常中文。
内部用latin-1编解码? 因为汉字或emoji拆成单字节后,用UTF-8解码会出错。latin-1是单字节编码,能把0~255每个字节直接映射成一个字符,保证数据不丢。这样BPE就能安全地把字节当成"字符"来合并。
扩展思考
- 视觉信息能不能帮分词器?
- 能不能让分词器继续学习?
- 让分词器学会"怎么分词"
分词器是大模型的第一道门槛。选啥算法、用啥语料、要不要字节级兜底,都影响效果和速度。现在主流基本就是字节级BPE加SentencePiece框架,但多语言平衡、脱敏、怎么加新词这些细节,是难点