CRF++ 中文分词

CRF++ 中文分词

原创  2017年01月18日 19:29:44

安装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,测试的话,建议只用一部分。

中文语料部分:

[python]  view plain  copy
  1. 19980101-01-001-001/m  迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  ——/w  一九九八年/t  新年/t  讲话/n  (/w  附/v  图片/n  1/m  张/q  )/w    
  2. 19980101-01-001-002/m  中共中央/nt  总书记/n  、/w  国家/n  主席/n  江/nr  泽民/nr    
  3. 19980101-01-001-003/m  (/w  一九九七年/t  十二月/t  三十一日/t  )/w    
  4. 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表示

[python]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. # make_crf_train_data.py  
  4. # 得到CRF++要求的格式的训练文件  
  5. # 用法:命令行--python make_crf_train_data.py input_file output_file  
  6. # 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)  
  7.   
  8. import codecs  
  9. import sys  
  10.   
  11.   
  12. def character_tagging(input_file, output_file):  
  13.     input_data = codecs.open(input_file, 'r''gbk')  
  14.     output_data = codecs.open(output_file, 'w''utf-8')  
  15.     for line in input_data.readlines():  
  16.         word_list = line.strip().split("  ")  
  17.         for word in word_list:  
  18.             words=word.split("/");  
  19.   
  20.             if len(words)>=2:  
  21.                 xz = words[1]  
  22.                 word=words[0]  
  23.                 if len(word) == 1:  
  24.                     output_data.write(word + "\t"+xz+"\tS\n")  
  25.                 else:  
  26.                     output_data.write(word[0] + "\t"+xz+"\tB\n")  
  27.                     for w in word[1:len(word) - 1]:  
  28.                         output_data.write(w + "\t"+xz+"\tM\n")  
  29.                     output_data.write(word[len(word) - 1] + "\t"+xz+"\tE\n")  
  30.         output_data.write("\n")  
  31.     input_data.close()  
  32.     output_data.close()  
  33.   
  34.   
  35. '''''if __name__ == '__main__': 
  36.     if len(sys.argv) != 3: 
  37.         print "pls use: python make_crf_train_data.py input output" 
  38.         sys.exit() 
  39.     input_file = sys.argv[1] 
  40.     output_file = sys.argv[2] 
  41.     character_tagging(input_file, output_file)'''  
  42.   
  43. character_tagging("199801.txt""train.data")  

执行

[python]  view plain  copy
  1. python make_crf_train_data.py  inputFilePath  tag4OutputFilePath  


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

tag4OutputFilePath 部分:

[python]  view plain  copy
  1. 1   m   E  
  2. 迈   v   B  
  3. 向   v   E  
  4. 充   v   B  
  5. 满   v   E  
  6. 希   n   B  
  7. 望   n   E  
  8. 的   u   S  
  9. 新   a   S  
  10. 世   n   B  
  11. 纪   n   E  
  12. —   w   B  
  13. —   w   E  
  14. 一   t   B  
  15. 九   t   M  
  16. 九   t   M  
  17. 八   t   M  
  18. 年   t   E  
  19. 新   t   B  
  20. 年   t   E  
  21. 讲   n   B  
  22. 话   n   E  
  23. (   w   S  
  24. 附   v   S  
  25. 图   n   B  
  26. 片   n   E  
  27. 1   m   S  
  28. 张   q   S  
  29. )   w   S  



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

[python]  view plain  copy
  1. crf_learn -f 3 -c 1.5 ./example/seg/template ../tag4OutputFilePath  crf_model  

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

编写py文件分词 :crf_segmenter.py

[html]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. #crf_segmenter.py  
  4. #用法:命令行输入--python crf_segmenter.py crf_model input_file output_file  
  5. # 利用CRF自带的python工具包,对输入文本进行分词  
  6.    
  7. import codecs  
  8. import sys  
  9.    
  10. import CRFPP  
  11.    
  12. def crf_segmenter(input_file, output_file, tagger):  
  13.     input_data = codecs.open(input_file, 'r', 'utf-8')  
  14.     output_data = codecs.open(output_file, 'w', 'utf-8')  
  15.     for line in input_data.readlines():  
  16.         tagger.clear()  
  17.         for word in line.strip():  
  18.             word = word.strip()  
  19.             if word:  
  20.                 tagger.add((word + "\to\tB").encode('utf-8'))  
  21.         tagger.parse()  
  22.         size = tagger.size()  
  23.         xsize = tagger.xsize()  
  24.         for i in range(0, size):  
  25.             for j in range(0, xsize):  
  26.                 char = tagger.x(i, j).decode('utf-8')  
  27.                 tag = tagger.y2(i)  
  28.                 if tag == 'B':  
  29.                     output_data.write(' ' + char)  
  30.                 elif tag == 'M':  
  31.                     output_data.write(char)  
  32.                 elif tag == 'E':  
  33.                     output_data.write(char + ' ')  
  34.                 else: #tag == 'S'  
  35.                     output_data.write(' ' + char + ' ')  
  36.         output_data.write('\n')  
  37.     input_data.close()  
  38.     output_data.close()  
  39.    
  40. if __name__ == '__main__':  
  41.     if len(sys.argv) != 4:  
  42.         print "pls use: python crf_segmenter.py model input output"  
  43.         sys.exit()  
  44.     crf_model = sys.argv[1]  
  45.     input_file = sys.argv[2]  
  46.     output_file = sys.argv[3]  
  47.     tagger = CRFPP.Tagger("-m " + crf_model)  
  48.     crf_segmenter(input_file, output_file, tagger)#  
