放牧代码和思想
专注自然语言处理、机器学习算法
    时间有限,只有GitHub上的issue能及时处理。另外,不要叫我楼主,谢谢。

实战HMM-Viterbi角色标注中国人名识别

目录

这几天写完了人名识别模块,与分词放到一起形成了两层隐马模型。虽然在算法或模型上没有什么新意,但是胜在训练语料比较新,对质量把关比较严,实测效果很满意。比如这句真实的新闻“签约仪式前秦光荣李纪恒仇和等一同会见了参加签约的企业家。”,分词结果:[签约/v, 仪式/n, 前/f, ,/w, 秦光荣/nr, 、/w, 李纪恒/nr, 、/w, 仇和/nr, 等/u, 一同/d, 会见/v, 了/ul, 参加/v, 签约/v, 的/uj, 企业家/n, 。/w],三个人名“秦光荣”“李纪恒”“仇和”一个不漏。一些比较变态的例子也能从容应对,比如下面:

原始句子 HanLP ansj分词
签约仪式前,秦光荣、李纪恒、仇和等一同会见了参加签约的企业家。 [签约/v, 仪式/n, 前/f,   ,/w, 秦光荣/nr, 、/w, 李纪恒/nr, 、/w, 仇和/nr, 等/u, 一同/d, 会见/v, 了/ul, 参加/v, 签约/v,   的/uj, 企业家/n, 。/w] [签约/v, 仪式/n, 前/f,   ,/w, 秦/nr, 光荣/a, 、/w, 李纪恒/nr, 、/w, 仇/nr, 和/c, 等/u, 一同/d, 会见/v, 了/ul, 参加/v,   签约/v, 的/uj, 企业家/n, 。/w]
王国强、高峰、汪洋、张朝阳、韩寒、小四 [王国强/nr, 、/w, 高峰/n,   、/w, 汪洋/n, 、/w, 张朝阳/nr, 、/w, 韩寒/nr, 、/w, 小/a, 四/m] [王国/n, 强/a, 、/w,   高峰/n, 、/w, 汪洋/n, 、/w, 张/q, 朝阳/ns, 、/w, 韩寒/nr, 、/w, 小/a, 四/m]
张浩和胡健康复员了 [张浩/nr, 和/c, 胡健康/nr,   复员/vn, 了/ul] [张浩/nr, 和/c, 胡/nr,   健康/a, 复员/vn, 了/ul]
王总和小丽结婚了 [王总/nr, 和/c, 小丽/nr,   结婚/v, 了/ul] [王/nr, 总和/n, 小丽/nr,   结婚/v, 了/ul]
编剧邵钧林和稽道青说 [编剧/n, 邵钧林/nr, 和/c,   稽道青/nr, 说/v] [编剧/n, 邵钧林/nr, 和/c,   稽/nr, 道青/nr, 说/v]
这里有关天培的壮烈 [这里/r, 有/v, 关天培/nr,   的/uj, 壮烈/a] [这里/r, 有关/vn, 天培/nr,   的/uj, 壮烈/a]
龚学平等领导,邓颖超生前 [龚学平/nr, 等/u, 领导/n,   ,/w, 邓颖超/nr, 生前/t] [龚学平/nr, 等/nw, 领导/n,   ,, 邓颖超/nr, 生前/t]

这是我将自己的分词与ansj作比较得出的结果,由于自己可以随时调整算法,所以主场占了很大便宜。但是第一句绝对没有放水,说实话能识别出“仇和”这么冷僻的名字着实让我惊喜了一下。

开源项目

本文代码已集成到HanLP中开源:http://www.hankcs.com/nlp/hanlp.html

原理

推荐仔细阅读《基于角色标注的中国人名自动识别研究这篇论文,该论文详细地描述了算法原理和实现。从语料库的整理、标注到最后的模式匹配都讲得清清楚楚。我在这篇论文的基础上做了改进,主要步骤我总结如下:

1、对熟语料库自动标注,将原来的标注转化为角色标注。角色标注一共有如下几种:

编码

代码

意义

例子

B

Pf

姓氏

华平先生

C

Pm

双名的首字

平先生

D

Pt

双名的末字

张华先生

E

Ps

单名

说:“我是一个好人”

F

Ppf

前缀

刘、  

G

Plf

后缀

、刘、肖、吴、叶

K

Pp

人名的上文

来到于洪洋的家。

L

Pn

人名的下文

新华社记者黄文

M

Ppn

两个中国人名之间的成分

编剧邵钧林稽道青说

U

Ppf

人名的上文和姓成词

这里有关天培的壮烈

V

Pnw

人名的末字和下文成词

龚学平等领导, 邓颖超生

X

Pfm

姓与双名的首字成词

王国

Y

Pfs

姓与单名成词

高峰汪洋

Z

Pmt

双名本身成词

朝阳

A

Po

以上之外其他的角色

1 中国人名的构成角色表

我在此基础上拓展了一个S,代表句子的开始。

2、统计标签的出现频次,标签的转移矩阵。

3、对粗分结果角色标注,模式匹配。

我对论文中的几个模式串做了拓充,并且采用了AC模式匹配算法。

体会

论文中将三字名称拆分为BCD,我实测在2-gram模型下,C很容易被识别为E,导致人名缺一半。

人民日报2014中的人名并不能覆盖所有常用字,所以我去别的地方找了个人名库,拆成BCD或BE补充了进去。

人民日报2014语料库中有很多错误,比如

