3、文本预处理:分词技术、停用词过滤、词干提取与词形还原
好,咱们继续往下走。上一章聊了倒排索引的结构,但有个关键问题我没细说——文档里的文本,到底怎么变成一个个可索引的词?
这就是文本预处理要干的事。说白了,就是把原始文本洗干净、切碎、去杂质,最后变成搜索引擎能理解的最小单元。我在早期做搜索项目时,就吃过没做好预处理的亏——用户搜「跑步鞋」,结果因为分词不对,愣是没召回「跑鞋」这个结果。嗯,从那以后,我对这步再也不敢马虎了。
3.1 分词技术:把句子切成词
分词,就是把连续的汉字序列切分成有意义的词语。英文天然有空格分隔,但中文没有。所以中文分词是搜索引擎的「第一道坎」。
我个人的习惯是,先理解两种最基础的算法:正向最大匹配和逆向最大匹配。别看现在深度学习分词满天飞,但这两个算法是理解分词逻辑的基石。
3.1.1 正向最大匹配(FMM)
思路很简单:从左往右扫描,每次取尽可能长的词。
假设词典里有「我们」「在」「北京」「天安门」「天安」「门前」。给定句子:
我们在天安门前
算法步骤:
- 设定最大词长,比如4个字。
- 从左边取4个字「我们在天」,查词典——没有。
- 去掉最后一个字,取「我们在」——没有。
- 再去掉,取「我们」——有!切出来。
- 从「在」开始,取4字「在天安门」——没有。
- 逐步缩短,取「在天」——没有。取「在」——有!
- 继续处理「天安门前」……
最终结果:我们 / 在 / 天安门前
核心要点:正向最大匹配是「贪心」的,它总是优先匹配最长的词。但有个问题——它可能把「天安门前」切成一个词,而实际上用户可能期望「天安门 / 前」。
3.1.2 逆向最大匹配(RMM)
和正向相反,从右往左切。还是那句话:
我们在天安门前
步骤:
- 从右边取4字「安门前」——没有。
- 取「门前」——没有。取「前」——有!
- 继续处理「我们在天安门」……
最终结果:我们 / 在 / 天安门 / 前
你看,结果不一样了。逆向匹配往往比正向更准,因为汉语的「中心词」常在后面。我在项目中做过对比测试,RMM的准确率通常比FMM高3-5个百分点。
我的经验:实际工程中,我经常把FMM和RMM的结果做交集或并集。如果两者一致,基本可以信任;如果不一致,再用统计模型做消歧。这叫「双向最大匹配法」,很多开源分词工具都用了这个思路。
3.2 停用词过滤:扔掉没用的词
分词之后,你会发现一堆「的」「了」「在」「是」……这些词几乎出现在每个文档里,对检索毫无帮助。你想想看,用户搜「北京的天气」,如果索引里全是「的」,那召回结果得多乱?
停用词过滤,就是把这些高频但无意义的词扔掉。
常见的停用词分两类:
| 类别 | 例子 | 为什么去掉 |
|---|---|---|
| 功能词 | 的、了、在、是、有、和 | 语法作用,无实际语义 |
| 高频泛词 | 我们、这个、那个、什么 | 出现太频繁,区分度低 |
注意:停用词表不是一成不变的。我曾经在一个电商搜索项目里,把「买」加进了停用词表,结果用户搜「买手机」时,核心词「买」被过滤了,召回结果全乱套。后来我学乖了——停用词表要跟业务场景绑定。比如在新闻搜索里,「报道」「记者」可能是停用词;但在招聘搜索里,「招聘」「求职」就是核心词。
实现起来很简单,维护一个哈希集合,分词后逐个判断:
if token in stopwords_set:
continue # 跳过
else:
index.add(token) # 加入倒排索引
3.3 词干提取与词形还原:归一化处理
英文里有个经典问题:用户搜「running」,文档里写的是「ran」。如果直接匹配,就漏掉了。中文也有类似情况,但表现形式不同。
3.3.1 词干提取(Stemming)
词干提取是「暴力」的。它直接砍掉单词的后缀,比如:
- running → runn(砍掉ing)
- ran → ran(不规则,砍不动)
- flies → fli(砍掉es)
你看,结果可能不是真正的单词。但没关系,搜索引擎只关心匹配,不关心拼写是否正确。我早期用Porter Stemmer算法处理英文文档,效果不错,但中文不适用——中文没有词形变化。
3.3.2 词形还原(Lemmatization)
词形还原更「聪明」。它会查词典,把单词还原成原型:
- running → run
- ran → run
- better → good
这需要词库和词性标注的支持。代价是速度慢,但准确率高。
中文怎么办?中文没有词干提取的概念,但有一个类似的操作——同义词归一化。比如「电脑」和「计算机」应该映射到同一个词。我在做医疗搜索时,把「高血压」「高血压病」「hypertension」都归一化到「高血压」,召回率提升了12%。
3.4 实战建议:预处理流水线
好了,知识点讲完了。我建议你在项目中这样组织预处理流程:
- 原始文本 → 去除HTML标签、特殊字符
- 分词 → 先用RMM,再用FMM做交叉验证
- 停用词过滤 → 业务定制停用词表
- 归一化 → 同义词映射、大小写统一(英文)
- 输出 → 干净的词列表,送入倒排索引构建
这个流水线我用了很多年,基本没出过大问题。你想想看,如果每个环节都做到位,搜索引擎的「地基」就稳了。下一章,咱们正式进入倒排索引的构建和查询,到时候你会看到,预处理的质量直接决定了搜索效果的上限。