2、中文分词技术:从原理到实战

分词,说白了就是把一句话切成一个个有意义的词。英文天然有空格分隔,中文可没这好事。「武汉市长江大桥」到底是「武汉/市长/江大桥」还是「武汉市/长江大桥」?嗯,这就是分词要解决的问题。

我刚开始做搜索那会儿,就栽在分词上。用户搜「苹果手机」,结果因为分词不对,把「苹果」和「手机」拆开了,召回了一堆水果和通讯设备。后来我才明白——分词是搜索的基石,地基不稳,上层建筑全白搭

2.1 分词原理:机器怎么理解中文?

分词的核心,就是让计算机在连续的中文字符串中找到词的边界。听起来简单,做起来难。中文里词和词之间没有空格,而且歧义无处不在。

举个例子:「他说的确实在理」。这句话可以切分成:

  • 他 / 说 / 的 / 确实 / 在理
  • 他 / 说 / 的确 / 实在 / 理

哪种对?得看上下文。分词算法要解决的,就是这类问题。

目前主流的分词方法分两大类:基于词典基于统计。实际项目中,我习惯把两者结合起来用,效果最好。

2.2 基于词典的分词:简单粗暴但有效

基于词典的分词,思路很直白——准备一个词库,然后拿着文本去匹配。匹配方式主要有三种:

方法 原理 优缺点
正向最大匹配 从左到右,取最长匹配词 简单,但容易漏掉短词
逆向最大匹配 从右到左,取最长匹配词 比正向准确率高一点
双向最大匹配 正向+逆向,选结果更好的 准确率最高,但慢一些

我记得有个项目,用户搜「北京大学生」,正向匹配会切成「北京大学/生」,逆向匹配会切成「北京/大学生」。哪个对?得看用户想找学校还是找学生。这时候双向匹配就能给出两种结果,让后续的语义分析去判断。

我的经验:词典分词的关键在词库质量。我一般会用基础词库(比如搜狗词库)+ 领域词库(比如医疗、法律)+ 用户搜索日志中的高频词。三管齐下,覆盖率能到90%以上。

2.3 基于统计的分词:让数据说话

词典分词有个硬伤——遇到新词就歇菜。比如「给力」「凡尔赛」这种网络新词,词典里没有,就切不出来了。

统计分词就不一样了。它不看词典,看概率。核心思想是:如果几个字经常一起出现,那它们很可能是一个词

常用的统计模型有:

  • N-gram模型:计算字与字之间的共现概率。比如「人工」后面跟「智能」的概率很高,那它们就应该组成一个词。
  • 隐马尔可夫模型(HMM):把分词看作序列标注问题,给每个字打标签(词首、词中、词尾、单字词)。
  • 条件随机场(CRF):比HMM更强大,能考虑更多上下文特征。

为什么会用统计方法?你想想看,用户搜「新冠疫苗」,如果词典里只有「新冠」和「疫苗」,那没问题。但如果用户搜「新冠疫苗接种」,统计模型能自动识别出「新冠疫苗」是一个整体,因为「新冠」和「疫苗」在语料中频繁共现。

注意:统计分词需要大量标注语料。我曾经在一个小语种项目上吃过亏——语料不够,模型训练出来效果还不如简单的词典分词。所以,数据量不够的时候,别盲目上统计方法。

2.4 Jieba分词库实战:拿来就能用

说到分词工具,Jieba(结巴分词)是Python生态里最常用的。它把词典分词和统计分词结合起来了,用起来特别顺手。

安装很简单:

pip install jieba

基本用法:

import jieba

text = "我在武汉大学学习计算机科学"
words = jieba.lcut(text)
print(words)
# 输出:['我', '在', '武汉大学', '学习', '计算机科学']

Jieba支持三种模式:

  • 精确模式:最常用,把句子最精确地切开,适合文本分析。
  • 全模式:把所有可能的词都列出来,速度快但有冗余。
  • 搜索引擎模式:在精确模式基础上,对长词再切分,适合搜索场景。

我一般这么用:

# 精确模式
words = jieba.lcut(text)

# 搜索引擎模式
words = jieba.lcut_for_search(text)

搜索引擎模式有个好处——它会把「武汉大学」同时切出「武汉」和「大学」,这样用户搜「武汉」或「大学」都能召回这条结果。召回率一下子就上去了。

避坑指南:Jieba默认词库是通用的,但如果你做垂直领域(比如医疗、法律),一定要加载自定义词典。我曾经做过一个法律搜索项目,不加自定义词典的话,「犯罪嫌疑人」会被切成「犯罪/嫌疑/人」,语义全变了。

加载自定义词典的方法:

jieba.load_userdict("mydict.txt")

词典格式很简单,每行一个词:

犯罪嫌疑人 5 n
搜索引擎优化 3 n

数字是词频,字母是词性。词频越高,Jieba越倾向于把它当作一个整体。

2.5 分词在搜索中的应用:不只是切词

分词在搜索里到底怎么用?我总结了几点:

  1. 索引构建:文档入库前先分词,每个词作为一个索引项。用户搜「计算机」,就能快速找到包含「计算机」的文档。
  2. 查询处理:用户输入的查询也要分词。比如用户搜「武汉大学计算机学院」,分词后得到「武汉大学」「计算机」「学院」,然后分别去索引里匹配。
  3. 同义词扩展:分词后可以做同义词替换。比如「计算机」和「电脑」是同义词,搜其中一个,另一个也能召回。
  4. 纠错辅助:分词结果可以帮助判断用户是不是打错了。比如「苹国手机」分词后,「苹国」不在词典里,系统就知道这里可能有错别字。

我记得有个电商项目,用户搜「电饭煲」,结果分词把「电饭煲」切成了「电饭」和「煲」,导致召回了一堆「电饭锅」和「砂煲」。后来我强制把「电饭煲」加入自定义词典,问题就解决了。

核心要点:分词不是越细越好,也不是越粗越好。搜索场景下,召回率和准确率的平衡才是关键。搜索引擎模式通常是最优选择——既能保证精确匹配,又能通过细粒度切分提高召回。

好了,分词这块就聊到这儿。下一章我们讲同义词,到时候你会看到,分词和同义词其实是密不可分的——分词分得准,同义词才能用得对。