• crf++分词


    1.linux下安装crf工具包

    先下载CRF++-0.58.tar.xz,在Linux环境下安装CRF工具包

    https://github.com/taku910/crfpp

    • 解压到某一个目录下面
    • 打开控制台,切换到解压目录
    • 依次输入命令:
    ./configure
    
    sudo make
    
    sudo make install
    

    其间,出现问题:

    发现是make和make install没用sudo命令,权限不够,导致不能创建一些目录。

    2.使用

    https://blog.csdn.net/wqx1414161394/article/details/79411988

    1.训练和测试的数据格式

    训练和测试文件必须包含多个tokens,每个token又包含多个列。token的定义可根据具体的任务,如词、词性等。每个token必须写在一行,且各列之间用空格或制表格间隔。一个token的序列可构成一个sentence,每个sentence之间用一个空行间隔。

    注意: 最后一列将是被CRF用来训练的最终标签!!!

    例子:He reckons the current account deficit will narrow to only #1.8 billion in September.

    img

    这个例子中”He reckons the current account deficit will narrow to only #1.8 billion in September .”代表一个训练语句,CRF++要求将这样的句子拆成每一个词一行并且是相同固定列数的数据,其中列除了原始输入,还可以包含一些其他信息,比如例子每个token包含3列,分别为字本身、字类型和词位标记,最后一列是Label信息,也就是标准答案yy。而不同的训练序列与序列之间的相隔,依靠一个空白行来区分。

    通俗说法:训练文件由若干个句子组成(可以理解为若干个训练样例),不同句子之间通过换行符分隔,上图中显示出的有两个句子。每个句子可以有若干组标签,最后一组标签是标注,上图中有三列,即第一列和第二列都是已知的数据,第三列是要预测的标注,以上面例子为例是,根据第一列的词语和和第二列的词性,预测第三列的标注。 当然这里有涉及到标注的问题,比如命名实体识别就有很多不同的标注集。

    https://blog.csdn.net/u010189459/article/details/38546115#

    日文trainset的例子如下

    毎 k   B
    日 k   I
    新 k   I
    聞 k   I
    社 k   I
    特 k   B
    別 k   I
    顧 k   B
    問 k   I                                                 
    4 n   B
    

    这里第一列是待分词的日文字,第二列暂且认为其是词性标记,第三列是字标注中的2-tag(B, I)标记,这个很重要,对于我们需要准备的训练集,主要是把这一列的标记做好,不过需要注意的是,其断句是靠空行来完成的。

    注意:每一行的列数必须相同一致,否则系统将报错。

    再来看测试集的格式:

    よ h   I
    っ h   I
    て h   I
    私 k   B
    た h   B
    ち h   I
    の h   B                                                     
    世 k   B
    代 k   I
    が h   B
    

    同样也有3列,第一列是日文字,第二列第三列与上面是相似的,不过在测试集里第三列主要是占位作用。事实上,CRF++对于训练集和测试集文件格式的要求是比较灵活的,首先需要多列,但不能不一致,既在一个文件里有的行是两列,有的行是三列;其次第一列代表的是需要标注的“字或词”,最后一列是输出位”标记tag”,如果有额外的特征,例如词性什么的,可以加到中间列里,所以训练集或者测试集的文件最少要有两列。

    2.准备特征模板

    CRF++训练的时候,要求我们自己提供特征模板。

    image

    # Unigram
    U00:%x[-2,0]
    U01:%x[-1,0]
    U02:%x[0,0]
    U03:%x[1,0]
    U04:%x[2,0]
    U05:%x[-2,0]/%x[-1,0]/%x[0,0]
    U06:%x[-1,0]/%x[0,0]/%x[1,0]
    U07:%x[0,0]/%x[1,0]/%x[2,0]
    U08:%x[-1,0]/%x[0,0]                                          
    U09:%x[0,0]/%x[1,0]
     
    # Bigram
    B
    

    模板文件中的每一行是一个模板。每个模板都是由%x[row,col]来指定输入数据中的一个token。row指定到当前token的行偏移,col指定列位置。
    image

    image

    以“U01:%x[0,1]”为例,它在该语料中生成的示例函数如下:

    func1 = if (output = O and feature=“U01:NN”) return 1 else return 0
    func2 = if (output = O and feature=“U01:N”) return 1 else return 0
    func3 = if (output = O and feature=“U01:NNP”) return 1 else return 0
    …
    

    关于CRF++中特征模板的说明和举例,请大家参考官方文档上的“Preparing feature templates”这一节.

    而以下部分的说明拿上述日文分词数据举例。在特征模板文件中,每一行(如U00:%x[-2,0])代表一个特征,而宏“%x[行位置,列位置]”则代表了相对于当前指向的token的行偏移和列的绝对位置,以上述训练集为例,如果当前扫描到“新 k I”这一行,

    毎 k   B
    日 k   I
    新 k   I   <== 扫描到这一行,代表当前位置
    聞 k   I
    社 k   I
    特 k   B
    別 k   I
    顧 k   B
    問 k   I
    4 n   B
    

    那么依据特征模板文件抽取的特征如下:

    # Unigram
    U00:%x[-2,0] ==> 毎
    U01:%x[-1,0] ==> 日
    U02:%x[0,0]  ==> 新
    U03:%x[1,0]  ==> 聞
    U04:%x[2,0]  ==> 社
    U05:%x[-2,0]/%x[-1,0]/%x[0,0] ==> 每/日/新
    U06:%x[-1,0]/%x[0,0]/%x[1,0]  ==> 日/新/聞
    U07:%x[0,0]/%x[1,0]/%x[2,0]   ==> 新/聞/社
    U08:%x[-1,0]/%x[0,0]          ==> 日/新
    U09:%x[0,0]/%x[1,0]           ==> 新/聞
     
    # Bigram
    B
    

    2.2模板类型

    CRF++里将特征分成两种类型,一种是Unigram的,“U”起头,另外一种是Bigram的,“B”起头。对于Unigram的特征,假如一个特征模板是”U01:%x[-1,0]“, CRF++会自动的生成一组特征函数(func1 … funcN) 集合:

    func1 = if (output = B and feature="U01:日") return 1 else return 0
    func2 = if (output = I and feature="U01:日") return 1 else return 0
    ....
    funcXX = if (output = B and feature="U01:問") return 1  else return 0
    funcXY = if (output = I and feature="U01:問") return 1  else return 0
    

    生成的特征函数的数目 = (L * N),其中L是输出的类型的个数,这里是B,I这两个tag,N是通过模板扩展出来的所有单个字符串(特征)的个数,这里指的是在扫描所有训练集的过程中找到的日文字(特征)。

    而Bigram特征主要是当前的token和前面一个位置token的自动组合生成的bigram特征集合。最后需要注意的是U01和U02这些标志位,与特征token组合到一起主要是区分“U01:問”和“U02:問”这类特征,虽然抽取的日文”字”特征是一样的,但是在CRF++中这是有区别的特征。

    Unigram feature 和 Bigram feature有什么区别呢?
    unigram/bigram很容易混淆,因为通过unigram-features也可以写出类似%x[-1,0]%x[0,0]这样的单词级别的bigram(二元特征)。而这里的unigram和bigram features指定是uni/bigrams的输出标签。
    这里的一元/二元指的就是输出标签的情况,这个具体的例子我还没看到,example文件夹中四个例子,也都是只用了Unigram,没有用Bigarm,因此感觉一般Unigram feature就够了。
    https://blog.csdn.net/miner_zhu/article/details/83143487

    3.训练

    命令行:
    % crf_learn template_file train_file model_file
    其中,template_file和train_file需由使用者事先准备好。crf_learn将生成训练后的模型并存放在model_file中。

    一般的,crf_learn将在STDOUT上输出下面的信息。

    img

    • iter: 迭代次数

    • terr: tags的错误率(错误的tag数/所有的tag数)

    • serr:sentence的错误率(错误的sentence数/所有的sentence数)

    • obj:当前对象的值。当这个值收敛到一个确定的值时,CRF模型将停止迭代

    • diff:与上一个对象值之间的相对差这个训练过程的时间、迭代次数等信息会输出到控制台上(感觉上是crf_learn程序的输出信息到标准输出流上了),如果想保存这些信息,我们可以将这些标准输出流到文件上,命令格式如下:

      % crf_learn template_file train_file model_file >> train_info_file
      

    有四个主要的参数可以调整:
    -a CRF-L2 or CRF-L1
    规范化算法选择。默认是CRF-L2。一般来说L2算法效果要比L1算法稍微好一点,虽然L1算法中非零特征的数值要比L2中大幅度的小。
    -c float
    这个参数设置CRF的hyper-parameter。c的数值越大,CRF拟合训练数据的程度越高。这个参数可以调整过度拟合和不拟合之间的平衡度。这个参数可以通过交叉验证等方法寻找较优的参数。
    -f NUM
    这个参数设置特征的cut-off threshold。CRF++使用训练数据中至少NUM次出现的特征。默认值为1。当使用CRF++到大规模数据时,只出现一次的特征可能会有几百万,这个选项就会在这样的情况下起到作用。
    -p NUM
    如果电脑有多个CPU,那么那么可以通过多线程提升训练速度。NUM是线程数量。

    带两个参数的命令行例子:
    % crf_learn -f  3 -c 1.5 template_file train_file model_file
    

    4.测试(解码)

     命令行:
     % crf_test -m model_file test_files
    

    在测试过程中,使用者不需要指定template file,因为,mode file已经有了template的信息。test_file是你想要标注序列标记的测试语料。

    有两个参数-v和-n都是显示一些信息的,-v可以显示预测标签的概率值,-n可以显示不同可能序列的概率值,对于准确率,召回率,运行效率,没有影响,这里不说明了。

    与crf_learn类似,输出的结果放到了标准输出流上,而这个输出结果是最重要的预测结果信息(测试文件的内容+预测标注),同样可以使用重定向,将结果保存下来,命令行如下。

    % crf_test -m model_file test_files >> result_file
    

    实验

    把数据集转换为需要的格式。本次是预测词性,所以把词性放在最后一列:
    image

    测试集:

    image

    模版template:

    # Unigram  
    U00:%x[-2,0]  
    U01:%x[-1,0]  
    U02:%x[0,0]  
    U03:%x[1,0]  
    U04:%x[2,0]  
    U05:%x[-2,0]/%x[-1,0]/%x[0,0]  
    U06:%x[-1,0]/%x[0,0]/%x[1,0]  
    U07:%x[0,0]/%x[1,0]/%x[2,0]  
    U08:%x[-1,0]/%x[0,0]                                            
    U09:%x[0,0]/%x[1,0]  
      
    # Bigram  
    B
    

    上面这个是进行分词可以用的模板

    下面的是词性标注用的模板:

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

    训练:

    重定向 >>追加 ,>覆盖

    #crf_learn template_wsg 1998_1.txt model.wsg > train_info_file&
    
    crf_learn template trainset.txt model_pos > train_info 2>&1 &
    

    测试:

    head -n 90000 1998_1.txt >test.wsg.data2
    crf_test -m model.wsg test.wsg.data2 > test.wsg.rst
    cut -f 1,3-4 test.wsg.rst>1.rst
    python clc_f.py 1.rst
    #
    crf_test -m model test.data > test.rst
    

    image

  • 相关阅读:
    作业7-英文词频统计预备,组合数据类型练习
    作业6-凯撒编码、GDP格式化输出、九九乘法表
    作业5-字符串操作
    作业3-turtle库基础练习
    作业2-Python基础练习
    理解管理信息系统
    Git-git rebase详解
    C语言中基本的数据类型
    读取配置文件的C语言接口实现
    Linux之异步IO机制分析
  • 原文地址:https://www.cnblogs.com/yh-blog/p/14537493.html
Copyright © 2020-2023  润新知