ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python中文分词教程之前向最大正向匹配算法介绍

2020-03-18 10:56:00  阅读:257  来源: 互联网

标签:教程 python S2 S1 词表 课时 sys 去掉 分词


  前言

  中文分词是中文文本处理的一个基础性工作,然而长久以来,在Python编程领域,一直缺少高准确率、高效率的分词组件。

  大家都知道,英文的分词由于单词间是以空格进行分隔的,所以分词要相对的容易些,而中文就不同了,中文中一个句子的分隔就是以字为单位的了,而所谓的正向最大匹配和逆向最大匹配便是一种分词匹配的方法,这里以词典匹配说明。

  最大匹配算法是自然语言处理中的中文匹配算法中最基础的算法,分为正向和逆向,原理都是一样的。

  正向最大匹配算法,故名思意,从左向右扫描寻找词的最大匹配。

  首先我们可以规定一个词的最大长度,每次扫描的时候寻找当前开始的这个长度的词来和字典中的词匹配,如果没有找到,就缩短长度继续寻找,直到找到或者成为单字。

  下面话不多说了,来一起看看详细的介绍吧。

  实例:

  S1=“计算语言学课程是三个课时” ,设定最大词长MaxLen = 5 ,S2= " "

  字典中含有三个词:[计算语言学]、[课程]、[课时]

  (1)S2="";S1不为空,从S1左边取出候选子串W="计算语言学";

  (2)查词表,“计算语言学”在词表中,将W加入到S2中,S2=“计算语言学/ ”, 并将W从S1中去掉,此时S1="课程是三个课时";

  (3)S1不为空,于是从S1左边取出候选子串W="课程是三个";

  (4)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程是三";

  (5)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程是";

  (6)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程"

  (7)查词表,W在词表中,将W加入到S2中,S2=“计算语言学/ 课程/ ”,并 将W从S1中去掉,此时S1="是三个课时";

  (8)S1不为空,于是从S1左边取出候选子串W="是三个课时";

  (9)查词表,W不在词表中,将W最右边一个字去掉,得到W="是三个课";

  (10)查词表,W不在词表中,将W最右边一个字去掉,得到W="是三个";

  (11)查词表,W不在词表中,将W最右边一个字去掉,得到W="是三"

  (12)查词表,W不在词表中,将W最右边一个字去掉,得到W=“是”,这时 W是单字,将W加入到S2中,S2=“计算语言学/ 课程/ 是/ ”,并将 W从S1中去掉,此时S1="三个课时";

  (13)S1不为空,从S1左边取出候选子串W="三个课时";

  (14)查词表,W不在词表中,将W最右边一个字去掉,得到W="三个课";

  (15)查词表,W不在词表中,将W最右边一个字去掉,得到W="三个";

  (16)查词表,W不在词表中,将W最右边一个字去掉,得到W=“三”,这时 W是单字,将W加入到S2中,S2=“计算语言学/ 课程/ 是/ 三/ ”,并 将W从S1中去掉,此时S1="个课时";

  (17)S1不为空,从S1左边取出候选子串W="个课时";

  (18)查词表,W不在词表中,将W最右边一个字去掉,得到W="个课";

  (19)查词表,W不在词表中,将W最右边一个字去掉,得到W=“个”, 这时W是单字,将W加入到S2中,S2=“计算语言学/ 课程/ 是/ 三/ 个/ ",并将W从S1中去掉,此时S1="课时";

  (20)S1不为空,从S1左边取出候选子串W="课时";

  (21)查词表,W在词表中,将W加入到S2中,S2=“计算语言学/ 课程/ 是/ 三/ 个/ 课时/ ",并将W从S1中去掉,此时S1=""。

  (22)S1为空,输出S2作为分词结果,分词过程结束。

  而至于为什么选择python这个语言呢?大概是因为我周围人用得少吧,我就想尝试突破,不过我也不讳言,我的C/C++,java等等高级语言用的也不多,虽说编程语言这个东西,基本上只要熟悉一个,其他的都好学,不过我在python上尝到了甜头,索性就用这个语言了。

  中文分词算法的Python实现:

  脚本接受两个参数,一个是输入文件的路径,另一个是词典的路径。

  它的运行方法如下:

  python max-match.py

  #!/usr/bin/env python

  import cPickle as pickle

  import sys

  # 词语最大长度为5

  window_size=5

  def max_match_segment(line, dic):

  # write your code here

  chars = line.decode("utf8")

  words = []

  idx = 0

  # 判断索引是否超过chars的长度

  while idx < len(chars):

  matched = False

  for i in xrange(window_size, 0, -1):

  cand=chars[idx:idx+i].encode("utf8")

  if cand in dic:

  words.append(cand)

  matched = True

  break

  # 判断for中是否匹配到数据

  if not matched:

  i = 1郑州妇科医院哪家好 yiyuan.120ask.com/art/

  words.append(chars[idx].encode("utf8"))

  idx += i

  return words

  if __name__=="__main__":

  try:

  fpi=open(sys.argv[1], "r")

  except:

  print >> sys.stderr, "failed to open file"

  sys.exit(1)

  try:

  dic = pickle.load(open(sys.argv[2], "r"))

  except:

  print >> sys.stderr, "failed to load dict %s" % sys.argv[2]

  sys.exit(1)

  try:

  fpo = open("out.txt","w")

  except:

  print >> sys.stderr, "failed to load out.txt"

  sys.exit(1)

  for line in fpi:

  fpo.write("\t".join( max_match_segment(line.strip(), dic) ))

  当然,这只是最基础的,还可以有很多高级的优化,比如说改成Trie树版本的,控制最大词长度的等等。


标签:教程,python,S2,S1,词表,课时,sys,去掉,分词
来源: https://blog.51cto.com/14335413/2479579

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有