用CRF做命名实体识别(三)

用CRF做命名实体识别(三)

标签: CRF
作者:炼己者


欢迎大家访问我的以及我的博客
本博客所有内容以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢!


命名实体识别系列

用CRF做命名实体识别(一)
用CRF做命名实体识别(二)
用BILSTM-CRF做命名实体识别


摘要

本文主要是对近期做的命名实体识别做一个总结,会给出构造一个特征的大概思路,以及对比所有构造的特征对结构的影响。先给出我最近做出来的特征对比:

特征 F1值 精度 召回率
0.8399 0.8472 0.8327
字+词性+边界 0.8711 0.8839 0.8589
字+词性+边界+实体指示词 0.8856 0.9076 0.8649
字+词性+边界+特征词 0.8847 0.8990 0.8709
字+词性+边界+实体指示词 +特征词 0.8853 0.8994 0.8718
字+词性+边界+常用词 0.928 0.9382 0.9182
字+词性+边界+特征词+常用词 0.9293 0.9381 0.9207
字+词性+边界+实体指示词+特征词+常用词 0.9261 0.9334 0.9191

目录

  • 整体操作流程
  • 特征的构造思路
  • 用CRF++训练模型
  • 用CRF++测试模型并计算F1值

正文

1.整体操作流程

  • 构造特征,然后合并,格式要符合CRF++训练的格式
  • 撰写对应的特征模板
  • 用CRF++训练模型
  • 用CRF++测试模型并计算F1值

2.特征的构造思路

  1. 构造词性

用jieba标注分词即可,直接调用jieba


2)构造词语边界特征

迈   B
向   E
充   B
满   M
希   M
望   E
的   W
新   B
世   M
纪   E

思路:

我们把句子先用jieba进行分词,然后遍历所有的词,用len函数判断这个词的长度,如果长度是1,那么标记为W,否则首部(word[0])标记为B,中间(word[1:-1])标记为M,尾部(word[-1])标记为E


  1. 构造实体指示词特征

首先肯定会问什么是实体指示词呢?

在中文中,有些词的出现通常标志着该词周围很可能出现相应的命名实体,这样的词,我们称之为命名实体指示词。命名实体指示词是文本中非常有意义的上下文信息,可以有效的帮助识别命名实体。通常可以分为人名指示词、地名指示词和组织名指示词。
比如:温家宝总理主持了政府工作报告。这句话中“总理”这个词很大程度上指示着人名实体温家宝的出现 。

我用人民日报标注语料提取了人名,地名,组织名指示词。先给大家看一下地名指示词大概长什么样子

['向/p',
 '同胞/n',
 '和/c',
 '是/v',
 '发展/vn',
 '历史/n',
 '年/q',
 '人民/n',
 '建设/v',
 '有/v',
 '特色/n',
 '社会主义/n',
 '恢复/v',
 '对/p',
 '主权/n',
......]

建立一个实体指示词表的思路:

(1)从人民日报标记语料库中按顺序读取一个词 ;
(2)如果这个词是一个标记了的命名实体则转(3),否则转(1);
(3)读取当前词左边的 2 个词和右边的 2 个词,组成上下文词汇集合word_text,若当前词左边或者右边的词数少于 2 个,则取尽可能多个;
(4)如果当前词的标记为地名,则在备选地名指示词集合 Indication_l 中查找 word_text中的词,如果找到了,则相应词的频度加 1;否则,将此词加入到 Indication_l 集合 中,该词频度设为 1;
(5)如果当前词是语料中的最后一个词,转(6),否则转(1);
(6)统计备选备选地名指示词集合 Indication_l中所有词汇在单位语料中出现的频度 f;
(7)如果频度 f 小于阈值(我设置的是20) ,删除该词;

建立好实体指示词表之后就该构建实体指示词这个特征了

a) 先对每句话进行jieba分词,注意是不带标注的jieba分词
b) 遍历每个词,判断这个词是否在我们的实体指示词表里,在的话我们就做个标记是Y,不在的话就标记为N
c) 然后用len函数判断这个词的长度,依次写入我们的标记即可


  1. 构造特征词

什么是特征词呢?
比如人名都是以姓氏开头的,所以它的特征词就是姓氏;组织名基本都是以特定的词汇结尾,比如公司,学校,集团等等;地名都是以省,市,国等特定的词结尾。这些都是特征词。这些特征词都可以从百度中查到,我们下载下来,这样就有三个文件。

思路

关于姓氏这个特征词的构造比较简单,因为它只有一个字,我们只需遍历每个字,然后判断这个字是不是在我们的姓氏表里,在的话标记为Y,不在的话标记为N。

中   N
共   N
中   N
央   N
总   N
书   N
记   N
、   N
国   N
家   N
主   N
席   N
江   Y
泽   N
民   N

