前段时间写了中文分词的一些记录里面提到了CRF的分词方法,近段时间又研究了一下,特把方法写下来,以备忘,另外,李沫南同学优化过CRF++,见:http://www.coreseek.cn/opensource/CRF/。我觉得CRF++还有更大的优化空间,以后有时间再搞。
1 下载和安装
CRF的概念,请google,我就不浪费资源啦。官方地址如下:http://crfpp.sourceforge.net/
我用的是Ubutnu,所以,下载的是源码:http://sourceforge.net/projects/crfpp/files/ 下载CRF++-0.54.tar.gz
没有gcc/g++/make请安装
% ./configure
% make[如果path.h报错 加上#inlcude<iostream>头文件]
% sudo make install
2 测试和体验
在源码包中有example,可以执行./exec.sh体验一下
exec.sh #训练和测试脚本
template #模板文件
test.data #测试文件
train.data #训练文件
可以打开看看
3 语料整理和模板编写
我采用的是6Tag和6Template的方式
S,单个词;B,词首;E,词尾;M1/M2/M,词中
1个字的词:
和 S
2个字的词(注意是实际上是一个字一行,我为了排版,改为横排的了):
中 B 国 E
3个字的词:
进 B 一 M 步 E
5个字的词:
发 B 展 M1 中 M2 国 M 家 E
跟多字的词
中 B 华 M1 人 M2 民 M 共 M 和 M国 E
标点符号作为单词(S表示)
从bamboo项目中下载:people-daily.txt.gz
pepoledata.py文件
- #!/usr/bin/python
- #-*-coding:utf-8-*-
- importsys
- #home_dir="D:/source/NLP/people_daily//"
- home_dir="/home/lhb/workspace/CRF_data/"
- defsplitWord(words):
- uni=words.decode('utf-8')
- li=list()
- foruinuni:
- li.append(u.encode('utf-8'))
- returnli
- #4tag
- #S/B/E/M
- defget4Tag(li):
- length=len(li)
- #printlength
- iflength==1:
- return['S']
- eliflength==2:
- return['B','E']
- eliflength>2:
- li=list()
- li.append('B')
- foriinrange(0,length-2):
- li.append('M')
- li.append('E')
- returnli
- #6tag
- #S/B/E/M/M1/M2
- defget6Tag(li):
- length=len(li)
- #printlength
- iflength==1:
- return['S']
- eliflength==2:
- return['B','E']
- eliflength==3:
- return['B','M','E']
- eliflength==4:
- return['B','M1','M','E']
- eliflength==5:
- return['B','M1','M2','M','E']
- eliflength>5:
- li=list()
- li.append('B')
- li.append('M1')
- li.append('M2')
- foriinrange(0,length-4):
- li.append('M')
- li.append('E')
- returnli
- defsaveDataFile(trainobj,testobj,isTest,word,handle,tag):
- ifisTest:
- saveTrainFile(testobj,word,handle,tag)
- else:
- saveTrainFile(trainobj,word,handle,tag)
- defsaveTrainFile(fiobj,word,handle,tag):
- iflen(word)>0:
- wordli=splitWord(word)
- iftag=='4':
- tagli=get4Tag(wordli)
- iftag=='6':
- tagli=get6Tag(wordli)
- foriinrange(0,len(wordli)):
- w=wordli[i]
- h=handle
- t=tagli[i]
- fiobj.write(w+'/t'+h+'/t'+t+'/n')
- else:
- #print'Newline'
- fiobj.write('/n')
- #B,M,M1,M2,M3,E,S
- defconvertTag(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
- forainarr:
- i+=1
- a=a.strip('/r/n/t')
- words=a.split('')
- test=False
- ifi%10==0:
- test=True
- forwordinwords:
- word=word.strip('/t')
- iflen(word)>0:
- i1=word.find('[')
- ifi1>=0:
- word=word[i1+1:]
- i2=word.find(']')
- ifi2>0:
- word=word[:i2]
- word_hand=word.split('/')
- w,h=word_hand
- #printw,h
- ifh=='nr':#renmin
- #print'NR',w
- ifw.find('·')>=0:
- tmpArr=w.split('·')
- fortmpintmpArr:
- saveDataFile(trainobj,testobj,test,tmp,h,tag)
- continue
- ifh!='m':
- saveDataFile(trainobj,testobj,test,w,h,tag)
- ifh=='w':
- saveDataFile(trainobj,testobj,test,"","",tag)#split
- trainobj.flush()
- testobj.flush()
- if__name__=='__main__':
- iflen(sys.argv)<2:
- print'tag[6,4]convertrawdatatotrain.dataandtag.test.data'
- else:
- tag=sys.argv[1]
- convertTag(tag)
下载下来并解压,然后用脚本整理数据,注意home_dir改为语料的目录:
python ./peopledata.py 6
90%数据作为训练数据,10%的数据作为测试数据,生成的文件如:
6.test.data
6.train.data
模板文件的写法如下
template:
- #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]
- #Bigram
- B
%x[row,column]代表的是行和列,[-1,0]表示前1个字的第1列,[0,0]当前字的第1列,[1,0]后1个字的第1列
4 执行和结果查看
6exec.sh文件
- #!/bin/sh
- ./crf_learn-f3-c4.0template6.train.data6.model>6.train.rst
- ./crf_test-m6.model6.test.data>6.test.rst
- ./crfeval.py6.test.rst
- #./crf_learn-aMIRA-f3templatetrain.datamodel
- #./crf_test-mmodeltest.data
- #rm-fmodel
WordCount from test result: 109805
WordCount from golden data: 109948
WordCount of correct segs : 106145
P = 0.966668, R = 0.965411, F-score = 0.966039
5 调整Tag和模板
4 Tag S/B/M/E 比 6Tag 去掉了M1和M2
python ./peopledata.py 4
4exec.sh文件为
- #!/bin/sh
- ./crf_learn-f3-c4.0template4.train.data4.model>4.train.rst
- ./crf_test-m4.model4.test.data>4.test.rst
- ./crfeval.py4.test.rst
4Tag的效果为
lhb@localhost:~/workspace/CRF_data$./crfeval.py 4.test.rst
ordCount from test result: 109844
WordCount from golden data: 109948
WordCount of correct segs : 105985
P = 0.964868, R = 0.963956, F-score = 0.964412
6Tag的效果比4Tag有细微的差距,当然是6Tag好。
6Tag 训练时间为
10062.00s
4tag的训练时间为
4208.71s
6Tag的标注方法差异
1)把M放在E之前:
发 B 展 M1 中 M2 国 M 家 E
2)把M放在B后
发 B 展 M 中 M1 国 M2 家 E
3)把M放在M1和M2之间:
发 B 展 M1 中 M 国 M2 家 E
第1种方式效果最好,有细微的差距。
template的编写
我尝试过12行模板的编写,把词性作为一个计算因素,但是速度实在是很慢,没跑完,我就关机了。效果应该比6 template要好,可以尝试以下。
- #Unigram
- U00:%x[-1,1]
- U01:%x[0,1]
- U02:%x[1,1]
- U03:%x[-1,1]/%x[0,1]
- U04:%x[0,1]/%x[1,1]
- U05:%x[-1,1]/%x[1,1]
- U06:%x[-1,0]
- U07:%x[0,0]
- U08:%x[1,0]
- U09:%x[-1,0]/%x[0,0]
- U010:%x[0,0]/%x[1,0]
- U011:%x[-1,0]/%x[1,0]
- #Bigram
- B
有某位同学问我要crfeval.py文件,特放出如下:
- #!/usr/bin/python
- #-*-coding:utf-8-*-
- importsys
- if__name__=="__main__":
- try:
- file=open(sys.argv[1],"r")
- except:
- print"resultfileisnotspecified,oropenfailed!"
- sys.exit()
- wc_of_test=0
- wc_of_gold=0
- wc_of_correct=0
- flag=True
- forlinfile:
- ifl=='/n':continue
- _,_,g,r=l.strip().split()
- ifr!=g:
- flag=False
- ifrin('E','S'):
- wc_of_test+=1
- ifflag:
- wc_of_correct+=1
- flag=True
- ifgin('E','S'):
- wc_of_gold+=1
- print"WordCountfromtestresult:",wc_of_test
- print"WordCountfromgoldendata:",wc_of_gold
- print"WordCountofcorrectsegs:",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))
相关推荐
CRF++使用教程(全)
CRF++使用pdf
基于CRF++的中文分词,包含了数据、CRF++工具、java源码,可以一键执行
CRF++ 目前最新版,包括CRF++ 0.58.tar.gz源文件for linux和.zip for windows 另外,包括一个介绍使用的下载网页文件。
crf++工具包crf++工具包crf++工具包crf++工具包crf++工具包crf++工具包crf++工具包crf++工具包
基于CRF++的中文分词 数据+CRF++工具+java源码.zip
CRF++系列学习包,内含CRF学习文档, CRF++ 0.58win包、mac和linux包CRF++系列学习包,内含CRF学习文档, CRF++ 0.58win包、mac和linux包
CRF++ 是开源的条件随机场的C++实现,可用于中英文句子分词,分段 . CRF++ 是专门为实现许多的自然语言处理任务的开源工具, 如命名实例识别,信息提取,句子分段等。
CRF++分词工具windows最新版本0.58,国内难以找到对应的下载连接,现真诚分享,需要其他版本的可留言
使用 CRF++ 训练命名实体识别模型
windows版CRF++-0.58.zip;linux版CRF++-0.54.zip.rar
CRF在NLP技术领域中主要用于文本标注,并有多种应用场景,例如: 分词(标注字的词位信息,由字构词) 词性标注(标注分词的词性,例如:名词,动词,助词) 命名实体识别(识别人名,地名,机构名,商品名等具有...
CRF++-0.58的Linux安装包,直接解压后就可以安装使用,用于人工智能的条件场训练
在Windows下使用CRFPP,需要Linux版的CRF++,编译是在Linux版的CRF++中完成。
crf++使用工具的详细介绍 模版的制定 crf咋各种模型中的使用案例demo
CRF++工具包使用教程,详细介绍crf如何使用以及相关介绍
crf_learn需要的训练数据是有标注的,如果是分词,就对一个词中的每一个字进行标注,标注值为每个字在词中的位置,4tag标注的话,标注集合为Y={S,B,M,E},S表示单字为词,B表示词的首字,M表示词的中间字,E表示词的...
CRF++工具包使用介绍,详细介绍了条件随机场的使用方法。
CRF++-0.57工具包
做分词用到的一个工具包CRF++,亲测可以使用.安装过程有什么问题的可以看下我的博客: http://blog.csdn.net/gdufstfknight/article/details/79030743