双向最大匹配算法python_python中文分词教程之前向最大正向匹配算法详解

中文分词是中文文本处理的一个基础性工作,然而长久以来,在Python编程领域,一直缺少高准确率、高效率的分词组件。下面这篇文章主要给大家介绍了关于python中文分词教程之前向最大正向匹配算法的相关资料,需要的朋友可以参考下。

364141c0ec1142f913682e5df08243ab.png

前言

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

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

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

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

9c886305178ba7d929673f3d41382f2a.png

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

实例:

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上尝到了甜头,索性就用这个语言了。

483ea1eaafe1fabe7bb53ef56cfe9e35.png

中文分词算法的Python实现:

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

它的运行方法如下:

python max-match.py 
#!/usr/bin/env pythonimport cPickle as pickleimport sys # 词语最大长度为5window_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   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("".join( max_match_segment(line.strip(), dic) ))

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值