###一、CRF++工具包的下载与安装
CRF 的工具有两种,一种是支持Linux环境的,一种是支持Windows环境的,大家可以自行根据自己的系统进行下载。
CRF++0.58资源链接:https://pan.baidu.com/s/1GKjKYSsgw46pLqjyMwf23A 密码:oj1q

在windows下安装很简单,解压到某目录下即可。
在此附CRF理论及工具包的使用讲解:https://wenku.baidu.com/view/5f805e0d8762caaedd33d491.html

windows下解压得到如下:
这里写图片描述

  • doc文件夹:就是官方主页的内容
  • example文件夹:有四个任务的训练数据(test.data)、测试数据(train.data)和模板文件(template),还有一个执行脚本文件exec.sh
  • sdk文件夹:CRF++的头文件和静态链接库。
  • clr_learn.exe:CRF++的训练程序
  • crl_test.exe:CRF++的测试程序
  • libcrffpp.dll:训练程序和测试程序需要使用的静态链接库。
  • 实际上,需要使用的就是crf_learn.exe,crf_test.exe和libcrfpp.dll,这三个文件。

###2 测试和体验
在源码包中有example,可以执行./exec.sh体验一下(Linux下的操作)
exec.sh #训练和测试脚本
template #模板文件
test.data #测试文件
train.data #训练文件

###3.生成训练数据【中文】
下载人民日报语料,对于语料有嵌套的标注,例如:[中央/n 电视台/n]nt,为了处理方便,只考虑最细粒度的分词结果,即当作是 中央/n 电视台/n 两个词进行处理。

通过下面python脚本,根据人民日报的语料库生成crf的测试和训练数据。原始数据中随机10%是测试数据,90%是训练数据。

两种格式:
6tag:S,单个词;B,词首;E,词尾;M1/M2/M,词中
4tag:S,单个词;B,词首;E,词尾;M,词中

运行Python脚本示例:

C:\Users\Administrator>python F:\pycodes\NLP\trainDataGenerate.py 4

其中参数4是传给了sys.argv[1] ,原因见:Python中 sys.argv[]的用法简明解释,因此执行main方法中的else部分。

# -*- coding: utf8  -*-
 
import sys
 
home_dir = "F:/pycodes/NLP/people_daily//"
def splitWord(words):
    uni = words.decode('utf-8')
    li = list()    
    for u in uni:
        li.append(u.encode('utf-8'))
    return li    
 
#4 tag
#S/B/E/M
def get4Tag(li):
    length = len(li)
    #print length
    if length   == 1:
        return ['S']
    elif length == 2:
        return ['B','E']
    elif length > 2:
        li = list()
        li.append('B')
    for i in range(0,length-2):
        li.append('M')
    li.append('E')
    return li

#6 tag
#S/B/E/M/M1/M2
def get6Tag(li):
    length = len(li)
    #print length
    if length   == 1:
        return ['S']
    elif length == 2:
        return ['B','E']
    elif length == 3:
        return ['B','M','E']
    elif length == 4:
        return ['B','M1','M','E']
    elif length == 5:
        return ['B','M1','M2','M','E']
    elif length > 5:
        li = list()
        li.append('B')
        li.append('M1')
        li.append('M2')
    for i in range(0,length-4):
        li.append('M')
    li.append('E')
    return li
 
def saveDataFile(trainobj,testobj,isTest,word,handle,tag):
    if isTest:
        saveTrainFile(testobj,word,handle,tag)
    else:
        saveTrainFile(trainobj,word,handle,tag)
 
def saveTrainFile(fiobj,word,handle,tag): 
    if len(word) > 0:
        wordli = splitWord(word)
        if tag == '4':
            tagli = get4Tag(wordli)
        if tag == '6':
            tagli = get6Tag(wordli)
        for i in range(0,len(wordli)):
            w = wordli[i]
            h = handle
            t = tagli[i]
            fiobj.write(w + '\t' + h + '\t' + t + '\n')
    else:
    #print 'New line'
        fiobj.write('\n')
 
