先讲一件让我推翻旧想法的事。去年我处理一批 GitHub Issue,顺手加载了一个在维基百科和书籍语料上训练的老牌 WordPiece tokenizer。结果 npm install 被切成了 n、pm、install,TypeScript 被切成四段。换成用代码和网页混合语料训练的分词器,同一个语料 token 数肉眼可见少了一截。那一刻我才意识到:分词器不是中立工具,它的训练数据就是它看世界的方式。

你可能会问:不就是一个切词工具吗?能差到哪去?都是子词单元,按理说重新组合应该没问题。问题在于,同一个词在两种 tokenizer 下可能被切得很不一样,这会直接影响 token 数、模型对词的记忆难度,以及处理未知词的行为。token 少了,模型能读到的有效内容就多了,成本也低了。
现在的语言模型大多用 BPE(Byte Pair Encoding)、WordPiece 或 Unigram 来训练子词词表。为避免混淆,我重点讲 BPE:初始化时把文本切成字符,然后统计每个相邻字符对的频率,把频率最高的一对合并成一个新符号,重复几万次。所以,一个词能否成为一个独立 token,只取决于它在训练语料里出现了多少回、跟谁一起出现。维基百科里「深度学习」「神经网络」高频出现,于是很快被合并;而「pre-trained」中间的连字符在 GitHub 上远比在百科里常见,所以它在两种语料里的合并时机完全不同。Hugging Face 的 Tokenizer 教程 对这几类算法有更完整的对比。
下面这张表可以快速看到维基百科和全互联网语料的本质差异:
| 维度 | 维基百科 | 全互联网(经清洗) |
|---|---|---|
| 文本领域 | 百科、历史、科学、人物 | 新闻、论坛、代码、社交媒体 |
| 语言风格 | 正式书面语 | 口语、俚语、中英混写、网络用语 |
| 标点与符号 | 规范标点,少量引号 | emoji、连续感叹号、URL、下划线 |
| 代码片段 | 极少,仅教程示例 | 大量真实代码、错误日志 |
| 多语言分布 | 按词条数量相对均衡 | 按真实网络内容分布,更不均匀 |
| 噪声水平 | 有编辑审查,较干净 | 有抓取残留、重复文本、机器生成内容 |
这些差异带来三个直接影响:
- token 效率。互联网语料训练出的分词器会把
TypeScript、MacBook、y'all这类高频率整词收进词表;维基百科分词器没见过那么多实例,就只能拆成词根或字节。这会直接拉长所有输入和输出的 token 数,也就是压缩了模型实际能看到的上下文。 - 领域适应性。代码模型 StarCoder 就是在代码语料上专门训练 tokenizer,才让
def、return、<div>这些模式在 token 层保持完整。通用分词器处理代码时,经常把一个关键字切成两半,模型学起来就费劲。 - 未知数据处理。维基百科文本很少出现网络表情和拼音缩写,一旦输入
lol或xswl,分词器很可能把它切到单字节。模型在注意力阶段对它的感知就变得非常局部,几乎学不到完整语义。
那是不是用全互联网数据就万事大吉?也不尽然。「全互联网」本身是个模糊概念,实际操作通常从 Common Crawl 这类数据集开始,经过去重、过滤、质量评分、语言采样,得到一份「看起来像互联网」的混合语料。如果采样有偏差,比如英语科技内容占绝对优势,词表里就会充满科技词,而医学、法律、小语种内容被边缘化。互联网上还有大量重复的营销文案,BPE 会把「click here」这种高频垃圾文本合并进词表,遇到正式文档就变成噪声。所以,好的 tokenizer 训练数据,本质上是为目标领域做混合配比。
所以实践中怎么选?
- 明确你的下游文本类型。做代码生成,就多放代码语料;做客服,就多放聊天记录和知识库。
- 先跑一个小的 BPE。用几千条样本训练一个临时 tokenizer,检查目标领域的代表文本能不能被自然切分,而不是只看词覆盖。
- 留一份验证集。比较候选 tokenizer 在验证集上的平均 token 数,以及罕见词是否被过度碎片化。token 数越低,通常意味着压缩效率越好,但不代表所有任务都好,还要人工看切分样例。
一个重要误区:tokenizer 能不能事后更换?
基本不能。语言模型的 embedding 矩阵和输出层都与词表严格对应,词表一变,整个权重结构都要重学。所以 tokenizer 必须在预训练前定死。这也意味着,如果你正在做一个小型项目,选一个在目标领域语料上训练过的 tokenizer,比随便选一个通用 tokenizer 再指望微调去弥补,要重要得多。
用维基百科训练的分词器是不是更适合学术文本?
总体上更接近,但不够全面。学术文章和百科语体接近,一些学科术语更容易完整保留。可学术文本里大量存在的公式、化学式、希腊字母,在百科里也不常见。E=mc^2 这种表达式,大概率被切成一个字母一个符号,而不是一个整体。
训练一个 tokenizer 需要多少数据?
不需要天量数据。BERT 的 WordPiece 用的是百科+书籍,约 33 亿词;GPT-2 的 BPE 用的是 40GB 网页文本。关键是语料构成是否覆盖了你关心的领域。如果你只做客服聊天,一个 5GB 的客服语料可能比 40GB 的网络杂烩更有效。
那我用微调来弥补 token 粒度问题不行吗?
很难。微调只能改参数,不能改词表。如果某个单词在预训练阶段被切成三个 token,微调很难学出完整词义。很多领域模型微调效果不佳,根源就在 tokenizer 没对上。
回到最初的问题。维基百科和全互联网训出来的分词器,差异不在「谁更好」,而在「谁更匹配你正在做的事」。维基百科提供高质量但狭窄的语体;全互联网提供粗糙但多样化的现实世界。我后来把项目里的 tokenizer 换成基于代码+网页混合语料训练的那版,TypeScript 和 JavaScript 都成了独立 token,代码段的 token 数明显下降。这个改变没有动模型结构,只是承认了一个事实:你对输入世界的假设,早就被写进了分词器的每一次合并里。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/774.html