基于CRF++的中文名实体识别程序

OrdinAry

发布日期: 2019-04-07 09:37:06 浏览量: 1141
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

1 实验环境

  • win10

  • Python 3.7.0

  • CRF++-0.58

2 程序主要算法

条件随机场(CRF):

条件随机场定义:令 G = ( V , E ) 表示一个无向图, 任意一个节点v对应一个随机变量Y,因此Y = (v ∈ V) , Y中元素与无向图 G中的顶点一一对应。当在条件 Χ 下,随机变量 Y v 的条件概率分布服从图的马尔可夫属性:p ( | Χ , , w ≠ v ) = p ( | Χ , , w ~ v ) ,其中 w ~ v 表示 ( w , v) 是无向图 G 的边。这时我们称 ( Χ , Y ) 是一个条件随机场。

我们可以推出最终条件随机场的条件概率为:

其中,

训练CRF主要就是要训练特征函数的权重(即),对于训练集(x1,y1),(x2,y2),…,(xn,yn)(x1,y1),(x2,y2),…,(xn,yn),采用极大似然估计法计算权重参数,条件概率的对数似然函数为:

其中

为训练样本集中xy的经验概率,它等于xy同时出现的次数除以样本空间容量;

为训练样本集中x的经验概率,它等于x出现的次数除以样本空间容量。

只需要对似然函数求导为0,进行优化求解即可。

3 实验过程

1)对语料进行预处理。在本次实验中,采用的1998年人民日报分词数据集,格式如下

需要将其处理为crf++需要的训练数据格式:

其中,O标识不是查找的中文名,S标识该中文名只有一个字符,B表示中文名的第一个字符,M标识中文名的非开始/结束字符,E表示中文名的最后一个字符

在处理过程中,需要将语料转换为对应的标注,并将形如[华北/ns 电管局/n]nt进行合并,合并为华北电管局/nt。同时,从中去除部分数据作为测试集数据。在本次实验中,我抽取了25%的数据用作测试。

具体实现见代码setTag.py

2)编写特征模板文件,该文件描述了用来训练以及进行测试的特征

  1. # Unigram
  2. U01:%x[-1,0]
  3. U02:%x[0,0]
  4. U03:%x[1,0]
  5. U04:%x[2,0]
  6. U05:%x[-2,0]
  7. U06:%x[0,0]/%x[-1,0]
  8. U07:%x[0,0]/%x[1,0]
  9. U08:%x[-1,0]/%x[-2,0]
  10. U09:%x[1,0]/%x[2,0]
  11. U10:%x[-1,0]/%x[1,0]
  12. # Bigram
  13. B

3)执行crf_learn -f 3 -p 8 template.txt train.txt model命令,完成模型的学习,模型文件为model

其中,各参数含义为:

  • -f, –freq=INT使用属性的出现次数不少于INT(默认为1)

  • -p, –thread=INT线程数(默认1),利用多个CPU减少训练时间

训练过程如下:

4)通过crf_test -m model test.txt > test.rst命令完成对测试集数据的标注,标注后的test.tst文件如下

第一列为进行标注的中文字符,第二列为按照模型进行标注的结果,第三列为人工标注的结果。

5)根据对测试集的标注结果计算模型的各项参数:Precision,Recall,F1-Score.

  1. def test(path):
  2. file = open(path)
  3. tags = 0#被标记字的总数
  4. right = 0#标记正确的数目
  5. precisionTags = 0#所有标记出来的数目
  6. recallTags = 0#应该被标记的字的数目
  7. for line in file:
  8. line = line.strip()
  9. if(len(line)==0):
  10. continue
  11. tags += 1
  12. _word, tag_real, tag_point = line.split()
  13. if tag_point == tag_real and tag_point != 'O':
  14. right += 1
  15. if tag_point != 'O':#被标注的数据
  16. precisionTags += 1
  17. if tag_real != 'O':#应该被标注的数据
  18. recallTags += 1
  19. precision = float(right)/precisionTags
  20. recall = float(right)/recallTags
  21. f1Score = 2*precision*recall/(precision+recall)
  22. print("precision:%f, recall:%f, F1Score:%f\n"%(precision,recall,f1Score))
  23. test('test.rst')

6 实验结果

测试内容:

Precision:所有标注正确的词的数量/所标注出来的词的总数

Recall:所有标注正确的词的数量/应该标注的词的数量

执行结果如下:

分析test.rst文件我们可以看出:

1) 人工标注为地名而模型未能成功标注的结果

  1. O O
  2. O B
  3. O E
  4. O O
  5. O B
  6. O M
  7. O M
  8. 使 O M
  9. O E
  10. O O

对于中国,阿联酋这两个地名,模型未能成功识别

2)人工未标注为地名而模型识别为地名的情况:

  1. (1)
  2. O O
  3. O O
  4. O O
  5. B O
  6. M O
  7. M O
  8. E O
  9. O O
  10. O O
  11. (2)
  12. O O
  13. O O
  14. O O
  15. B O
  16. M O
  17. E O
  18. O O
  19. O O
  20. O O

在人工标注中,巴自治区以及维也纳未被标注为地名,而在模型中,将其识别为地名。

分析上述结果,我们可以看出:CRF算法通过对地名前后的词语进行提取,将其纳入模型的考虑范围中。在判断一个词是否为地名时,主要通过对前后的特征进行匹配,从而进行判断。因此,当前后不具有明显特征时,不能够对特征进行有效提取。同时,对于具有多重含义的词进行识别时,可能会识别错误。

7 实验结论和体会

CRF可以有效对中文名词进行识别,其主要通过对特征进行提取,生成模型,然后用模型来进行匹配。由于本次实验中,仅通过对词进行特征提取,效果没有达到最佳,为了提升识别的效果,可以将语料的词性作为特征进行提取或者扩充训练的语料。同时,可以对语料进行事先整理,提升识别效果

8 执行过程如下

  • 采用1998年人民日报分词数据集,文件为renmin.txt

  • 执行setTag.py文件(python setTag.py),用以生成CRF++格式标注的训练集以及测试集数据

  • 执行crf_learn -f 3 -p 8 template.txt train.txt model命令,生成模型(template可修改)

  • 执行crf_test -m model test.txt > test.rst命令,将该模型在测试集数据上进行测试,标注结果写到test.rst文件中
    test.rst文件格式如下:
    进行标记的字 完成的标记 真正的标记

  • 执行testResult.py文件(python testResult.py),查看识别效果

上传的附件 cloud_download 基于CRF++的中文名实体识别程序.zip ( 15.86mb, 3次下载 )
error_outline 下载需要11点积分

发送私信

有没有那样一种永远,永远永远不改变

12
文章数
32
评论数
最近文章
eject