input_file是需要分词的文件,output_file是分词后的输出文件

最后执行:

[html]  view plain  copy
  1. python crf_segmenter.py crf_model input_file output_file  




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


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



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

[python]  view plain  copy
  1. === SUMMARY:  
  2. === TOTAL INSERTIONS: 99  
  3. === TOTAL DELETIONS: 30  
  4. === TOTAL SUBSTITUTIONS: 156  
  5. === TOTAL NCHANGE: 285  
  6. === TOTAL TRUE WORD COUNT: 821  
  7. === TOTAL TEST WORD COUNT: 890  
  8. === TOTAL TRUE WORDS RECALL: 0.773  
  9. === TOTAL TEST WORDS PRECISION: 0.713  
  10. === F MEASURE: 0.742  
  11. === OOV Rate: 0.141  
  12. === OOV Recall Rate: 0.259  
  13. === IV Recall Rate: 0.858  
  14. ### blog_test_segment.utf8 99 30 156 285 821 890 0.773 0.713 0.742 0.141 0.259 0.858  


[html]  view plain  copy
  1. <pre code_snippet_id="2137761" snippet_file_name="blog_20170118_1_4933737" name="code" class="html"><pre code_snippet_id="2137761" snippet_file_name="blog_20170118_1_4933737"></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6. <pre></pre>  
  7. <pre></pre>  
  8. <pre></pre>  
  9. <link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=2.0">  
  10.             </pre>  

安装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,测试的话,建议只用一部分。

中文语料部分:

[python]  view plain  copy
  1. 19980101-01-001-001/m  迈向/v  充满/v  希望/n  的/u  新/a  世纪/n  ——/w  一九九八年/t  新年/t  讲话/n  (/w  附/v  图片/n  1/m  张/q  )/w    
  2. 19980101-01-001-002/m  中共中央/nt  总书记/n  、/w  国家/n  主席/n  江/nr  泽民/nr    
  3. 19980101-01-001-003/m  (/w  一九九七年/t  十二月/t  三十一日/t  )/w    
  4. 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表示

[python]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. # make_crf_train_data.py  
  4. # 得到CRF++要求的格式的训练文件  
  5. # 用法:命令行--python make_crf_train_data.py input_file output_file  
  6. # 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)  
  7.   
  8. import codecs  
  9. import sys  
  10.   
  11.   
  12. def character_tagging(input_file, output_file):  
  13.     input_data = codecs.open(input_file, 'r''gbk')  
  14.     output_data = codecs.open(output_file, 'w''utf-8')  
  15.     for line in input_data.readlines():  
  16.         word_list = line.strip().split("  ")  
  17.         for word in word_list:  
  18.             words=word.split("/");  
  19.   
  20.             if len(words)>=2:  
  21.                 xz = words[1]  
  22.                 word=words[0]  
  23.                 if len(word) == 1:  
  24.                     output_data.write(word + "\t"+xz+"\tS\n")  
  25.                 else:  
  26.                     output_data.write(word[0] + "\t"+xz+"\tB\n")  
  27.                     for w in word[1:len(word) - 1]:  
  28.                         output_data.write(w + "\t"+xz+"\tM\n")  
  29.                     output_data.write(word[len(word) - 1] + "\t"+xz+"\tE\n")  
  30.         output_data.write("\n")  
  31.     input_data.close()  
  32.     output_data.close()  
  33.   
  34.   
  35. '''''if __name__ == '__main__': 
  36.     if len(sys.argv) != 3: 
  37.         print "pls use: python make_crf_train_data.py input output" 
  38.         sys.exit() 
  39.     input_file = sys.argv[1] 
  40.     output_file = sys.argv[2] 
  41.     character_tagging(input_file, output_file)'''  
  42.   
  43. character_tagging("199801.txt""train.data")  

执行

