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,上代码。

# -*- coding: UTF-8 -*-
 
importcollections
d=collections.defaultdict(lambda:1)
 
definit(filename='SogouLabDic.dic'):
    f=open(filename,'r')
    total=0
   whileTrue:
        line=f.readline()
       ifnotline:break
        word, freq = line.split('\t')[0:2]
        total+=1
       try:
            d[word.decode('gbk')]=int(freq)
       except:
            d[word]=int(freq)
    f.close()
    d['_t_']=total
 
defsolve(s):
    l=len(s)
    p=[0foriinrange(l+1)]
    p[l]=1
    div=[1foriinrange(l+1)]
    t=[1foriinrange(l)]
   foriinrange(l-1,-1,-1):
       forkinrange(1,l-i+1):
            tmp=d[s[i:i+k]]
           ifk>1andtmp==1:
               continue
           if(d[s[i:i+k]]*p[i+k]*div[i]>p[i]*d['_t_']*div[i+k]):
                p[i]=d[s[i:i+k]]*p[i+k]
                div[i]=d['_t_']*div[i+k]
                t[i]=k
    i=0
   whilei<l:
       prints[i:i+t[i]],
        i=i+t[i]
 
 
if__name__ =='__main__':
    init()
    s="其中最简单的就是最大匹配的中文分词"
    s=s.decode('utf8')
    solve(s)
词库用到了搜狗实验室提供的不错的词库,程序还是很清晰的,值得注意的就是乘法不要直接去乘因为频率都是小于1的,乘的太多可能就会变为0就要影响整个算法了,所以我是分子分母分开存放的,话说直接用了python的原生大整数,连gcd都懒得写了啊。。。

 

摘自  isnowfy 

相关内容

    暂无相关文章

评论关闭