“我爱自然语言处理”——8 个字,几个词?对你来说不假思索,对计算机来说却是一道必须解决的难题。
一、背景:中文 NLP 为什么必须先过"分词"这一关?
1.1 中文 vs 英文:天然的差异
- 英文有天然的分隔符—空格。
"I love NLP"三个词一目了然。 - 中文是一种连续书写的语言,字与字之间没有显式边界。
因此,计算机处理英文时,按空格切一刀就能拿到词。但面对中文,它看到的只是一串连续的字符流,从哪里断开,完全没有线索。

1.2 歧义:中文分词的核心难点
即使知道"要切",切在哪里也不简单。
-
同一段文字,切法不同,意思完全不同:
- “自然语言处理”——是一个词,还是"自然语言"+“处理”?
- “好好工作”——是"好好"+“工作”,还是"好"+“好工作”?
- “南京市长江大桥”——是"南京市长/江大桥",还是"南京/市/长江大桥"?

-
这种歧义性是中文分词最本质的挑战。对人来说靠语感就能判断,但对计算机而言,需要专门的算法来解决。
1.3 为什么分词质量决定一切
分词不是一个孤立的步骤,它是几乎所有中文 NLP 任务的第一道工序:
| 下游任务 | 对分词的依赖 |
|---|---|
| 词袋模型(BoW) | 需要先有"词",才能统计词频 |
| 词向量训练(Word2Vec) | 以词为单位输入,分词粒度决定向量质量 |
| 文本分类/情感分析 | 每个词就是一个特征,分错词 = 特征错误 |
| 搜索引擎/信息检索 | 倒排索引以词为 key,分词不准则召回不准 |
分词质量直接决定了后续所有任务的天花板。 分错一个词,后面全错。这也是为什么中文 NLP工程中,分词往往是投入调优时间最多的环节之一。
二、基础知识:中文分词到底在做什么?
2.1 核心任务
中文分词(Chinese Word Segmentation)的目标很明确:把连续的汉字序列切分成有意义的词语序列。
输入: "研究生命的起源"
输出A: "研究 / 生命 / 的 / 起源" ← 正确
输出B: "研究生 / 命 / 的 / 起源" ← 错误(歧义)
看起来简单,但中文分词面临三大挑战:
| 挑战 | 说明 | 示例 |
|---|---|---|
| 分词歧义 | 同一段文字有多种合理切分 | “南京市长江大桥” → 南京市长/江大桥 or 南京/市/长江大桥 |
| 未登录词(OOV) | 新词、人名、品牌名不在词典中 | “ChatGPT”、“奥利给” |
| 粒度选择 | 切分粗细影响下游效果 | “人工智能” 整体 vs “人工”+“智能” |
2.2 主流分词方法
从技术路线上看,中文分词经历了三代演进:
| 方法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 词典匹配 | 最大匹配法,查词典贪心切分 | 快、简单 | 无法处理歧义和未登录词 |
| 统计模型 | HMM / CRF,基于概率选择最优切分 | 能处理歧义和新词 | 需要标注语料训练 |
| 深度学习 | BiLSTM-CRF / BERT,序列标注 | 精度最高 | 计算成本高 |
jieba 采用的是 词典匹配 + HMM 统计模型 的混合方案:已知词靠词典查找,未登录词靠 HMM 模型利用 Viterbi 算法识别。这种设计让它在速度和精度之间取得了很好的平衡。
2.3 常用工具一览
| 工具 | 特点 | 典型用途 |
|---|---|---|
| jieba | 轻量、易用、支持自定义词典 | 情感分析、文本分类、快速原型 |
| pkuseg | 精度高、可选择领域模型 | 专业领域分词(新闻、医疗等) |
| thulac | 支持词性标注 | 文本标注、语法分析 |
| HanLP | 功能全面、高级 NLP 能力 | 命名实体识别、依存分析 |
其中 jieba 是 Python 生态中使用最广泛的中文分词库——GitHub 超过 30k star,几乎是中文 NLP 的默认选择。
三、技术原理:jieba 的分词算法
jieba 的核心策略是:“词典兜底,统计补刀”—已知词靠查词典,未知词靠概率模型。
内部分两步走:

3.1 步骤一:DAG + 动态规划(处理已知词)
jieba 自带一个约 35万词的前缀词典,每个词都标注了词频。分词时,它先用这个词典对输入文本构建一个DAG(有向无环图)。 什么是 DAG?简单说,就是把一段文字所有可能的切分方式都画出来。
以 “我爱北京天安门” 为例,DAG 中的边(每条边 = 词典中的一个词)。

