CRF++ 中文分词


安装CRF和安装maxent差不多,都是./configure,make,sudo su,make install。CRF提供了各种语言的工具包,有java、python、perl等。我用的是python语言工具包,

所以还要安装python工具包:进入CRF++-0.58/python,python setup.py build ,(sudo) python setup.py install。安装完成后,可以打开python shell ,然后输入 import CRFPP,看看是否可以成功import,如果可以,就说明安装成功了。

CRF的example里有一个seg目录,里面是一个关于日文分词的例子。日文和中文很相似,所以用这个例子来训练model最合适了。

这里的训练集文件使用1998年1月份的《人民日报》语料 ,下载地址http://download.csdn.net/detail/u013378306/9740867

由于生成训练数据集后,有22M,测试的话,建议只用一部分。

中文语料部分:

19980101-01-001-001/m  迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  ——/w  一九九八年/t  新年/t  讲话/n  (/w  附/v  图片/n  1/m  张/q  )/w  
19980101-01-001-002/m  中共中央/nt  总书记/n  、/w  国家/n  主席/n  江/nr  泽民/nr  
19980101-01-001-003/m  (/w  一九九七年/t  十二月/t  三十一日/t  )/w  
19980101-01-001-004/m  12月/t  31日/t  ,/w  中共中央/nt  总书记/n  、/w  国家/n  主席/n  江/nr  泽民/nr  发表/v  1998年/t  新年/t  讲话/n  《/w  迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  》/w  。/w  (/w  新华社/nt  记者/n  兰/nr  红光/nr  摄/Vg  )/w  


为了得到适合拿来训练的数据集(4-tag标记),用到一个python脚本--make_crf_train_data.py:

  • 词首,常用B表示
  • 词中,常用M表示
  • 词尾,常用E表示
  • 单子词,常用S表示

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# make_crf_train_data.py
# 得到CRF++要求的格式的训练文件
# 用法:命令行--python make_crf_train_data.py input_file output_file
# 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs
import sys


def character_tagging(input_file, output_file):
	input_data = codecs.open(input_file, 'r', 'gbk')
	output_data = codecs.open(output_file, 'w', 'utf-8')
	for line in input_data.readlines():
		word_list = line.strip().split("  ")
		for word in word_list:
			words=word.split("/");

			if len(words)>=2:
				xz = words[1]
				word=words[0]
				if len(word) == 1:
					output_data.write(word + "\t"+xz+"\tS\n")
				else:
					output_data.write(word[0] + "\t"+xz+"\tB\n")
					for w in word[1:len(word) - 1]:
						output_data.write(w + "\t"+xz+"\tM\n")
					output_data.write(word[len(word) - 1] + "\t"+xz+"\tE\n")
		output_data.write("\n")
	input_data.close()
	output_data.close()


'''if __name__ == '__main__':
	if len(sys.argv) != 3:
		print "pls use: python make_crf_train_data.py input output"
		sys.exit()
	input_file = sys.argv[1]
	output_file = sys.argv[2]
	character_tagging(input_file, output_file)'''

character_tagging("199801.txt", "train.data")

执行

python make_crf_train_data.py  inputFilePath  tag4OutputFilePath


inputFilePath 人民日报文件   ,tag4OutputFilePath 转换后的4tag文件

tag4OutputFilePath 部分:

1	m	E
迈	v	B
向	v	E
充	v	B
满	v	E
希	n	B
望	n	E
的	u	S
新	a	S
世	n	B
纪	n	E
—	w	B
—	w	E
一	t	B
九	t	M
九	t	M
八	t	M
年	t	E
新	t	B
年	t	E
讲	n	B
话	n	E
(	w	S
附	v	S
图	n	B
片	n	E
1	m	S
张	q	S
)	w	S



有了训练语料,接下来就可以利用crf的训练工具crf_learn来训练模型了,切换到CRF++0.58目录下,执行如下命令即可:

crf_learn -f 3 -c 1.5 ./example/seg/template ../tag4OutputFilePath  crf_model

得到crf_model即为训练好的模型文件。

编写py文件分词 :crf_segmenter.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#crf_segmenter.py
#用法:命令行输入--python crf_segmenter.py crf_model input_file output_file
# 利用CRF自带的python工具包,对输入文本进行分词
 
import codecs
import sys
 
import CRFPP
 
def crf_segmenter(input_file, output_file, tagger):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        tagger.clear()
        for word in line.strip():
            word = word.strip()
            if word:
                tagger.add((word + "\to\tB").encode('utf-8'))
        tagger.parse()
        size = tagger.size()
        xsize = tagger.xsize()
        for i in range(0, size):
            for j in range(0, xsize):
                char = tagger.x(i, j).decode('utf-8')
                tag = tagger.y2(i)
                if tag == 'B':
                    output_data.write(' ' + char)
                elif tag == 'M':
                    output_data.write(char)
                elif tag == 'E':
                    output_data.write(char + ' ')
                else: #tag == 'S'
                    output_data.write(' ' + char + ' ')
        output_data.write('\n')
    input_data.close()
    output_data.close()
 
if __name__ == '__main__':
    if len(sys.argv) != 4:
        print "pls use: python crf_segmenter.py model input output"
        sys.exit()
    crf_model = sys.argv[1]
    input_file = sys.argv[2]
    output_file = sys.argv[3]
    tagger = CRFPP.Tagger("-m " + crf_model)
    crf_segmenter(input_file, output_file, tagger)#
input_file是需要分词的文件,output_file是分词后的输出文件

最后执行:

python crf_segmenter.py crf_model input_file output_file




input_file 文件:
中华人民工和国,中国国家主席江泽民,讲述了三个代表重要思想,我们要解放思想,实事求是,抓住机遇,实现祖国的和平统一,繁荣富强。


output_file:
  
中华  人民  工  和国  ,  中国  国家  主席  江  泽民  ,讲  述了  三个  代表  重要  思想  ,我  们要  解放  思想  ,  实事  求是  ,抓  住机  遇,  实现  祖国  的  和  平统  一,  繁荣  富强  。



从上面的结果可以看出,效果也不比之前的maxent理想,但这里主要是我的电脑在作孽,由于原来的训练数据太大了,大概有400多万行数据,我在电脑上跑了三次,结果三次都导致了系统崩溃,最后一次我从晚上十点开始跑数据,一直到第二天凌晨一点还没好,后来我就去睡觉了,电脑开着让它继续运行,结果第二天醒来,程序又崩溃了,所以后来我就截取了训练数据里的大概五万行数据用来训练model,结果就导致了正确率不高的问题,其实如果电脑给力的话,分词准确率大概有96%。这也是CRF的一个特点,它需要大量的数据来进行训练才能得到理想的效果。
最终分词效率:

=== SUMMARY:
=== TOTAL INSERTIONS: 99
=== TOTAL DELETIONS: 30
=== TOTAL SUBSTITUTIONS: 156
=== TOTAL NCHANGE: 285
=== TOTAL TRUE WORD COUNT: 821
=== TOTAL TEST WORD COUNT: 890
=== TOTAL TRUE WORDS RECALL: 0.773
=== TOTAL TEST WORDS PRECISION: 0.713
=== F MEASURE: 0.742
=== OOV Rate: 0.141
=== OOV Recall Rate: 0.259
=== IV Recall Rate: 0.858
### blog_test_segment.utf8 99 30 156 285 821 890 0.773 0.713 0.742 0.141 0.259 0.858










   

你可能感兴趣的:(CRF++ 中文分词)