IK分词器其实根本不“认识”中文,它不懂语法,也不理解语义。它的“自动分词”,本质上是一个“穷举查字典 + 消歧规则”的机械匹配游戏。
下面我把它的“大脑”拆开,看看它到底是怎么一步步把中文句子切开的。
第一步:加载“电子词典”(核心前提)
IK启动时,会把词典文件(main.dic、stopword.dic等)加载到内存中,构建一个Trie树(前缀树)。
作用:给定任何一个汉字开头,它能瞬间判断出以这个字开头的所有词。
例子:输入“中”,Trie树能快速找出
中国、中华、中间、中华人民共和国等所有以“中”开头的词。
第二步:从左到右“大贪心”(最大匹配)
当输入句子"南京市长江大桥"时,IK开始从左到右逐个字符扫描,算法是正向最大匹配(FMM):
从第1个字“南”开始,假设词库最大词长是5个字。
IK先截取
"南京市长江"(5个字)去查词典。查不到?去掉最后一个字,查
"南京市长江"(4个字)——还是查不到。再去掉一个字,查
"南京市"(3个字)——查到了!输出[南京市]。
指针跳到第4个字“长”,继续截取
"长江大桥"(4个字)去查词典。查
"长江大桥"(4个字)——查到了!输出[长江大桥]。
最终粗切结果为:
[南京市, 长江大桥]。
第三步:处理“切分冲突”(消歧义)
如果只是贪心匹配,句子"中华人民共和国"会遇到冲突:
正向最大匹配会切出
[中华人民共和国](整词)。但细粒度模式需要切出
[中华人民共和国, 中华, 华人, 人民, 共和国...]。
IK的解决策略是“子词组合”:
先通过Trie树找出所有能匹配上的词项(一个词网)。
再通过基于规则(Rule)的消歧算法,决定保留哪些词。规则包括:
长度优先:长词优先于短词(
ik_smart模式)。交叉词最小化:尽量避免切出的词在原文中相互重叠。
第四步:两种模式的“自动”区别
你配置IK时,通常有两个选择,它们的“自动”逻辑完全不同:
| 模式 | 自动逻辑 | 示例"中华人民共和国" |
|---|---|---|
ik_smart(智能) | 只输出最粗、最长的唯一结果,用于减少索引体积。 | [中华人民共和国] |
ik_max_word(最细) | 穷举所有可能的词,把所有在词典中命中的子词全拆出来。 | [中华人民共和国, 中华, 华人, 人民, 共和国, 共和, 国] |
第五步:自动过滤“垃圾词”(停用词)
切完词后,IK会自动执行一个后置过滤器:
遍历所有切出的Token,如果命中
stopword.dic(如“的”、“了”、“啊”),直接丢弃,不存入倒排索引。目的:省磁盘空间,提高检索速度(因为停用词几乎不提供检索价值)。
实战验证:用_analyze看透IK的“自动”过程
你可以直接在Kibana或Console里跑这个命令,看IK到底输出了什么:
POST /_analyze { "analyzer": "ik_max_word", "text": "乒乓球拍卖完了" }输出结果:
乒乓球拍, 乒乓球, 球拍, 拍卖, 完了
注意:IK并没有像人一样理解这是“乒乓+球拍+拍卖+完了”,它只是机械地把词典里所有匹配上的词都吐了出来。它并不知道这句话到底是在说体育用品还是拍卖会。
IK分词器最大的“死穴”(影响自动分词准确性)
既然IK是纯词典匹配,那它最怕两件事:
未登录词(OOV):词典里没有的词,比如网络热词“YYDS”、“内卷”,或者人名“李子柒”。IK遇到这些,会直接拆成单字
[李, 子, 柒],导致搜索失效。歧义句:
"美国会通过法案"。IK智能模式会切成[美国, 国会, 通过, 法案],但如果语境是指“美国/会/通过”,它无法根据上下文语义判断,只能死板地按词典最长词匹配。
总结一句人话
IK的自动分词,就是“拿着词典当尺子,从左到右量出最长的那几段,然后把所有碰巧匹配上的词项全倒出来”。它没有智能,只有匹配。