DAG 建好后,jieba 用 动态规划,从右往左计算每个位置的最大概率路径。高频词组合的路径概率最大,自然就选出了:我 / 爱 / 北京 / 天安门,而不是"北 / 京 / 天 / 安 / 门" 这种逐字切分。因为后者的联合概率远低于前者。
因此,DAG 负责"穷举所有可能",动态规划负责"选出最优解"。
3.2 步骤二:HMM + Viterbi(识别未登录词)
词典再大也不可能覆盖所有词。人名"令狐冲"、新词"内卷"、专业术语等,这些词不在词典里,DAG 会把它们拆成单字。
这时 jieba 启动第二道防线:HMM(隐马尔可夫模型)。
-
核心思想是给每个字标注一个位置状态:
状态 含义 示例 B (Begin) 词的开头 令 M (Middle) 词的中间 狐 E (End) 词的结尾 冲 S (Single) 单字成词 我 
-
jieba 用预训练好的 HMM 参数(状态转移概率 + 发射概率),通过 Viterbi 算法计算最优状态序列:

Viterbi 发现 “令→狐” 的 B→M 转移概率远高于 B→B,说明"狐"更可能是一个词的中间而非另一个词的开头,于是把"令狐冲"识别为一个完整的词。
-
因此,HMM 通过字的位置概率,把词典"不认识"的词重新拼回来。
3.2 两步协作
实际分词时,两步是协作的关系:
| DAG + 动态规划 | HMM + Viterbi | |
|---|---|---|
| 处理对象 | 词典中的已知词 | 词典外的未登录词 |
| 优势 | 快速、准确 | 能识别新词、人名 |
| 局限 | 遇到新词就“不认识” | 速度稍慢,偶有误判 |
| 触发条件 | 默认执行 | 仅对连续单字片段启用 |
jieba 先用 DAG 切出一个初步结果,如果其中出现连续的单字序列(说明词典没能识别),就对这段启用 HMM进行二次识别。两者配合,既保证了已知词的速度和准确性,又兜住了未登录词的识别能力。
四、 三种分词模式
理解了底层原理,再看 jieba 的三种模式就很清晰了:
| 模式 | 调用方式 | 原理 | 输出示例(“我爱自然语言处理”) | 适用场景 |
|---|---|---|---|---|
| 精确模式 | jieba.lcut(text) | DAG 最大概率路径,无冗余 | [‘我’, ‘爱’, ‘自然语言’, ‘处理’] | 文本分析、模型训练 |
| 全模式 | jieba.lcut(text, cut_all=True) | 扫描 DAG 所有可能的词,有重叠 | [‘我’, ‘爱’, ‘自然’, ‘自然语言’, ‘语言’, ‘处理’] | 速度优先、不怕冗余 |
| 搜索引擎模式 | jieba.lcut_for_search(text) | 精确模式 + 对长词再切分 | [‘我’, ‘爱’, ‘自然’, ‘语言’, ‘自然语言’, ‘处理’] | 倒排索引、提高召回率 |
4.1 精确模式
默认方式,最精确的切分,适合文本分析。
import jieba
text = "我爱自然语言处理"
print("精确模式:", jieba.lcut(text))
输出:
精确模式: ['我', '爱', '自然语言', '处理']
4.2 全模式
扫描所有可能的词,速度快但是有冗余。
print("全模式:", jieba.lcut(text, cut_all=True))
输出:
全模式: ['我', '爱', '自然', '自然语言', '语言', '处理']
4.3 搜索引擎模式
在搜索场景中,用户的查询目标往往并不明确。搜索引擎模式正是基于这一现实需求,在精确模式的基础上,对长词进行再次切分,以提升检索系统的召回能力。
(1) 分词结果与倒排索引
-
搜索引擎的核心数据结构是倒排索引(Inverted Index),其组织方式与我们日常阅读文档的直觉正好相反:
- 正排索引:给定一篇文档,列出它包含哪些词
- 倒排索引:给定一个词,找出哪些文档包含它
而分词的结果,正是倒排索引中“词项”的直接来源。
倒排索引(词 → 文档):
深度学习 → [文档1]
自然语言 → [文档1, 文档3]
自然 → [文档2]
模型 → [文档1, 文档2, 文档3]
当用户输入查询词时,搜索引擎只需在倒排索引中查找对应词项,即可快速返回所有相关文档。
(2) 查询粒度不确定性带来的问题
-
问题在于:用户的搜索词粒度是不可预期的。
- 文档中可能写的是 “自然语言处理”
- 用户却可能搜索:
- “自然语言”
- “自然”
- 甚至更短的片段
-
不同的分词策略,会直接影响倒排索引中词项的构成,从而显著改变搜索系统的召回能力与索引质量。
分词模式 索引中的词 用户搜“自然”能命中吗 说明 精确模式 自然语言、处理 不能 只保留语义完整的词,索引干净,但对短查询不友好 全模式 自然、语言、自然语言、处理 + 可能的噪声片段 能,但索引有噪声 穷举所有可能的词片段,召回率高,但容易引入大量噪声 搜索引擎模式 自然、语言、自然语言、处理 能,且索引干净 在精确分词的基础上,额外保留有意义的长词子词,在召回率与索引质量之间取得平衡 因此可以将搜索引擎模式概括为:搜索引擎模式 = 精确模式的准确性 + 长词子词级别的召回能力,这也正是其命名的由来。
(3) 使用示例
在 jieba 中,搜索引擎模式正是围绕上述设计目标实现的:
print("搜索模式:", jieba.lcut_for_search(text))
输出:
搜索模式: ['我', '爱', '自然', '语言', '自然语言', '处理']
可以看到,长词被保留的同时,其关键子词也被纳入索引范围,这使得搜索系统在面对不同粒度的用户查询时,能够获得更稳定的召回效果。
4.4 对比分析
下图直观展示了三种模式对同一句话的切分差异:

