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

一. 摘要

本文是对上文用CRF做命名实体识别(一)做一次升级。多添加了5个特征(分别是词性,词语边界,人名,地名,组织名指示词),另外还修改了特征模板,最终训练了11个小时,F1值为0.98。(这里面有错误,计算F1值不应该计算全体的,应该只计算带有标注实体的词,不然量这么大,肯定F1值就大。最终改了计算F1值的方法,F1值为0.8856)

二. 目录

  • 整个流程的思路
  • 一些概念解释
    - 实体指示词
    - 词语边界
    - 为什么要用jieba再次分词标注词性
  • 具体流程实现
  • 总结与展望

三. 正文

1. 整个流程的思路:

  • 根据人民日报语料库建立命名实体指示词库
  • 构建人名,地名,组织名指示词特征
  • 构建词性特征以及词语边界特征
  • 将这五个特征合并,形成CRF++的训练数据格式
  • 编写特征模板
  • 划分数据集为训练集和测试集
  • 用CRF++训练模型
  • 测试模型

2. 上面出现的一些概念解释

2.1 实体指示词

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

2.2 词语边界

一个词有头有尾,我们给它进行位置标注。B代表词语的头部,M代表词语的中间部位,E代表词语的尾部,W代表一个词。如下所示:

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

2.3 为什么要用jieba再次分词标注词性

因为人民日报标注语料是人工标注的。我们构造了词性这个特征,测试的时候我们不可能对要测试的语料进行人工标注词性,这样工程量太大了,所以我们直接用jieba分词标注,这样训练和测试都是用的jieba标注的词性。


3. 具体流程实现

3.1 根据人民日报语料库建立命名实体指示词库

1)建立地名指示词库

(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) ,删除该词;
下图便是地名指示词

['向/p',
 '同胞/n',
 '和/c',
 '是/v',
 '发展/vn',
 '历史/n',
 '年/q',
 '人民/n',
 '建设/v',
 '有/v',
 '特色/n',
 '社会主义/n',
 '恢复/v',
 '对/p',
 '主权/n',
......]
2)同理建立人名指示词库以及组织名指示词库

3.2 构建人名,地名,组织名指示词特征

1)构建地名指示词特征
  • A. 读入数据
['迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  ——/w  一九九八年/t  新年/t  讲话/n  (/w  附/v  图片/n  1/m  张/q  )/w',
 '中共中央/nt  总书记/n  、/w  国家/n  主席/n  江泽民/nr',
 '(/w  一九九七年/t  十二月/t  三十一日/t  )/w',
 '12月/t  31日/t  ,/w  中共中央/nt  总书记/n  、/w  国家/n  主席/n  江泽民/nr  发表/v  1998年/t  新年/t  讲话/n  《/w  迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  》/w  。/w  (/w  新华社/nt  记者/n  兰红光/nr  摄/Vg  )/w',
 '同胞/n  们/k  、/w  朋友/n  们/k  、/w  女士/n  们/k  、/w  先生/n  们/k  :/w',......]

  • B. 提取上面列表里的地名实体
    • 空列表表示这句话里面没有我们的地名实体
[[],
 [],
 [],
 [],
 [],
 ['香港特别行政区/ns', '澳门/ns', '台湾/ns'],
 ['中国/ns', '中国/ns', '中国/ns', '香港/ns', '香港/ns', '中国/ns'],
 ['中国/ns', '中国/ns'],
......]
  • C. 将列表里的每个元素变成只含有中文的句子
['迈向充满希望的新世纪——一九九八年新年讲话(附图片1张)',
 '中共中央总书记、国家主席江泽民',
 '(一九九七年十二月三十一日)',
 '12月31日,中共中央总书记、国家主席江泽民发表1998年新年讲话《迈向充满希望的新世纪》。(新华社记者兰红光摄)',
 '同胞们、朋友们、女士们、先生们:',......]

  • D. 对列表里的每个元素进行jieba分词标注词性
['迈向/v  充满希望/nz  的/uj  新世纪/nz  —/x  —/x  一九九八年/m  新年/t  讲话/n  (/x  附图片/n  1/m  张/nr  )/x',
 '中共中央/nt  总书记/n  、/x  国家/n  主席/n  江泽民/nr',
 '(/x  一九九七年/m  十二月/m  三十一日/m  )/x',
 '12/m  月/m  31/m  日/m  ,/x  中共中央/nt  总书记/n  、/x  国家/n  主席/n  江泽民/nr  发表/v  1998/m  年/m  新年/t  讲话/n  《/x  迈向/v  充满希望/nz  的/uj  新世纪/nz  》/x  。/x  (/x  新华社/nt  记者/n  兰红光/nr  摄/vg  )/x',
 '同胞们/n  、/x  朋友/n  们/k  、/x  女士们/n  、/x  先生/n  们/k  :/x',......]

  • E. 去掉列表里面的空格,让它更紧凑
['迈向/v充满希望/nz的/uj新世纪/nz—/x—/x一九九八年/m新年/t讲话/n(/x附图片/n1/m张/nr)/x',
 '中共中央/nt总书记/n、/x国家/n主席/n江泽民/nr',
 '(/x一九九七年/m十二月/m三十一日/m)/x',
 '12/m月/m31/m日/m,/x中共中央/nt总书记/n、/x国家/n主席/n江泽民/nr发表/v1998/m年/m新年/t讲话/n《/x迈向/v充满希望/nz的/uj新世纪/nz》/x。/x(/x新华社/nt记者/n兰红光/nr摄/vg)/x',
 '同胞们/n、/x朋友/n们/k、/x女士们/n、/x先生/n们/k:/x',......]

  • F. 读取我们前面构建的地名指示词表