去/vf 年老/vi 张中秋/nr 去/vf “/w 泡茶/vi ”/w ,/w 送礼/vi 遭到/v 了/ule 拒绝/v ,/w 老张/nz 担心/v 金额/n 不够/a

中秋很明显不是人名的组成部分,这个必须手工剔除。

“中秋安全”会识别出“中 秋安全”来,因为2-gram词典中没有“中秋@安全”这种接续,而有“中@未##人”这种接续。初步的解决方法是手工往2-gram词典里面加一条“中秋@安全”。这反映了这种方法的局限性,另一方面也说明词典的重要性。

nlp.jpg

转载须注明:码农场 » 实战HMM-Viterbi角色标注中国人名识别

分享到:更多 ()
  1. Pingback: HanLP开源 | HundredLee's Blog

  2. 你好,在你的PersonDictionary.java中我个人觉得发现了一个bug,就是在parsePattern这函数中,对V这个进行拆分时,感觉你拆分代码不对,个人觉得应该是这样的:listIterator.previous();
    String nowED = current.realWord.substring(0,1);
    String nowL = current.realWord.substring(1);
    listIterator.set(new Vertex(nowED));
    listIterator.next();
    listIterator.add(new Vertex(nowL));

  3. 博主,你好,我有一个疑问,观测状态为文本里面的词,隐含状态为角色序列。HMM的参数统计出来,即模型确定后。如果来了一个新的文本进行veterbi求解,而该文本里面有新的词,即新的观测状态,请问怎么标记?谢谢

  4. 博主你好,我在在阅读HanLP的人名识别这部分代码时发现了一个问题,Viterbi.java中的computeEnumSimply应该是贪心算法吧,而不是维特比?

  5. 博主你好,最近在拜读你的HanLP代码,在阅读人名识别这部分的代码时,有一个疑问:PersonRecognition中的Recognition在求最优标签序列时调用了viterbiExCompute,viterbiExCompute又调用了Viterbi.computeEnumSimply,但computeEnumSimply我看了一下应该是贪心算法,不是维特比,不知道是不是这里是个bug还是故意为之?烦请解答,谢谢!

  6. 请教博主:“人民日报2014语料库”是个怎样的语料库,好像只听说过1998的人民日报语料库。难道又有人大规模标注了2014年人民日报?这可是个大事,要花很多人力物力的。请博主指教,谢谢!

  7. 博主你好,感觉人名识别准确率不是很高,召回率挺高。“安倍让”、“练毅力”、“卫和平”等都识别成人名了,还有日本人名的准确率太低,经常把普通词识别为日本人名。

  8. 这的确是个问题,开放语境灵活很多。没有完美的算法,未来我可能会实现一些准确率更高但召回率更低的算法(如“字位法”),以供自由选择吧。

  9. 日本人名识别算是首创,积累的经验并不多,但还是做了些优化:https://github.com/hankcs/HanLP/commit/ec2f3d3b67d0c6b3cc5621a9a8b195399b86c214

  10. 博主你好,想请教一个小问题。多层隐马模型,若将人民识别放在第二层,那第二层的输入依赖于第一层的输出,此时语料库作为训练集,是不是需要经过第一层后再做标识?

  11. 博主你好!你的标准分词利用了用户词典,而用户词典中很多是实体,导致分词时有好多单词组合在一起成为实体了,这样会不会不符合分词标准啊?

  12. Pingback: 有关命名实体识别技术的调研 | NUSTM

  13. 博主,请问root目录必须是绝对路径吗?我用的是 web项目怎么写相对路径,能给个实例吗?thank you!

  14. 你好,我想识别出这句话中的人名“卢凡”,参考你的说明我添加在“data\dictionary\person\nrf.txt”中,并删除“data\dictionary\person\nrf.txt.trie.dat”,可是还是不能识别出“卢凡是先进事迹报告团的成员。”中的“卢凡”呢?

  15. 楼主你好,我再用HanLP进行命名实体识别时,效果感觉不太好,远远低于我的预期,尤其是人名识别和机构名识别。我采用的语料主要集中在汽车行业。如果对于机构名识别效果差的话,我还能从测试语料与训练语料的差异上给出解释,但是对于人名识别,感觉比较难以理解。 比如 “都带长”,“都一处”,"那就来","方是为",咋一看感觉都是基于一些姓得到的。

  16. 博主,您好。我目前尝试自定义一个人物关系词典作追加词典,然后用hanlp的词性标注功能将关系词识别出来。但是结果不理想。例如,实验结果还是将“丈夫”识别为n,而不是自定义词典中我自己定义的词性,似乎自定义词典并没有起到作用?请问这个问题要怎么解决?谢谢!

  17. 博主,您好,我想咨询下,在训练转移概率的时候。XYZA怎么标识。比如王/B 国/C 维/D。那其他位置的王国/X。如果这样,康复 X 2 L 1这种只是优先统计出来,并不是角色语料中统计出来的吗?

  18. 博主你好,最近在用HanLP做人名识别,发现当三字人名中的前两个字也是一个人名时,识别不出来三字人名。例如:证明原告孙辉与被告姚宏旭之间的借款关系。识别为:[证明/v, 原告/n, 孙辉/nr, 与/p, 被告/n, 姚宏/nr, 旭/nr, 之间/f, 的/uj, 借款/n, 关系/n]

    姚宏旭被拆开了,怎么处理下呢?

我的开源项目

HanLP自然语言处理包基于DoubleArrayTrie的Aho Corasick自动机