- 精确模式:每个位置只保留最优切分,词与词之间没有重叠,结果最干净
- 全模式:把所有可能的词都列出来,“自然”、“语言”、"自然语言"同时出现,存在冗余重叠
- 搜索引擎模式:先按精确模式切分,再对"自然语言"这类长词做二次拆分,兼顾精确性和召回率
选择建议:绝大多数场景用精确模式;做搜索或信息检索用搜索引擎模式;全模式很少直接用。
五、自定义词典:让分词更懂你的领域
jieba 的默认词典主要覆盖通用语言场景,在面对专业术语、业务新词或固定搭配时,往往会出现过度切分的问题。
相比频繁更换分词工具,引入一份贴合业务的自定义词典,通常是成本最低、收益最高的优化手段。
5.1 词典格式
自定义词典采用纯文本格式,每行表示一个词条,可选地指定词频和词性:
深度学习
好好工作
大语言模型 5 n
Transformer 5 eng
-
字段说明如下:
- 词条:希望被整体识别的词
- 词频(可选):值越大,分词时被优先选中的概率越高
- 词性(可选):用于词性标注场景,对分词本身影响较小
-
在大多数业务中,仅提供词条本身就已经能显著改善分词效果。
5.2 自定义词典的使用
加载自定义词典前后,对比分词结果如下:
import jieba
text = "喜欢深度学习,要努力好好工作~"
# 不使用自定义词典
print("精确模式: ", jieba.lcut(text))
# 加载自定义词典
jieba.load_userdict("custom_dict.txt")
# ['喜欢', '深度学习', ',', '要', '努力', '好好工作', '~']
输出结果为:
精确模式: ['喜欢', '深度', '学习', ',', '要', '努力', '好好', '工作', '~']
使用自定义词典的精确模式: ['喜欢', '深度学习', ',', '要', '努力', '好好工作', '~']
-
可以看到,在加载自定义词典后:
- “深度学习” 被识别为一个完整术语
- “好好工作” 作为固定搭配不再被错误拆分
-
分词结果明显更符合语义与业务预期。
5.3 小结
在实际项目中,维护一份领域词典往往比更换分词工具更有效。
-
原因在于:
- 分词错误多来自领域知识缺失,而非算法能力不足
- 自定义词典可控、可迭代,能快速适配业务变化
- 对搜索、召回、统计分析等下游任务影响立竿见影
-
这也是为什么在搜索引擎、推荐系统、日志分析等场景中,“词典建设”本身就是一项长期工程资产。
六、总结
6.1 本篇要点
- 中文没有天然词边界,分词是中文 NLP 的第一道门槛,质量直接决定所有下游任务的天花板。
- 分词面临三大挑战:歧义切分、未登录词、粒度选择。
- jieba = DAG 动态规划 + HMM Viterbi,词典处理已知词,HMM 识别新词,两步协作覆盖绝大多数场景。
- 三种模式各有定位:精确模式用于分析,搜索引擎模式用于检索,全模式用于穷举。
- 自定义词典是最低成本的精度提升方式,比换工具更实际。
6.2 分词工具选型速查
| 需求 | 推荐工具 | 理由 |
|---|---|---|
| 快速原型 / 通用场景 | jieba | 生态好、上手快、自定义词典方便 |
| 专业领域高精度 | pkuseg | 支持领域模型切换 |
| 需要词性标注 | thulac / HanLP | 内置词性标注能力 |
| 深度学习 pipeline | BERT WordPiece / SentencePiece | 与模型分词器一致,避免 tokenization mismatch |

323

被折叠的 条评论
为什么被折叠?



