命名实体识别(Named Entity Recognition)也是自然语言处理中的一个难关,特别是中文这样没有大小写等固定形态的语言。上次介绍过《实战HMM-Viterbi角色标注中国人名识别》,这次基于类似的原理,为HanLP实现中文地址地名(NS)的自动识别。
原理
训练
对熟语料自动角色标注,统计单词的角色频次、角色的转移概率等,训练出一个模型,同时总结一些可用的模式串。
识别
根据上述模型,利用HMM-Viterbi算法标注陌生文本的粗分结果,利用Aho-Corasick算法模式匹配,匹配出可能的地址,将其送入第二层隐马尔可夫模型中。
实战
训练
自动角色标注
《基于层叠隐马尔可夫模型的中文命名实体识别.pdf》中使用如下地名识别角色:
我在此基础上拓充了CDE分别为三字地名的三个字位,H为中国地名的后缀,G为整个地址,这样一般最多可以识别6字地名(CDE地名+三字后缀),比论文有所改进。
通过少量的代码即可自动对熟语料进行角色标注,比如对于这一句人民日报2014切分语料中的句子:
1 | |
逐步处理得到
1 2 3 4 5 6 7 | |
统计词频
在对所有熟语料句子执行自动标注后,即可统计每一个非Z词语的词频,得到一个角色词典:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
统计转移矩阵
转移矩阵指的是从一个角色标签转移到另一个角色的频次,利用它和角色词频可以计算出HMM中的初始概率、转移概率、发射概率,进而完成求解。关于维特比算法和实现请参考《通用维特比算法的Java实现》。
这里对人民日报2014切分语料训练出如下转移矩阵:
识别
例子
以“南翔向宁夏固原市彭阳县红河镇黑牛沟村捐赠了挖掘机”为例,不进行地名识别时,会得出下列输出:
1 | |
上例中“宁夏”“固原市”等属于常用地名,因此被收录到核心词典中,此处表现出正确的分词结果。但是像“彭阳县”“红河镇”“黑牛沟村”等地名属于非常小的地方,没有被词典收录,自然也没法得出正确的分词结果。
角色标注
1 2 | |
模式匹配
利用Aho-Corasick算法模式匹配如下模式串:
1 2 3 4 | |
得到如下地名:
1 2 3 | |
第二层隐马模型细分
其实这应该算是第三层隐马模型,因为地名识别中也用到了一次HMM,并且那次的输出是这次的输入。细分之后得出最终的结果:
1 | |
总结
HMM模型可以解决很多问题,将多个HMM模型层叠起来,可以发挥出更加精准的效果。
不过2元文法依然会有误命中的情况,事实上,一些高频地名已经收录到核心词典和用户自定义词典中。所以HanLP的默认配置关闭了地名识别,仅仅在一些极端情况下(专门提取县级地址)交由用户打开。
目录