盘古分词-中文人名识别
作者: eaglet
eaglet 曾经在KTDictSeg 中分别尝试使用规则和统计方式来识别中文(汉族)人名,但效果都不理想。在盘古分词中eaglet另辟它径,采用一种新的算法来识别中文人名,效果相比规则和统计方式要好很多。下面eaglet就来介绍这种中文人名的识别方法。
要很好的识别中文人名,我们需要对要分解的句子按预处理和消除歧义两个步骤进行处理。
预处理
识别中文人名的第一步是进行预处理,预处理的过程是找出要识别的句子中所有可能的中文人名。查找的方式是首先根据姓氏来匹配,找到姓氏后再根据常见的单字中文名和双字中文名来匹配。盘古分词字典目录下有三个文件分别是 ChsSingleName.txt, ChsDoubleName1.txt, ChsDoubleName2.txt,它们分别表示单字人名,双字人名的首字和双字人名的尾字,根据这三个文件中指定的常用中文名,我们可以完成预处理的过程。
比如 张三丰李世民
其中 “张”、“李”是姓,“三”是常用单字名和常用双字名首字,“世”是常用双字名首字,“民”和“丰”是常用双字名尾字
这样预处理的结果就是
张三
张三丰
李世民
消除歧义
由于汉语非常复杂,预处理完了以后,还存在歧义的问题。比如
“张三说的确实在理”和 “李三买了一张三角桌子”这两句话中都包括 “张三”这个词,但第一句话中张三是人名,第二句话则不是。
所以要提高中文人名的识别率,消除歧义是关键的一步。
eaglet 给出的办法是将第一步预处理出来的中文人名和字典中匹配的所有词全部输出出来,然后找到词和词之间空隙最小且分出来的词最少的那种组合。
拿“李三买了一张三角桌子”这句话来举例
在字典中我们分解出如下的词
三 买 了 一张 张 三角 三 桌子 子
再加上之前预处理找到的人名 李三和张三,最后分解出下面这些词
李三 三 买 了 一张 张三 张 三角 三 桌子 子
这时候我们再对这些词进行组合,组合的规则是在一组词中不能有交错的词出现,比如一张 和 张三 就不能出现在一组词中。
组合完后,根据我上面说的规则排序,找到最匹配的组合。
我们可以看看最匹配的组合是
李三/买/了/一张/三角/桌子/ 这个组合词和词之间没有间隙,即间隙为0,分出的单词数为6
如果把“张三”作为一个词分出来,其组合为
李三/买/了/ /张三/ /桌子/ 这个组合由于“张”前面的“一”和后面的“角”在字典中没有,所以间隙为1+1=2,其没有前面的最佳组合间隙小,所以我们不取这个组合。
那么我们再深入一些,如果我们在字典中加入了“一” 和 “角”这两个词,是不是就会分错呢?答案是否定的。
加入“一” 和 “角”这两个词后,如果要把“张三”作为一个词分出来,其组合为
李三/买/了/一/张三/角/桌子/ 这时间隙为0不错,但分出来的单词数为7,大于前面的最佳组合,所以这个组合还是会被忽略掉。
总结
盘古分词人名识别算法讲出来其实很简单,不过eaglet 为了探索这个算法,花了一年多的时间。这个算法在中文人名的识别上比我之前采用的方法有了很大的进步,但并不是万能的,首先我们不可能把所有的人名都放到那个人名字典中,这就导致一些不太常见的人名无法被分出来,其次对于一些只有人名没有姓的情况,这种方面目前也无法识别,再次由于双字人名被分为首字和尾字分别存储,这样虽然增加了组合的数量,但也难免会组合出一些非人名的情况。
不过技术总会不断推进,eaglet 并不是汉语语言专家,也不是专门做汉语语言方面研究的。eaglet在此就算抛砖引玉吧。各位看官,如果你有更好的方法,不妨也拿出来和大家一起分享分享,如果你觉得eaglet目前的算法还有哪些改进余地,也不妨提出来,大家一起讨论。