Tokenizer是什么?——文本到数字的翻译官
Tokenizer是LLM的翻译官。它把人类能看懂的文字(你好世界),翻译成模型能处理的数字([1, 45, 678, 23])。没有Tokenizer,模型无法理解任何文字。
为什么要Tokenize?神经网络只认识数字。它无法理解你好这两个字,但它能理解数字1和数字45。Tokenizer就是把文字映射到数字的桥梁。
Tokenization完整流程:1.文本输入→2.分词(把文本切成小块)→3.映射到ID(每个token对应唯一整数)→4.输入模型(ID转换成向量)→5.输出解码(模型输出ID,再翻译回文字)。
为什么不用单个字符?如果每个字符是一个token,英文26个字母,中文几万个汉字。但unhappiness有12个字符,如果是一个token,模型只需一步处理。而且词比字符更有语义。
为什么不用单个词?英语有100万+单词,中文词更多。如果每个词是一个token,词汇表太大。而且新词不断出现(如bitcoin、ChatGPT),模型无法处理新词。
解决方案:子词(Subword)Tokenization。把词拆成更小的、有意义的部分。例如:unhappiness → un + happiness。既减少了词汇表大小,又能处理新词(un + known = unknown)。
主流Tokenizer对比:
| Tokenizer | 算法 | 代表模型 | 特点 |
|---|---|---|---|
| BPE | Byte Pair Encoding | GPT-2/3/4, LLaMA | 合并最频繁的字符对,简单高效 |
| WordPiece | 贪婪子词分割 | BERT | 选择使语言模型概率最大的子词 |
| SentencePiece | 自监督学习 | LLaMA, T5 | 不依赖语言,直接处理原始文本 |
| Byte-level BPE | 字节级BPE | GPT-2 | 用256个字节表示所有语言,词汇表极小 |
BPE算法:最聪明的合并游戏
BPE(Byte Pair Encoding)是GPT系列使用的Tokenizer算法。它的核心思想:反复合并文本中最频繁出现的字符对,直到词汇表达到目标大小。
BPE完整步骤(简单例子):
假设训练语料只有4个单词(已拆分成字符):low → l,o,w;lower → l,o,w,e,r;newest → n,e,w,e,s,t;widest → w,i,d,e,s,t。
初始词汇表:所有字符 {l,o,w,e,r,n,s,t,i,d} = 10个token。
第1轮:找最频繁的字符对。统计相邻字符对:l-o:2次,o-w:2次,w-e:2次(newest, widest),e-s:2次(newest, widest)。w-e和e-s并列最频繁(2次)。
合并we:把w和e合并成新token we。词汇表=11个token。文本变成:low→l,o,w;lower→l,o,w,e,r;newest→n,we,s,t;widest→w,i,d,e,s,t。
第2轮:再找最频繁。o-w:2次(low, lower)。合并ow:low→l,ow;lower→l,ow,e,r。
重复这个过程,直到词汇表达到目标大小(如GPT-2的50,000)。
BPE的优雅之处:频率驱动(常见组合如ing、er、tion自动合并为token)、处理新词(没见过ChatGPT?拆成Chat + GPT)、词汇表大小可控、多语言友好(Byte-level BPE用256个字节)。
参数表:
| 参数 | 含义 | 典型值 | 太大/太小 |
|---|---|---|---|
| vocab_size | 最终词汇表大小 | 32K, 50K, 100K | 太大→embedding层过大;太小→token序列过长 |
| min_frequency | 合并的最小频率 | 2 | 太大→错过常见组合;太小→合并噪声 |
| special_tokens | 特殊token | [CLS], [SEP], [MASK] | 根据模型架构定制 |
中文Tokenizer的特殊挑战
中文没有空格,这是最大的挑战。英文Hello world天然有空格分词,中文你好世界没有空格。中文Tokenizer必须自己决定切分位置。
中文Tokenizer的三种策略:
1. 字符级:每个汉字是一个token。优点:词汇表小(几千个常用汉字),不会遇到未登录词。缺点:序列太长。今天天气很好=7个token,但语义上只有3-4个概念。
2. 词级:用分词工具(如jieba)先切词,每个词是一个token。优点:语义完整。今天天气很好=3个token(今天/天气/很好)。缺点:词汇表巨大(几十万个词),新词OOV严重。
3. 子词级:BPE在中文中的表现。BPE能发现有意义的组合:快乐→快+乐(BPE可能合并为快乐,因为这对很常见);不快乐→不+快乐;超级快乐→超级+快乐。
中文Tokenizer实践建议:
| Tokenizer | 适用场景 | 中文表现 |
|---|---|---|
| BERT-wwm | 中文NLP任务 | Whole Word Masking,整词掩码 |
| ChatGLM-Tokenizer | 中文对话 | 针对中文优化,中英文混合效果好 |
| SentencePiece | 多语言模型 | 不依赖空格,中文/英文/日文统一处理 |
| Qwen-Tokenizer | 中文大模型 | 针对中文词汇表优化,扩展性好 |
代码实战:用HuggingFace训练自己的Tokenizer
例子:对比不同Tokenizer的编码结果
原文:unhappiness
字符级:u,n,h,a,p,p,i,n,e,s,s = 11个token
词级:unhappiness = 1个token(如果在词汇表里)
BPE(GPT-2风格):un + happiness = 2个token(如果un和happiness都是常见子词);或un + happy + ness = 3个token(如果happy更常见)
结论:子词级Tokenizer在词汇表大小和序列长度之间取得了最佳平衡。BPE能自动发现最有价值的子词组合。
另一个例子:中文
原文:人工智能技术
字符级:人,工,智,能,技,术 = 6个token
词级(jieba):人工智能, 技术 = 2个token
BPE(中文优化):人工 + 智能 + 技术 = 3个token(如果这三个子词常见);或人工 + 智 + 能 + 技 + 术 = 5个token(如果智能未被合并)
这取决于训练语料中哪些子词组合最常见。
练习:Tokenizer
Q1:为什么英文用空格分词,但中文用空格分词效果差?
Q2:BPE的核心思想是什么?为什么它能处理新词?
Q3:假设BPE训练语料中chat出现100次,bot出现50次,chatbot出现30次。如果词汇表已满,BPE会合并哪个对?
Q4:中文Tokenizer用字符级有什么优缺点?用词级有什么优缺点?
Q5:vocab_size=10000和vocab_size=100000分别对模型有什么影响?
查看答案
A1:英文是拼音文字,空格天然分隔单词。中文是意音文字,没有空格,每个字独立但组合成词才有完整含义。人工智能分开意义不同,人工智能组合才有完整含义。
A2:BPE的核心思想是反复合并语料中最频繁出现的字符对,形成子词。它能处理新词因为新词可以拆成已知的子词。例如ChatGPT未见过,但可以拆成Chat + GPT(如果这两个子词在词汇表中)。
A3:BPE会合并出现最频繁的字符对。chat(100) + bot(50) = 需要看相邻对。chatbot中的chat和bot相邻出现30次。如果ch和at等子词更频繁,会先合并它们。具体取决于整个语料的频率分布。
A4:字符级:优点→词汇表小(几千字),不会OOV;缺点→序列长,语义碎片化。词级:优点→语义完整;缺点→词汇表大(几十万个词),新词OOV严重。
A5:vocab_size=10000:embedding层小,但每个token代表的语义信息少,序列长(一篇长文可能需要1000+token)。vocab_size=100000:embedding层大(增加模型参数),但每个token更语义化,序列短。需要平衡:通常32K-50K是最佳点。