美文网首页机器学习与数据挖掘
命名实体识别之CRF++(吐血整理)

命名实体识别之CRF++(吐血整理)

作者: yangOvOyang | 来源:发表于2018-05-23 21:26 被阅读143次

    吐血整理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.png
    image.png

    相关文章

      网友评论

        本文标题:命名实体识别之CRF++(吐血整理)

        本文链接:https://www.haomeiwen.com/subject/zupdjftx.html