语言的“颗粒度”:我们到底在切什么?
我们都知道模型要处理文本,第一步是把一段段字符变成“token”。但这些 token 究竟应该是句子、单词,还是更小的片段,比如“un + break + able”?
这背后涉及的是一个非常核心的问题:我们到底用什么单位来让模型“看懂”语言?这个单位,就叫做 token,而设计这个单位的方式,就是 tokenizer。
Tokenizer 就像语言世界的切割刀,它决定了模型从多大、从哪里开始理解文本。粗了,信息不够细;细了,理解变得困难。
Tokenizer 的作用:不仅是切词,更是理解的“格式”
我们不妨打个比方:如果把语言模型比作人脑,那 tokenizer 就是它的“眼睛”。一双合适的眼睛,能帮助我们快速捕捉信息;而模糊不清的视野,只会增加理解的负担。
当你读到“unbelievable”,你可以立刻意识到它是“un + believe + able”构成的,这种构词结构能让你快速理解它的意思。如果 tokenizer 能切出这样的结构,模型自然也能更快学到“构词法”。
而如果 tokenizer 把它切成了“u + n + b + …”,模型可能就要花更多精力才能拼凑出“哦,这是一个否定+动词+形容词构成的词”。
多种颗粒度下的 Tokenizer
颗粒度 | 示例 | 优点 | 缺点 | 常见应用模型 |
---|---|---|---|---|
句子级 | “今天天气真不错。” | 结构清晰,语言自然单位 | 无法细致建模,严重OOV问题 | 早期RNN、规则模型 |
单词级 | “unbelievable” | 易懂,训练快 | 新词无能为力 | Word2Vec、GloVe |
子词级 | “un + believe + able” | 词表小,无OOV,语义较好 | 切分复杂,训练有偏 | BERT, GPT, T5 等 |
字符级 | “u + n + b + …” | 跨语言能力强,无需词表 | 序列太长,学习难 | CANINE、ByT5 |
字节级 | “\x75 \x6e \x62 …” | 统一所有输入类型,无任何限制 | 表达太原始,需要大模型配合 | GPT-2、tiktoken |
区域级(图像) | 图像划分的 Patch(如ViT) | 可以对图像输入统一处理 | 不一定与语言token天然对齐 | CLIP, BLIP, Flamingo 等 |
我们可以看到,从语义结构最强的“句子”到最原始的“字节”,Tokenizer 划分的单位越小,信息越精细,但模型所承担的“组合理解”任务也越大。
Tokenizer 是怎么“切”的?
除了“切多大”,另一个问题是“怎么切”。有两种主要方式:
自下而上(从细到粗)
这是像 BPE、WordPiece 采用的方式。它们会从字符出发,看哪些字符经常一起出现,就把它们合并成一个 token。
比如:
- “t” + “h” = “th”
- “th” + “e” = “the”
这就像小朋友拼积木:经常拼在一起的,就变成一个新块。
自上而下(从粗到细)
UnigramLM 则反其道而行之:先给出一个大词表,然后剪掉那些“不太重要的”子词。
这种方式的好处是:
- 可以保留多种切分方式
- 允许在训练中做“随机切分”,增强模型泛化能力
它特别适合像中文、日文这种没有空格的语言。
自动学习(可学习的Tokenizer)
最近的趋势是:让模型自己学!
例如:MxDNA 会让模型自己决定“这个DNA序列该怎么切”,而不是你提前设定好。LaVIT 等多模态模型甚至可以自动学习图像要分几个 token。
这说明:Tokenizer 已经不只是静态规则,而是可以作为模型的一部分,由数据驱动学习得来。
小结:Tokenizer 是理解的设计哲学
一句话总结:Tokenizer 决定了模型“看到什么”。
它不是辅助工具,而是模型理解世界的基础。就像你戴什么样的眼镜,会直接影响你对世界的观察方式。
后续我们会聊:
- NLP 的 Tokenizer 是如何一步步演化出来的?
- 多模态中,图像、音频也能被“切”吗?
- 在蛋白质、基因这类序列中,我们如何找到合适的“token”?
Tokenizer,从此不只是“切词”的代名词。