Python中文分词的简单示例

前端之家收集整理的这篇文章主要介绍了Python中文分词的简单示例前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对python这个高级语言感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编两巴掌来看看吧!

解压后取出以下文件

训练数据:icwb2-data/training/pku_ training.utf8

测试数据:icwb2-data/testing/pku_ test.utf8

正确分词结果:icwb2-data/gold/pku_ test_ gold.utf8

评分工具:icwb2-data/script/socre

2 算法描述

算法是最简单的正向最大匹配(FMM):

用训练数据生成一个字典

对测试数据从左到右扫描,遇到一个最长的词,就切分下来,直到句子结束

注:这是最初的算法,这样做代码可以控制在60行内,后来看测试结果发现没有很好地处理数字问题, 才又增加了对数字的处理。

3 源代码及注释

  1. # @param 用Python写一个简单的中文分词器
  2. # @author 编程之家 jb51.cc|jb51.cc
  3. #! /usr/bin/env python
  4. # -*- coding: utf-8 -*-
  5. # Author: minix
  6. # Date: 2013-03-20
  7. import codecs
  8. import sys
  9. # 由规则处理的一些特殊符号
  10. numMath = [u'0',u'1',u'2',u'3',u'4',u'5',u'6',u'7',u'8',u'9']
  11. numMath_suffix = [u'.',u'%',u'亿',u'万',u'千',u'百',u'十',u'个']
  12. numCn = [u'一',u'二',u'三',u'四',u'五',u'六',u'七',u'八',u'九',u'〇',u'零']
  13. numCn_suffix_date = [u'年',u'月',u'日']
  14. numCn_suffix_unit = [u'亿',u'个']
  15. special_char = [u'(',u')']
  16. def proc_num_math(line,start):
  17. """ 处理句子中出现的数学符号 """
  18. oldstart = start
  19. while line[start] in numMath or line[start] in numMath_suffix:
  20. start = start + 1
  21. if line[start] in numCn_suffix_date:
  22. start = start + 1
  23. return start - oldstart
  24. def proc_num_cn(line,start):
  25. """ 处理句子中出现的中文数字 """
  26. oldstart = start
  27. while line[start] in numCn or line[start] in numCn_suffix_unit:
  28. start = start + 1
  29. if line[start] in numCn_suffix_date:
  30. start = start + 1
  31. return start - oldstart
  32. def rules(line,start):
  33. """ 处理特殊规则 """
  34. if line[start] in numMath:
  35. return proc_num_math(line,start)
  36. elif line[start] in numCn:
  37. return proc_num_cn(line,start)
  38. def genDict(path):
  39. """ 获取词典 """
  40. f = codecs.open(path,'r','utf-8')
  41. contents = f.read()
  42. contents = contents.replace(u'\r',u'')
  43. contents = contents.replace(u'\n',u'')
  44. # 将文件内容按空格分开
  45. mydict = contents.split(u' ')
  46. # 去除词典List中的重复
  47. newdict = list(set(mydict))
  48. newdict.remove(u'')
  49. # 建立词典
  50. # key为词首字,value为以此字开始的词构成的List
  51. truedict = {}
  52. for item in newdict:
  53. if len(item)>0 and item[0] in truedict:
  54. value = truedict[item[0]]
  55. value.append(item)
  56. truedict[item[0]] = value
  57. else:
  58. truedict[item[0]] = [item]
  59. return truedict
  60. def print_unicode_list(uni_list):
  61. for item in uni_list:
  62. print item,def divideWords(mydict,sentence):
  63. """
  64. 根据词典对句子进行分词,使用正向匹配的算法,从左到右扫描,遇到最长的词,
  65. 就将它切下来,直到句子被分割完闭
  66. """
  67. ruleChar = []
  68. ruleChar.extend(numCn)
  69. ruleChar.extend(numMath)
  70. result = []
  71. start = 0
  72. senlen = len(sentence)
  73. while start < senlen:
  74. curword = sentence[start]
  75. maxlen = 1
  76. # 首先查看是否可以匹配特殊规则
  77. if curword in numCn or curword in numMath:
  78. maxlen = rules(sentence,start)
  79. # 寻找以当前字开头的最长词
  80. if curword in mydict:
  81. words = mydict[curword]
  82. for item in words:
  83. itemlen = len(item)
  84. if sentence[start:start+itemlen] == item and itemlen > maxlen:
  85. maxlen = itemlen
  86. result.append(sentence[start:start+maxlen])
  87. start = start + maxlen
  88. return result
  89. def main():
  90. args = sys.argv[1:]
  91. if len(args) < 3:
  92. print 'Usage: python dw.py dict_path test_path result_path'
  93. exit(-1)
  94. dict_path = args[0]
  95. test_path = args[1]
  96. result_path = args[2]
  97. dicts = genDict(dict_path)
  98. fr = codecs.open(test_path,'utf-8')
  99. test = fr.read()
  100. result = divideWords(dicts,test)
  101. fr.close()
  102. fw = codecs.open(result_path,'w','utf-8')
  103. for item in result:
  104. fw.write(item + ' ')
  105. fw.close()
  106. if __name__ == "__main__":
  107. main()
  108. # End www.jb51.cc

4 测试及评分结果

使用 dw.py 训练数据 测试数据, 生成结果文件

使用 score 根据训练数据,正确分词结果,和我们生成的结果进行评分

使用 tail 查看结果文件最后几行的总体评分,另外socre.utf8中还提供了大量的比较结果, 可以用于发现自己的分词结果在哪儿做的不够好

注:整个测试过程都在Ubuntu下完成

$ python dw.py pku_training.utf8 pku_test.utf8 pku_result.utf8

$ perl score pku_training.utf8 pku_test_gold.utf8 pku_result.utf8 > score.utf8

$ tail -22 score.utf8

INSERTIONS: 0

DELETIONS: 0

SUBSTITUTIONS: 0

NCHANGE: 0

NTRUTH: 27

NTEST: 27

TRUE WORDS RECALL: 1.000

TEST WORDS PRECISION: 1.000

=== SUMMARY:

=== TOTAL INSERTIONS: 4623

=== TOTAL DELETIONS: 1740

=== TOTAL SUBSTITUTIONS: 6650

=== TOTAL NCHANGE: 13013

=== TOTAL TRUE WORD COUNT: 104372

=== TOTAL TEST WORD COUNT: 107255

=== TOTAL TRUE WORDS RECALL: 0.920

=== TOTAL TEST WORDS PRECISION: 0.895

=== F MEASURE: 0.907

=== OOV Rate: 0.940

=== OOV Recall Rate: 0.917

=== IV Recall Rate: 0.966

 

基于词典的FMM算法是非常基础的分词算法,效果没那么好,不过足够简单,也易于入手,随着学习的深入,我可能还会用Python实现其它的分词算法。另外一个感受是,看书的时候尽量多去实现,这样会让你有足够的热情去关注理论的每一个细节,不会感到那么枯燥无力。

猜你在找的Python相关文章