python中文分词


相对于英文而言,中文在计算机处理方面有个必须要面对的问题就是中文分词,英文的单词都是空格间隔的,而中文的词语则不同,所以用程序解决中文分词,在很多自然语言处理方面都是首要进行的步骤。

其中最简单的就是最大匹配的中文分词了,比如“今天天气不错”可以分词为“今天/天气/不错”,但是面对一些有歧义的句子时却显得捉襟见肘,于是“南京市长江大桥”就会被分成“南京市长/江/大桥”而不是“南京市/长江/大桥”,于是更好的是基于统计学原理的分词,也就是说看哪种出现的频率更高。

对于一个中文字符串“a1a2a3...an”如何正确的用词语c1,c2..cm表示就是中文分词的任务,也就是说我们要去找寻P(c1c2..cm)最大的分词,按照马尔科夫链的想法就是说我们就是求P(c1)*P(c1|c2)*P(c1c2|c3)*...P(c1c2...cm-1|cm)最大。按照阿卡姆剃刀的想法我们可以假设一个最可能的实现,于是google黑板报的假设就是每个词只跟前面的词有关,于是变为求P(c1)*P(c1|c2)*P(c2|c3)*...P(cm-1|cm)最大。进一步的其实我们可以假设每个词都是相对独立的,也就是求P(c1)*P(c2)*...P(cm)最大,那么这个怎么求呢,就是用dp(动态规划)的方法。ok,上代码。

  1. # -*- coding: UTF-8 -*-
  2.  
  3. import  collections
  4. d= collections. defaultdict ( lambda: 1 )
  5.  
  6. def init (filename= 'SogouLabDic.dic' ):
  7.     f= open (filename, 'r' )
  8.     total= 0
  9.      while  True:
  10.         line=f. readline ( )
  11.          if  not line:  break
  12.         word, freq = line. split ( '\t' ) [ 0: 2 ]
  13.         total+= int (freq ) +1 #smooth
  14.          try:
  15.             d [word. decode ( 'gbk' ) ]= int (freq ) +1
  16.          except:
  17.             d [word ]= int (freq ) +1
  18.     f. close ( )
  19.     d [ '_t_' ]=total
  20.  
  21. def solve (s ):
  22.     l= len (s )
  23.     p= [ 0  for i  in  range (l +1 ) ]
  24.     p [l ]= 1
  25.     div= [ 1  for i  in  range (l +1 ) ]
  26.     t= [ 1  for i  in  range (l ) ]
  27.      for i  in  range (l -1, -1, -1 ):
  28.          for k  in  range ( 1,l-i +1 ):
  29.             tmp=d [s [i:i+k ] ]
  30.              if k > 1  and tmp== 1:
  31.                  continue
  32.              if (d [s [i:i+k ] ] *p [i+k ] *div [i ]  > p [i ] *d [ '_t_' ] *div [i+k ] ):
  33.                 p [i ]=d [s [i:i+k ] ] *p [i+k ]
  34.                 div [i ]=d [ '_t_' ] *div [i+k ]
  35.                 t [i ]=k
  36.     i= 0
  37.      while i <l:
  38.          print s [i:i+t [i ] ],
  39.         i=i+t [i ]
  40.  
  41.  
  42. if __name__ ==  '__main__':
  43.     init ( )
  44.     s= "其中最简单的就是最大匹配的中文分词"
  45.     s=s. decode ( 'utf8' )
  46.     solve (s )

词库用到了搜狗实验室提供的不错的词库,程序还是很清晰的,值得注意的就是乘法不要直接去乘因为频率都是小于1的,乘的太多可能就会变为0就要影响整个算法了,所以我是分子分母分开存放的,话说直接用了python的原生大整数,连gcd都懒得写了啊。。。

ps:注意到如果词在字典里没有出现会导致概率乘积是0的情况,所以需要进行smooth

参考资料:
http://scturtle.is-programmer.com/posts/26648.html
http://www.matrix67.com/blog/archives/4212
http://www.google.com.hk/ggblog/googlechinablog/2006/04/blog-post_7327.html
http://mindhacks.cn/2008/09/21/the-magical-bayesian-method/

------------我是分割线--------------------
理论上用log相加的方法是最好的,于是修改了下代码,变得更简短了,只要34行哎,代码在github

   
   
---------------------------- -笔记:---------------------------------
动态规划求最大值
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值