#B,M,M1,M2,M3,E,S
def convertTag(tag):    
    fiobj    = open( home_dir + 'people-daily.txt','r')
    trainobj = open( home_dir + tag + '.train.data','w' )
    testobj  = open( home_dir + tag + '.test.data','w')
 
    arr = fiobj.readlines()
    i = 0
    for a in arr:
        i += 1
        a = a.strip('\r\n\t ')
        if a=="":continue
        words = a.split(" ")
        test = False
        if i % 10 == 0:
            test = True
        for word in words:
            # print "---->", word
            word = word.strip('\t ')
            if len(word) > 0:        
                i1 = word.find('[')
            if i1 >= 0:
                word = word[i1+1:]
            i2 = word.find(']')
            if i2 > 0:
                w = word[:i2]
            word_hand = word.split('/')
            # print "----",word
            w,h = word_hand
            #print w,h
            if h == 'nr':    #ren min
                #print 'NR',w
                if w.find('·') >= 0:
                    tmpArr = w.split('·')
                    for tmp in tmpArr:
                        saveDataFile(trainobj,testobj,test,tmp,h,tag)
                continue
            if h != 'm':
                saveDataFile(trainobj,testobj,test,w,h,tag)
            
            if h == 'w':
                saveDataFile(trainobj,testobj,test,"","",tag) #split
 
    trainobj.flush()
    testobj.flush()
 

# sys.argv[0]表示代码本身文件路径
# Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的

if __name__ == '__main__':    
    if len(sys.argv) < 2:
        print 'tag[6,4] convert raw data to train.data and tag.test.data'
    else:
        tag = sys.argv[1]
        convertTag(tag)
    # print len(sys.argv)

####4、模板
template格式
a) 特征选取的行是相对的,列是绝对的,一般选取相对行前后m行,选取n-1列(假设语料总共有n列),特征表示方法为:%x[行,列],行列的初始位置都为0。

# Unigram  
U00:%x[-1,0]  
U01:%x[0,0]  
U02:%x[1,0]  
U03:%x[-1,0]/%x[0,0]  
U04:%x[0,0]/%x[1,0]  
U05:%x[-1,0]/%x[1,0] 

###5、训练和测试

#!/bin/sh  
crf_learn -f 3 -c 4.0 template 4_train.data 4_model > 4_train.rst  
crf_test -m 4_model 4_test.data > 4_test.rst

crf_learn <模板> <训练语料> <模板文件> > <训练输出文件>
其中模板和训练语料是需要事先准备好的,模板文件(4_model)在训练完成后生成。
通过追加-t可以得到CRF模型文件。
crf_learn -f 3 -c 4.0 template 4_train.data 4_model -t > 4_train.txt 可以得到4_model.txt这个CRF模型文件。
crf_test <模板文件> <测试语料> > <测试输出文件>
测试用到训练过程的模板文件。

可选参数说明:

-f, –freq=INT 使用属性的出现次数不少于INT(默认为1)
-m, –maxiter=INT 设置INT为LBFGS的最大迭代次数 (默认10k)
-c, –cost=FLOAT 设置FLOAT为代价参数,过大会过度拟合 (默认1.0)
-e, –eta=FLOAT 设置终止标准FLOAT(默认0.0001)
-C, –convert 将文本模式转为二进制模式
-t, –textmodel 为调试建立文本模型文件
-a, –algorithm=(CRF|MIRA)  选择训练算法,默认为CRF-L2
-p, –thread=INT线程数(默认1),利用多个CPU减少训练时间
-H, –shrinking-size=INT 设置INT为最适宜的迭代变量次数 (默认20)
-v, –version 显示版本号并退出
-h, –help 显示帮助并退出

###6、计算F值

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import sys
 
if __name__=="__main__":
    try:
        file = open(sys.argv[1], "r")
    except:
        print "result file is not specified, or open failed!"
        sys.exit()
    
    wc_of_test = 0
    wc_of_gold = 0
    wc_of_correct = 0
    flag = True
    
    for l in file:
        if l=='\n': continue
    
        _, _, g, r = l.strip().split()
     
        if r != g:
            flag = False
    
        if r in ('E', 'S'):
            wc_of_test += 1
            if flag:
                wc_of_correct +=1
            flag = True
    
        if g in ('E', 'S'):
            wc_of_gold += 1
 
    print "WordCount from test result:", wc_of_test
    print "WordCount from golden data:", wc_of_gold
    print "WordCount of correct segs :", wc_of_correct
            
    #查全率
    P = wc_of_correct/float(wc_of_test)
    #查准率,召回率
    R = wc_of_correct/float(wc_of_gold)
    
    print "P = %f, R = %f, F-score = %f" % (P, R, (2*P*R)/(P+R))

操作过程如下:
这里写图片描述
追加-t操作过程:
这里写图片描述

参考:
CRF++中文分词使用指南
条件随机场
CRF++模型格式说明
CRF++的使用
CRF++代码分析

GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:4 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