关于地名和组织名的特征词构造有点麻烦,因为它是多个字。不过和上面构建实体指示词特征的思路一样
a) 先对每句话进行jieba分词,注意是不带标注的jieba分词
b) 遍历每个词,判断这个词是否在我们的特征词表里,在的话我们就做个标记是Y,不在的话就标记为N
c) 然后用len函数判断这个词的长度,依次写入我们的标记即可


5)构造常用词

什么是常用词呢?
比如常见的人名王伟,张伟等,常见的地名其实就是中国的所有地名,包括各种村什么的,还有常用的组织名,这些都可以从网上找到。这样就可以得到三个文件。
比如组织名"中共中央"就被找到,并标记为Y

中   Y
共   Y
中   Y
央   Y
总   N
书   N
记   N
、   N
国   N
家   N
主   N
席   N
江   N
泽   N
民   N

和上面构建实体指示词特征的思路一样
a) 先对每句话进行jieba分词,注意是不带标注的jieba分词
b) 遍历每个词,判断这个词是否在我们的常用词表里,在的话我们就做个标记是Y,不在的话就标记为N
c) 然后用len函数判断这个词的长度,依次写入我们的标记即可


6)构造标签
对文本进行jieba标注分词后,我们会得到每个词的词性,然后观察发现,人名标注词性为/nr,组织名是/nt,地名是/ns。这样我们就可以遍历所有的词,先判断词性,再结合前面构造边界的方法便可以构造了。

迈   O
向   O
充   O
满   O
希   O
望   O
的   O
新   O
世   O
纪   O
—   O
—   O
一   B_TIME
九   M_TIME
九   M_TIME
八   M_TIME
年   E_TIME
新   B_TIME
年   E_TIME
讲   O
话   O
(   O
附   O
图   O
片   O
1   O
张   O
)   O

7)构造好特征就是合并特征了,我用的是dataframe操作的
下面的特征顺序依次是
(字+词性+边界+地方指示词+组织名指示词+人名指示词+姓氏+地名特征词+组织名特征词+标签)

迈   v   B   N   N   N   N   N   N   O
向   v   E   N   N   N   N   N   N   O
充   nz  B   N   N   N   N   N   N   O
满   nz  M   N   N   N   N   N   N   O
希   nz  M   N   N   N   N   N   N   O
望   nz  E   N   N   N   N   N   N   O
的   uj  W   Y   Y   Y   N   N   N   O
新   nz  B   N   N   N   N   N   N   O
世   nz  M   N   N   N   N   N   N   O
纪   nz  E   N   N   N   N   N   N   O
—   x   W   N   N   N   N   N   N   O
—   x   W   N   N   N   N   N   N   O
一   m   B   N   N   N   N   N   N   B_TIME
九   m   M   N   N   N   N   N   N   M_TIME
九   m   M   N   N   N   N   N   N   M_TIME
八   m   M   N   N   N   N   N   N   M_TIME
年   m   E   N   N   N   N   N   N   E_TIME
新   t   B   Y   N   N   N   N   N   B_TIME
年   t   E   Y   N   N   N   N   N   E_TIME
讲   n   B   N   N   Y   N   N   N   O
话   n   E   N   N   Y   N   N   N   O
(   x   W   N   N   N   N   N   N   O
附   n   B   N   N   N   N   N   N   O
图   n   M   N   N   N   N   N   N   O
片   n   E   N   N   N   N   N   N   O
1   m   W   Y   N   N   N   N   N   O
张   nr  W   N   N   N   Y   N   N   O
)   x   W   N   N   N   N   N   N   O

合并好所有的特征之后这就是划分我们的数据集了,为了计算F1值我们还要把它们划分为训练集(70%)和测试集(30%)。


3.特征模板

比如下面的特征模板就是针对
(字+词性+边界+地方指示词+组织名指示词+人名指示词+姓氏+地名特征词+组织名特征词)这几个特征写的

# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-2,1]
U06:%x[-1,1]
U07:%x[0,1]
U08:%x[1,1]
U09:%x[2,1]
U10:%x[0,0]/%x[0,1]
U11:%x[0,0]/%x[1,0]
U12:%x[0,0]/%x[-1,0]
U13:%x[-1,0]/%x[0,1]
U14:%x[0,0]/%x[1,1]
U15:%x[-1,0]/%x[-1,1]
U16:%x[-1,0]/%x[-2,0]
U17:%x[-2,0]/%x[-2,1]
U18:%x[1,0]/%x[2,0]
U19:%x[-1,1]/%x[1,0]
U20:%x[0,1]/%x[1,0]
U21:%x[-2,1]/%x[-1,1]
U22:%x[0,1]/%x[-2,1]
U23:%x[-1,1]/%x[0,1]
U24:%x[-1,1]/%x[1,1]
U25:%x[0,1]/%x[1,1]
U26:%x[0,1]/%x[2,1]
U27:%x[1,1]/%x[2,1]
U28:%x[-1,2]
U29:%x[-2,2]
U30:%x[-1,2]/%x[-2,2]
U31:%x[0,1]/%x[-1,2]
U32:%x[0,1]/%x[-2,2]
U33:%x[0,1]/%x[1,2]
U34:%x[0,0]/%x[-1,2]
U35:%x[0,0]/%x[-2,2]
U36:%x[0,0]/%x[1,2]
U37:%x[0,1]/%x[-1,2]/%x[-2,2]
U38:%x[-1,2]/%x[0,1]/%x[1,1]
U39:%x[-1,2]/%x[-1,1]/%x[0,1]
U40:%x[-1,2]/%x[0,1]/%x[0,0]
U41:%x[-2,2]/%x[-1,2]/%x[0,1]
U42:%x[-2,3]/%x[-1,3]/%x[1,3]/%x[2,3]
U43:%x[-2,4]/%x[-1,4]/%x[1,4]/%x[2,4]
U44:%x[-2,5]/%x[-1,5]/%x[1,5]/%x[2,5]
U45:%x[0,6]
U46:%x[0,7]
U47:%x[0,8]
U48:%x[1,8]
U49:%x[2,8]
U50:%x[-2,5]/%x[-1,5]/%x[0,6]/%x[1,5]/%x[2,5]
U51:%x[-2,3]/%x[-1,3]/%x[0,7]
U52:%x[-2,4]/%x[-1,4]/%x[0,8]

# Bigram
B

写特征模板首先是要把所有的特征都要罗列进去,然后特征模板里面比如说
“U50:%x[-2,5]/%x[-1,5]/%x[0,6]/%x[1,5]%x[2,5]”这句话的意思就是
当前字是否为姓氏,且它的左边和右边两个字是否为人名指示词

%x[-1,5]里面表示[-1行,5列]。0代表的是当前这个字,那么-1不就是代表前一个字么,而那个第五列指的就是第五个特征(注意我构造的特征的顺序,前面有说到),也就是对应的人名指示词这个特征了


4.用CRF++训练模型

具体操作就看我的里关于CRF++训练的操作,那里有详细的介绍。


5.用CRF++测试模型并计算F1值

调用sklearn库即可,非常简单
很重要的一点计算F1值一定记住把预测值和真实值都是O的全部删掉。比如说下面,倒数第二列是真实值,最后一列是预测值。为什么要删掉两列都是O的呢?因为整个数据集这样的太多了,会导致F1值偏高,我之前就把这部分算进去了,结果F1值为0.98,还沾沾自喜,以为自己好厉害

谈   v   B   N   N   N   N   N   N   O   O
到   v   E   N   N   N   N   N   N   O   O
亚   ns  B   N   N   N   N   N   N   B_LOCATION  B_LOCATION
洲   ns  E   N   N   N   N   N   N   E_LOCATION  E_LOCATION
金   n   B   Y   N   N   Y   N   N   O   O
融   n   E   Y   N   N   N   N   N   O   O
风   n   B   N   N   N   N   N   N   O   O
波   n   E   N   N   N   N   N   N   O   O
,   x   W   N   N   N   N   N   N   O   O
董   nr  B   N   N   N   Y   N   N   B_PERSON    B_PERSON
建   nr  M   N   N   N   N   N   N   M_PERSON    M_PERSON
华   nr  E   N   N   N   N   N   N   E_PERSON    E_PERSON
说   v   W   Y   Y   Y   N   N   N   O   O
:   x   W   N   N   N   N   N   N   O   O
“   x   W   N   N   N   N   N   N   O   O
香   ns  B   N   N   N   N   N   N   B_LOCATION  B_LOCATION
港   ns  E   N   N   N   N   N   N   E_LOCATION  E_LOCATION
将   d   W   Y   Y   Y   N   N   N   O   O
坚   i   B   N   N   N   N   N   N   O   O
定   i   M   N   N   N   N   N   N   O   O
不   i   M   N   N   N   N   N   N   O   O
移   i   E   N   N   N   N   N   N   O   O
地   uv  W   Y   N   Y   N   N   N   O   O

6.展望

用CRF做命名实体识别基本就做到这里了,我们发现(字+词性+边界+特征词+常用词)这几个特征可以达到比较好的效果,F1值为0.9293。再加入特征效果就会下降了,而且训练时间也会加长。后面打算用神经网络来做命名实体识别,目前主流方法是BILSTM-CRF,据说效果是很好的,网上有可以直接用的代码,回来操作一下。希望这篇博文会对大家有所帮助,至少可以帮大家入门命名实体识别。


以下是我所有文章的目录,大家如果感兴趣,也可以前往查看
戳右边:打开它,也许会看到很多对你有帮助的文章

你可能感兴趣的:(用CRF做命名实体识别(三))