['向/p',
 '同胞/n',
 '和/c',
 '是/v',
 '发展/vn',
 '历史/n',
 '年/q',
 '人民/n',
 '建设/v',
 '有/v',
 '特色/n',
 '社会主义/n',
 '恢复/v',
 '对/p',
 '主权/n',
......]
  • G. 取出每一句话的地名指示词
[[[]],
 [[]],
 [[]],
 [[]],
 [[]],
 [[], [], []],
 [['是/v'], ['是/v'], ['是/v'], ['对/p'], ['对/p'], ['是/v']],
 [[], []],
 [['和/c'], ['和/c'], ['与/p'], [], [], [], ['和/c'], ['和/c'], [], ['和/c'], []],
 [['有/v', '建设/vn'], ['有/v', '建设/vn']],
 [[], ['和/c'], ['和/c']],
 [[], ['是/v'], ['是/v'], [], [], ['是/v']],......]
  • H. 美化一下
[[],
 [],
 [],
 [],
 [],
 [],
 ['是/v', '是/v', '是/v', '对/p', '对/p', '是/v'],
 [],
 ['和/c', '和/c', '与/p', '和/c', '和/c', '和/c'],
 ['有/v', '建设/vn', '有/v', '建设/vn'],
 ['和/c', '和/c'],
 ['是/v', '是/v', '是/v'],......]
  • J. 替换取出来的地名指示词里面的标签
[[],
 [],
 [],
 [],
 [],
 [],
 ['是/pi', '是/pi', '是/pi', '对/pi', '对/pi', '是/pi'],
 [],
 ['和/pi', '和/pi', '与/pi', '和/pi', '和/pi', '和/pi'],
 ['有/pi', '建设/pi', '有/pi', '建设/pi'],
 ['和/pi', '和/pi'],
 ['是/pi', '是/pi', '是/pi'],......]
  • K. 改变每句话里的实体指示词的标签
# 发现下面的 '与/p' 被改成了 '与/pi'
' ... 通过/p  高层/n  互访/v  ,/x  中国/ns  与/pi  美国/ns  、/x  俄罗斯/ns  、/x  法国/ns  ... '
  • L. 对上面列表里面的每句话进行切分,做成列表
[['迈向/v',
  '充满希望/nz',
  '的/uj',
  '新世纪/nz',
  '—/x',
  '—/x',
  '一九九八年/m',
  '新年/t',
  '讲话/n',
  '(/x',
  '附图片/n',
  '1/m',
  '张/nr',
  ')/x'],
 ['中共中央/nt', '总书记/n', '、/x', '国家/n', '主席/n', '江泽民/nr'],......]
  • M. 写入外部文件
    • 写成下面的形式,是地名指示词就标注为Y,不是就标注为N
未   N
来   N
发   N
展   N
的   N
目   N
标   N
和   Y
指   N
导   N
方   N
针   N
。   N
中   N
国   N
与   Y
周   N
边   N
国   N
家   N
和   Y

到这里我们就构建好了地名指示词特征了

2)同理构建人名,组织名指示词特征

3.3 构建词性特征以及词语边界特征

1)构建词性特征
迈   v
向   v
充   nz
满   nz
希   nz
望   nz
的   uj
新   nz
世   nz
纪   nz
2)构建词语边界特征
迈   B
向   E
充   B
满   M
希   M
望   E
的   W
新   B
世   M
纪   E

3.4 将这五个特征合并,形成CRF++的训练数据格式

从左到右的特征依次为字符,词性,词语边界,地名指示词,组织名指示词,人名指示词,标签。(最后一列在用CRF做命名实体识别(一)中有讨论过,这里不再赘述)

年   a   B   N   N   N   O
轻   a   E   N   N   N   O
时   n   W   N   N   N   O
,   x   W   N   N   N   O
在   p   W   Y   N   N   O
重   ns  B   N   N   N   B_LOCATION
庆   ns  E   N   N   N   E_LOCATION
山   ns  B   N   N   N   O
城   ns  E   N   N   N   O
,   x   W   N   N   N   O
在   p   W   Y   N   N   O
红   n   B   N   N   N   B_LOCATION
岩   n   E   N   N   N   M_LOCATION
嘴   n   W   N   N   N   E_LOCATION
山   n   B   N   N   N   O
头   n   E   N   N   N   O
的   uj  W   N   N   N   O
楼   n   B   N   N   N   O
房   n   E   N   N   N   O
,   x   W   N   N   N   O
我   r   B   N   N   N   O
们   r   E   N   N   N   O
红   nr  B   N   N   N   B_ORGANIZATION
岩   nr  E   N   N   N   M_ORGANIZATION
歌   n   B   N   N   N   M_ORGANIZATION
咏   n   E   N   N   N   M_ORGANIZATION
团   n   W   N   N   N   E_ORGANIZATION
的   uj  W   N   N   N   O
男   n   B   N   N   N   O
女   n   E   N   N   N   O
青   t   B   N   N   N   O
年   t   E   N   N   N   O

3.5 特征模板

# 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]

# Bigram
B

3.6 划分数据集为训练集和测试集

  • 这里我是70%为训练集,30%为测试集。主要是为了测F1值

3.7 训练的方法同用CRF做命名实体识别(一)

3.8 测试模型

  • F1值的计算用了sklearn库,最终得值是0.8856
  • 从网上下载了一些新闻语料库,也是要处理成上面的那种格式(CRF++可以训练数据的格式),最终效果还可以,主要还是得看jieba分词标注词性的效果

四. 总结与展望

整个流程走完了,最后得出的效果也很不错,接下来打算把CRF的原理好好理一遍,以及用BI-LSTM-CRF方法做命名实体识别,据说这是目前的主流处理方法。


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

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