Skip to content

第四章:分词技术总览

分词(Tokenization)是将原始文本切分为若干具有独立语义的最小单元(即 token)的过程,是所有 NLP 任务的起点。


为什么需要分词?

计算机无法直接理解文本字符串。分词是将文本转换为数值表示的第一步:

原始文本:"我爱自然语言处理"
    ↓ 分词
Token 序列:["我", "爱", "自然语言处理"]
    ↓ 映射到词表
ID 序列:[2769, 4263, 8547]
    ↓ 嵌入层
向量序列:[[0.12, -0.34, ...], [0.56, 0.78, ...], [-0.11, 0.45, ...]]

英文分词

按照分词粒度的大小,英文分词可分为三个层次:

词级分词(Word-Level)

词级分词是最传统、最直观的方式。在英文中,空格和标点是天然的分隔符。

python
text = "I love natural language processing"
tokens = text.split()
# ['I', 'love', 'natural', 'language', 'processing']

优点:简单直观,语义清晰

缺点——OOV 问题

词级分词容易出现 OOV(Out-Of-Vocabulary,未登录词)问题。当模型遇到词表中没有的词时,无法处理。

训练词表:["I", "love", "natural", "language", "processing", ...]
输入文本:"I love NLP and ChatGPT"
OOV 词:  "NLP", "ChatGPT" → 被替换为 <UNK>

随着网络新词、专有名词不断涌现,OOV 问题会越来越严重。

字符级分词(Character-Level)

以单个字符为最小单位:

python
text = "I love NLP"
tokens = list(text)
# ['I', ' ', 'l', 'o', 'v', 'e', ' ', 'N', 'L', 'P']

优点

  • 词表极小(英文仅需 ~100 个字符)
  • 几乎不存在 OOV 问题

缺点

  • 单个字符语义信息极弱
  • 输入序列变得很长,增加计算成本
  • 模型需要更长的上下文才能理解词义

子词级分词(Subword-Level)

子词级分词是介于词级和字符级之间的方法,也是现代 NLP 的主流选择

它将词语切分为更小的子词单元:

"unhappiness" → ["un", "happi", "ness"]
"tokenization" → ["token", "ization"]
"ChatGPT" → ["Chat", "G", "PT"]

核心优势

特性词级字符级子词级
词表大小大(数万-数十万)极小(数百)适中(数千-数万)
OOV 问题严重基本无
语义信息中等
序列长度极长适中

为什么子词分词能解决 OOV?

即使一个完整的词没有出现在词表中,只要它可以被拆分为词表中存在的子词单元,就可以被模型识别和表示。

常见的子词分词算法包括:

  • BPE(Byte Pair Encoding)
  • WordPiece
  • Unigram Language Model

我们将在下一章详细讲解这些算法。


中文分词

中文与英文的最大区别是:中文没有空格作为天然的词边界

英文:I love natural language processing  (空格分隔)
中文:我爱自然语言处理  (没有空格)

因此中文分词是一个更具挑战性的问题。

字符级分词(中文)

将文本按单个汉字切分:

python
text = "我爱自然语言处理"
tokens = list(text)
# ['我', '爱', '自', '然', '语', '言', '处', '理']

由于汉字本身通常具有独立语义,字符级分词在中文中比在英文中更"语义友好"。

这也是很多中文预训练模型(如 BERT 中文版)采用的方式。

词级分词(中文)

将文本按完整词语切分:

python
import jieba
text = "小明毕业于北京大学计算机系"
tokens = jieba.lcut(text)
# ['小明', '毕业', '于', '北京大学', '计算机系']

优点:切分结果更贴近人类阅读习惯,语义更完整

缺点

  • 需要依赖词典或模型
  • 分词结果可能存在歧义:"南京市长江大桥" → "南京市/长江大桥" 还是 "南京/市长/江大桥"?

子词级分词(中文)

虽然中文没有英文中的词根、前缀、后缀等子词结构,但 BPE 等算法仍可直接应用于中文。它们以汉字为基本单位,通过学习语料中高频的字组合来构建子词词表。

"自然语言处理" → ["自然", "语言", "处理"]
"深度学习" → ["深度", "学习"]
"大模型" → ["大", "模型"]

当前主流的中文大模型(如通义千问、DeepSeek)均采用子词分词。


中文分词工具:jieba

jieba 是中文分词领域应用最广泛的开源工具。

安装

bash
pip install jieba

三种分词模式

精确模式(默认)

试图将句子最精确地切开,适合文本分析。

python
import jieba

text = "小明毕业于北京大学计算机系"
result = jieba.lcut(text)
print(result)
# ['小明', '毕业', '于', '北京大学', '计算机系']

全模式

把句子中所有可以成词的词语都扫描出来,速度最快。

python
result = jieba.lcut(text, cut_all=True)
print(result)
# ['小', '明', '毕业', '于', '北京', '北京大学', '大学', '计算', '计算机', '计算机系', '算机', '系']

搜索引擎模式

在精确模式基础上,对长词进一步切分,适合搜索引擎。

python
result = jieba.lcut_for_search(text)
print(result)
# ['小明', '毕业', '于', '北京', '大学', '北京大学', '计算', '算机', '计算机', '计算机系']

三种模式对比

模式方法特点适用场景
精确模式jieba.lcut()最精确,无冗余文本分析
全模式jieba.lcut(cut_all=True)最全,有冗余快速扫描
搜索引擎模式jieba.lcut_for_search()长词再切分搜索引擎

自定义词典

jieba 支持用户自定义词典,用于增强特定领域词汇的识别能力。

词典格式:一个词占一行,格式为 词语 词频 词性标签(词频和词性可省略)

text
# dict.txt
云计算
云原生 5
大模型 10 n

加载词典

python
import jieba

jieba.load_userdict('dict.txt')
result = jieba.lcut("随着云计算技术的普及,越来越多企业开始采用云原生架构")
print(result)

动态修改词典

python
# 添加词语
jieba.add_word("大模型", freq=10, tag="n")

# 删除词语
jieba.del_word("自定义词")

分词工具对比

工具类型适用语言特点
jieba基于词典/模型中文轻量、快速、广泛使用
HanLP基于模型多语言功能全面、准确率高
pkuseg基于模型中文北大开源、准确率高
HuggingFace Tokenizer子词分词多语言与预训练模型配套
SentencePiece子词分词多语言语言无关、不需预分词
tiktoken子词分词多语言OpenAI 的高效分词器

小结

分词方式粒度词表大小OOV语义序列长度
词级严重
字符级
子词级基本无

现代 NLP 模型普遍采用子词级分词,它在词表大小、OOV 处理和语义保留之间取得了最佳平衡。下一章我们将深入讲解 BPE、WordPiece 和 Unigram 等子词分词算法的原理。

AI 知识体系 — 从机器学习到大语言模型