命名实体识别之CRF++(吐血整理)
吐血整理CRF++工具,只能说走条路的人都不容易,没个师兄师姐带路,你走一辈子都不一定走得出去。这东西出来的太早了,命名实体识别是自然语言处理非常基础性的工作,所有已经没什么人做了,大都直接用工具耍耍。而当年的工具原地址什么一大堆的都不见得在了。没办法,谁有珍藏都是宝贝。本文从零起步,一步步探索十五年前前人走过的路,吐血整理日记。
1. 准备工作
1.1 准备训练文件和测试文件
训练文件和测试文件都由空行隔开的若干个序列组成,每个序列对应一个句子。序列包含多个的token,一个token对应一个词,独占一行,占据多列,列数虽然不限但是所有token的列数必须相同。大多数情况下,token包含3列,分别是word,POS tag,sub-category of POS. 看一下官网的例子:
训练文件和测试文件格式1.2 准备模板文件
由于CRF++是作为通用工具设计的,所以必须事先指定特征模板。该文件描述了在训练和测试中使用哪些特征。
模板基础与宏 模板文件的每一行都代表一个模板,通常用%x[row,col]来定义,row是当前token位置的行偏移,用相对位置来指定行(+n表示下面第n行,-n表示上面第n行),col直接用绝对位置来指定列。以下图为例,当前token为"the DT B-NP"。那么%x[0,1]表示当前行的第二列,即DT;而%x[-2,1]表示当前行上面两行的第二列,即PRP.
输入文件 模板样例模板类型 模板包括两种类型,一种是Unigram,一种是Bigram. Unigram模板下,CRF++会自动根据%x[0,1]生成以下特征函数。现在来解释这些由if-else构成的特征函数从何而来,从上面的输入文件可知,输出总共有L种(B-NP, I-NP, .... , O), 模板产生的唯一的特征数有N种(DT, NN, ...),那么特征函数就有L*N种。
func1 = if (output = B-NP and feature="U01:DT") return 1 else return 0
func2 = if (output = I-NP and feature="U01:DT") return 1 else return 0
func3 = if (output = O and feature="U01:DT") return 1 else return 0
....
funcXX = if (output = B-NP and feature="U01:NN") return 1 else return 0
funcXY = if (output = O and feature="U01:NN") return 1 else return 0
...
标志符来区分相对位置 如果要区分相对位置,则需要添加identifier. 如果%x[-2,1]和%x[1,1]指向的都是DT,而需要区分那么,就写成
U01:%x[-2,1]
U02:%x[1,1]
给出一个样例模板文件,这个样例文件中的空行只是为了美观,你只要保证后面的identifier中的数字比前面的identifier中的数字大就行。
# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-1,0]/%x[0,0]
U06:%x[0,0]/%x[1,0]
U10:%x[-2,1]
U11:%x[-1,1]
U12:%x[0,1]
U13:%x[1,1]
U14:%x[2,1]
U15:%x[-2,1]/%x[-1,1]
U16:%x[-1,1]/%x[0,1]
U17:%x[0,1]/%x[1,1]
U18:%x[1,1]/%x[2,1]
U20:%x[-2,1]/%x[-1,1]/%x[0,1]
U21:%x[-1,1]/%x[0,1]/%x[1,1]
U22:%x[0,1]/%x[1,1]/%x[2,1]
# Bigram
B
2. 训练(Encoding)
提前准备好模板文件和训练文件,crf_learn生成训练好的模型文件model_file
crf_learn template_file train_file model_file
# 将训练过程信息输出到文件
crf_learn template_file train_file model_file > train_info_file
3. 测试(Decoding)
# 这里的-m不要掉了
crf_test -m model_file test_files > output.txt
测试的时候因为正确答案那一列没有删除,所有最后测试结果文件比测试文件多生成一列。这时利用一个工具可以计算最后的准确率和召回率等数据。
这个工具是一个perl语言写的脚本文件conlleval.pl,没错就是这么心酸,你需要耐心地在电脑上安装Perl环境,去官网上下载,然后在cmd命令行通过命令来运行这个工具
# 注意<,>分别是读入文件和输出文件的意思,不可省略,output.txt是测试生成文件,而result.txt是最后计算F1各种数据后保存的文件
perl conlleval.pl -r < output.txt > result.txt
4. 错误集锦
tagger.cpp(393) [feature_index_->buildFeature(this)]
训练文件的格式错误,注意特征数和文件编码(设定为UTF-8)
5. 后记之Unigram和Bigram的区别
image.pngimage.png