欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2025/3/15 编程问答 34 豆豆
生活随笔 收集整理的这篇文章主要介绍了 用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。这里的特征词是指“实体通常的结尾词”,比如“有限公司”,“药监局”,“超市”等等,这些特征词来源于两个地方:

  • 从训练集中分词得到。
  • 从开源中文分词工具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模型的训练,需要一个特征模板,以便能够自动在训练文本中提取特征函数,特征模板的定义直接决定了最后的识别效果

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

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    # 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/命名实体识别的语料和代码/

     

    https://www.lookfor404.com/%e7%94%a8crf%e5%81%9a%e5%91%bd%e5%90%8d%e5%ae%9e%e4%bd%93%e8%af%86%e5%88%ab-ner%e7%b3%bb%e5%88%97%ef%bc%88%e4%b8%89%ef%bc%89/

    总结

    以上是生活随笔为你收集整理的用CRF做命名实体识别——NER系列(三)的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。