[python]  view plain  copy
  1. python make_crf_train_data.py  inputFilePath  tag4OutputFilePath  


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

tag4OutputFilePath 部分:

[python]  view plain  copy
  1. 1   m   E  
  2. 迈   v   B  
  3. 向   v   E  
  4. 充   v   B  
  5. 满   v   E  
  6. 希   n   B  
  7. 望   n   E  
  8. 的   u   S  
  9. 新   a   S  
  10. 世   n   B  
  11. 纪   n   E  
  12. —   w   B  
  13. —   w   E  
  14. 一   t   B  
  15. 九   t   M  
  16. 九   t   M  
  17. 八   t   M  
  18. 年   t   E  
  19. 新   t   B  
  20. 年   t   E  
  21. 讲   n   B  
  22. 话   n   E  
  23. (   w   S  
  24. 附   v   S  
  25. 图   n   B  
  26. 片   n   E  
  27. 1   m   S  
  28. 张   q   S  
  29. )   w   S  



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

[python]  view plain  copy
  1. crf_learn -f 3 -c 1.5 ./example/seg/template ../tag4OutputFilePath  crf_model  

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

编写py文件分词 :crf_segmenter.py

[html]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. #crf_segmenter.py  
  4. #用法:命令行输入--python crf_segmenter.py crf_model input_file output_file  
  5. # 利用CRF自带的python工具包,对输入文本进行分词  
  6.    
  7. import codecs  
  8. import sys  
  9.    
  10. import CRFPP  
  11.    
  12. def crf_segmenter(input_file, output_file, tagger):  
  13.     input_data = codecs.open(input_file, 'r', 'utf-8')  
  14.     output_data = codecs.open(output_file, 'w', 'utf-8')  
  15.     for line in input_data.readlines():  
  16.         tagger.clear()  
  17.         for word in line.strip():  
  18.             word = word.strip()  
  19.             if word:  
  20.                 tagger.add((word + "\to\tB").encode('utf-8'))  
  21.         tagger.parse()  
  22.         size = tagger.size()  
  23.         xsize = tagger.xsize()  
  24.         for i in range(0, size):  
  25.             for j in range(0, xsize):  
  26.                 char = tagger.x(i, j).decode('utf-8')  
  27.                 tag = tagger.y2(i)  
  28.                 if tag == 'B':  
  29.                     output_data.write(' ' + char)  
  30.                 elif tag == 'M':  
  31.                     output_data.write(char)  
  32.                 elif tag == 'E':  
  33.                     output_data.write(char + ' ')  
  34.                 else: #tag == 'S'  
  35.                     output_data.write(' ' + char + ' ')  
  36.         output_data.write('\n')  
  37.     input_data.close()  
  38.     output_data.close()  
  39.    
  40. if __name__ == '__main__':  
  41.     if len(sys.argv) != 4:  
  42.         print "pls use: python crf_segmenter.py model input output"  
  43.         sys.exit()  
  44.     crf_model = sys.argv[1]  
  45.     input_file = sys.argv[2]  
  46.     output_file = sys.argv[3]  
  47.     tagger = CRFPP.Tagger("-m " + crf_model)  
  48.     crf_segmenter(input_file, output_file, tagger)#  
input_file是需要分词的文件,output_file是分词后的输出文件

最后执行:

[html]  view plain  copy
  1. python crf_segmenter.py crf_model input_file output_file  




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


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



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

[python]  view plain  copy
  1. === SUMMARY:  
  2. === TOTAL INSERTIONS: 99  
  3. === TOTAL DELETIONS: 30  
  4. === TOTAL SUBSTITUTIONS: 156  
  5. === TOTAL NCHANGE: 285  
  6. === TOTAL TRUE WORD COUNT: 821  
  7. === TOTAL TEST WORD COUNT: 890  
  8. === TOTAL TRUE WORDS RECALL: 0.773  
  9. === TOTAL TEST WORDS PRECISION: 0.713  
  10. === F MEASURE: 0.742  
  11. === OOV Rate: 0.141  
  12. === OOV Recall Rate: 0.259  
  13. === IV Recall Rate: 0.858  
  14. ### blog_test_segment.utf8 99 30 156 285 821 890 0.773 0.713 0.742 0.141 0.259 0.858  


[html]  view plain  copy
  1. <pre code_snippet_id="2137761" snippet_file_name="blog_20170118_1_4933737" name="code" class="html"><pre code_snippet_id="2137761" snippet_file_name="blog_20170118_1_4933737"></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6. <pre></pre>  
  7. <pre></pre>  
  8. <pre></pre>  
  9. <link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=2.0">  
  10.             </pre>  

猜你喜欢

转载自blog.csdn.net/fsz520w/article/details/78384587