用CRF做命名实体识别——NER系列(三)

在上一篇文章《用隐马尔可夫模型(HMM)做命名实体识别——NER系列(二)》中,我们使用HMM模型来做命名实体识别,将问题转化为统计概率问题,进行求解。显然,它的效果是非常有限的。

在深度学习技术火起来之前,主流的、最有效的方法,就是CRF(条件随机场)模型。本文不对CRF模型进行展开讲解,而是结合我之前参加的CCF BDCI的其中一个赛题,直接用CRF++工具进行实战。下面直接进入正题。

1.赛题解读

赛题介绍:https://www.datafountain.cn/competitions/269/details/rule

任务描述

总结一下,这个题目要求我们对数据集中的每条记录,提取出正文中的主要机构实体,判断这些机构的风险等级(中性,正向或负向),并为每个实体生成相应的摘要和关键词。

我接下来主要讲提取实体这一部分,用的是CRF模型,训练直接使用CRF++工具(http://taku910.github.io/crfpp/)(似乎被墙了?)。

2.算法流程图

算法流程图

3.算法说明

3.1 定义实体标注集

为了确保最后的机构实体识别准确度,使用BMEWO标注集,各个标注的意义如下:

B:实体的开头

M:实体的中间部分

E:实体的结束

W:单独成实体

O:句子的其它成分

比如下面这个句子(已做分词处理):

山西      相立      山泉      饮品      开发      有限公司     生产      的桶装  饮用水  检出      铜绿      假   单胞菌

背后的标注为:

山西/B  相立/M 山泉/M 饮品/M 开发/M 有限公司/E  生产/O  的/O 桶装/O     饮用水/O     检出/O  铜绿/O   假/O 单胞菌/O

3.2训练文本、测试文本预处理

对训练文本进行中文分词、去除停用词的处理,并根据上述的标注集进行标注。同时,除了词本身,还引入了4个特征:

特征:【词性】,用jieba分词识别出来的词性

特征②:【是否是特征词】,该词是特征词,标记1;不是特征词,标记0。这里的特征词是指“实体通常的结尾词”,比如“有限公司”,“药监局”,“超市”等等,这些特征词来源于两个地方:

  1. 从训练集中分词得到。
  2. 从开源中文分词工具hanlp的机构名词典中整理得到。

特征③:【是否是地点】,该词是地点,标记为isloc;该词不是地点,标记为notloc。这里的地点信息我们是从jieba的分词词性标注功能中得到的,词性标注为ns的一般是地点。

特征④:【是否是句子结束】,该词是这个句子的结束词,标记为isend;否则标记为notend。

训练文本在经过预处理之后,格式如下:

宁夏      ns   0     isloc      notend B

物美      nz   0     notloc  notend M

超市      v     1     notloc  notend M

有限公司    n     1     notloc  notend M

森林公园    n     0     notloc  notend M

   n     1     notloc  isend    E

其中,第一列为词本身,第二列为特征①,第三列为特征②,第四列为特征③,第五列为特征④,第六列列为正确标注。

测试文本的预处理和上面的基本一样,区别在于,测试文本没有正确的实体标注,所以测试文本的预处理文件只有五列。最后我们要用CRF模型预测的是第六列标注。

3.3训练CRF模型

CRF模型的训练,需要一个特征模板,以便能够自动在训练文本中提取特征函数,特征模板的定义直接决定了最后的识别效果

针对此次的机构实体,我们定义了几种特征模板,最终选择了以下模板:

# Unigram

U01:%x[-2,0]

U02:%x[-1,0]

U03:%x[0,0]

U04:%x[1,0]

U05:%x[2,0]

U06:%x[-2,0]/%x[-1,0]/%x[0,0]

U07:%x[-1,0]/%x[0,0]/%x[1,0]

U08:%x[0,0]/%x[1,0]/%x[2,0]

U09:%x[-1,0]/%x[0,0]

U10:%x[0,0]/%x[1,0]

U11:%x[-1,1]/%x[0,1]/%x[1,1]

U12:%x[-1,1]/%x[0,1]

U13:%x[0,1]/%x[1,1]

U14:%x[0,1]/%x[0,2]

U15:%x[-1,1]/%x[0,2]

U16:%x[-2,1]/%x[-1,1]/%x[0,2]

U17:%x[-1,1]/%x[0,2]/%x[1,1]

U18:%x[0,2]/%x[1,1]/%x[2,1]

U19:%x[0,0]/%x[0,2]

U20:%x[-1,0]/%x[0,2]

U21:%x[-2,0]/%x[-1,0]/%x[0,2]

U22:%x[-1,0]/%x[0,2]/%x[1,0]

U23:%x[0,2]/%x[1,0]/%x[2,0]

# Bigram

B

下面解释一下上述特征模板:

①Unigram类型

每一行%x[#,#]生成一个CRFs中的点(state)函数: f(s, o), 其中s为t时刻的标签(output),o为t时刻的上下文以及特征信息。

比如:U06:%x[-2,0]/%x[-1,0]/%x[0,0]

U06是指这个特征模板的编号,对于%x[-2,0]而言,%x是指找到的字符;[-2,0]是定位信息,其中中括号里面的-2是指当前词的前两个词,0是指第0列。后面用/连接的是多个特征的组合。

对于以下的训练文本:

宁夏     ns   0     isloc      notend B

物美     nz   0     notloc  notend M

超市     v     1     notloc  notend M

有限公司   n     1     notloc  notend M

森林公园   n     0     notloc  notend M

  n     1     notloc  isend    E

假如当前识别到第三行,则U06:%x[-2,0]/%x[-1,0]/%x[0,0]对应识别出来的文本为宁夏/物美/超市。

这就相当于我们在文本中找到的一条特征。

②Bigram类型

每一行%x[#,#]生成一个CRFs中的边(Edge)函数:f(s’, s, o), 其中s’为t – 1时刻的标签.也就是说,Bigram类型与Unigram大致机同,只是还要考虑到t – 1时刻的标签.这里只写一个B,默认生成f(s’, s).

有了特征模板以及训练文本文件,就可以进行CRF模型训练了,我们采用了CRF++这个开源工具包进行训练,使用默认参数,最终模型识别出来的特征有11616755条。

3.4预测、生成实体

有了上述预处理测试文本和训练生成的CRF模型,我们可以进行测试文本的标签预测,生成crf_test_output.txt

由于crf_test_output.txt里面预测的是每个词背后的标注,我们还要做一个后处理工作才能把真正的实体提取出来。

用正则表达式B+M*E+或者W匹配文本,然后将其背后的文字提取出来,就是识别出来的机构实体。

3.4效果和缺点

在使用CRF模型之后,我们得到了不错的效果。线下训练文本的实体召回率可以达到91.3%,另外,识别出来的无效实体也少了很多。

和基于规则的实体识别相比,它有着以下优点:

  • 通过特征模板,能够最大限度的挖掘文本的特征,而不需要人工提取。
  • 能够考虑大量的上下文信息、特征。
  • 考虑了相邻词的标注信息,这是传统的最大熵算法所不具备的。
  • 和神经网络模型相比,CRF模型的可解释性强,具体到每一个特征都有可以解释的意义。因此调整起来比较容易。

当然,这个模型也不是完美的,比如,我们训练的这个模型就比较“看重”机构特征词。举个例子,如果“下属公司”单独出现,则它也可能会被识别为机构名,需要我们人工定义一些规则将其去除。


CRF++工具的使用就没有介绍了,训练的过程只需要预处理语料以及模板文件,预处理语料格式和模板文件,在上文已经体现出来了,感兴趣的朋友,缺少语料或者工具,可以找我要。

代码和语料:
https://www.lookfor404.com/命名实体识别的语料和代码/

《用CRF做命名实体识别——NER系列(三)》有58个想法

  1. 你好,博主,可以把关于CRF实验的语料发我一份吗?我也对这方面实验感兴趣,看了你的博客觉得很有帮助,十分感谢,邮箱1528619012@qq.com,真的很感谢!

  2. 您好博主,最近在做命名实体识别,看了您的文章觉得很有帮助,可以把关于CRF实验的语料也发我一份么,我想试试看能不能复现您的流程,真的很感谢您。
    邮箱:724601318@qq.com
    麻烦您了

  3. 提示提交评论失败。。再发一次
    非常感谢楼主很细致的讲述和研究,跟着您hmm的数据和代码能理解的很透传;麻烦您给一份crfpp的数据和代码吧,非常感谢。邮箱:540046370@qq.com

  4. 楼主,看了您的文章感觉受益匪浅,最近一直在做ner方面相关的研究,望您能在百忙之中,抽出点时间,能够您的crf实现和结合crf与lstm实现的代码和语料发我借我阅读,在下不胜感激,邮箱364675265@qq.com

  5. 楼主你好,我现在要做特定领域的实体识别任务,只有少量的领域词典,请问有什么比较好的语料标注工具介绍一下吗?谢谢~

  6. 博主,最近玩一个项目,涉及到命名实体识别,感觉文章写的真的是深入浅出,手动赞一个,话说可以把关于CRF实验的语料发我一份么,邮箱:1063745232@qq.com,么么哒。

  7. 博主你好,你的整个命名实体识别系列写的非常好,一步步深入。我最近在做新闻数据的命名实体识别,可以把这个CRF的代码发给我吗?麻烦了 邮箱1490494835@qq.com

  8. 你好,刚接触这一块,真是收益匪浅?我想问一下这个是不是也可以做关于时间的标注,比如“昨天”,“明天”提取有关时间的标记,然后转换成日期格式,还有能不能把这份代码和数据发一份,1096099464@qq.com,不胜感激

    1. 理论上,序列标注就是时序相关的数据~
      代码以及语料:https://www.lookfor404.com/命名实体识别的语料和代码/

  9. 你好,我最近在学习NER,你写的前几篇文章我都仔细阅读并写代码做了实现,收获很大。请问这一篇文章的语料可以分享一下吗?
    我的邮箱是745366246@qq.com,十分感谢。

  10. hello,楼主,我最近也在对比人工特征,和RNN提取特征之后的crf标注结果对比,能否分享一下您整理的相关资料呢,万分感谢!我的邮箱是1280197133@qq.com

  11. 非常感谢博主细致的讲述,我最近刚接触NER,能否给发下crf的代码和语料,非常感谢!!!邮箱:990795617@qq.com

  12. 博主您好,我最近在学ner,看见您写的很清晰,可以把ner这个系列的1,2,3,4的代码发我邮箱一下吗,我的邮箱是1402072392@qq.com,十分感谢。

    1. 你好,我不是博士。/捂脸
      语料代码参看:https://www.lookfor404.com/命名实体识别的语料和代码/

  13. 博士您好,写的很清楚了。您本节实验的语料和代码,可以发我一份吗?谢谢了。1030624832@qq.com

    1. 请自取哈:https://www.lookfor404.com/%e5%91%bd%e5%90%8d%e5%ae%9e%e4%bd%93%e8%af%86%e5%88%ab%e7%9a%84%e8%af%ad%e6%96%99%e5%92%8c%e4%bb%a3%e7%a0%81/

  14. 楼主您好,最近在实验crf做命名实体的识别,能否发一份您的实现代码和语料,万分感谢。
    邮箱2529253059@qq.com

      1. 博主您好!看了您写的博客收获很多,写的很有条理,我是NER新手,您贴的代码好像链接都没有了,可以麻烦您发一份这个比赛crf资料和代码吗?我的邮箱1477241758@qq.com,谢谢博主大佬啦!后续可以加您交流一下吗

  15. 您好
    想請教一下,如果我手上已經備有一份專業領域的詞典,請問需要在您第二章節裡的圖片的哪個區塊加入判斷?或是這個專業的辭典應該要編入訓練文本裡面一同訓練?

  16. 您好,请问关于CRF这个比赛的代码您还有吗,希望您发一份我参考下,邮箱:1063962573@qq.com

  17. 博主您好!看了您写的博客收获很多,写的很有条理,我是NER新手,您贴的代码好像链接都没有了,可以麻烦您发一份这个比赛crf资料和代码吗?我的邮箱1477241758@qq.com,谢谢博主大佬啦!后续可以加您交流一下吗

  18. 您好,可以指导我一下相关的东西吗?还是有些不清楚。比如特征模板的部分。如果可以的话加一下我的QQ 704097584

  19. 你好,我大三本科在读,最近在做有关CRF命名实体识别实验,能麻烦你发一下这个实验代码和语料吗?谢谢!我的qq:1262639259@qq.com

赵聪进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注