正向逆向最大匹配算法实现自动分词python

原理指路这。
直接上实验过程。

1、199801人民日报语料

正向逆向最大匹配算法实现自动分词python_第1张图片
这是已经分词而且词性标记好的,我们用来获取里面的词,作为后续自己分词的底表。

2、生成底表

# 匹配词性
def cixing(data):
    dic = {
     }
    for line in data:   # 匹配普通词性标注
        pattern = re.findall(r'/[A-Za-z]{1,30}', line)
        for p in pattern:
                if p in dic:
                    dic[p] += 1
                else:
                    dic[p] = 1
    for line in data:   # 匹配实体词性标注,如[江  峡  大道]ns
        pattern2 = re.findall(r'][A-Za-z]{1,30}', line)
        for p in pattern2:
                #print(p)
                if p in dic:
                    dic[p] += 1
                else:
                    dic[p] = 1
    print(dic)
    print(len(dic))
    return dic


# 去除词性标注
def restore(dic, data):
    raw_data=[]
    final=[]
    for line in data:
        #print(line)  这里其实可以对字典排序一下 但是我懒得改了
        line=line.strip(' ').replace('[','')
        for i in dic.keys():
            if len(i)>=3:
                line = line.replace(i,'')  # 防止部分词性前缀相似导致的错误匹配
        raw_data.append(line)
    for l in raw_data:
        for i in dic.keys():
            l = l.replace(i,'').strip(' ')
        final.append(l)
    #print(final)
    return final


# 统计词汇
def wordlist(data):
    wordlist={
     }
    for line in data:
        line=line.split(' ')
        for word in line:
            if word in wordlist.keys():
                wordlist[word] += 1
            else:
                wordlist[word] = 1
    #wordlist.pop('')
    print(wordlist)
    return wordlist


def write_excel(path,dic):
    workbook = xlsxwriter.Workbook(path)
    worksheet = workbook.add_worksheet('sheet1')
    worksheet.write(0, 0, '词汇')
    worksheet.write(0, 1, '频次')
    for k, i in zip(range(len(dic)), dic.keys()):
        j = dic[i]
        #print(i, j)
        worksheet.write(k+1, 0, i)
        worksheet.write(k+1, 1, j)
    workbook.close()

形成下面形式的一个词表,我还统计了一下频次。
正向逆向最大匹配算法实现自动分词python_第2张图片

3、正向和逆向最大匹配算法实现

最大步长我设置为5,一般都是设置为5。

# 逆向最大匹配分词
def segword(data):
    wordlis= sorted(wordlexicon, key=lambda i: len(i), reverse=True)  # 按长度大小排序
    #print(wordlis)
    re=[]
    for i in range(len(data)):
        s1 = data[i]
        #print(s1)
        s2 = ''
        maxlen = 5
        w = s1[-maxlen:]  # 逆向
        while (w):
            if len(w) != 1:
                if w in wordlis:
                    s2 = w + ' ' + s2
                    n=len(s1)-len(w)
                    s1 = s1[0:n]
                    w = s1[-maxlen:]
                    #print(s2,s1)
                else:
                    w = w[1:len(w)]
                    #print(w)
            else:
                s2 = w + ' ' + s2
                n = len(s1) - len(w)
                s1 = s1[0:n]
                w = s1[-maxlen:]
                #print(s2, s1)
        re.append(s2)
    print(re)
    return re


# 正向最大匹配分词
def segword_2(data):
    wordlis= sorted(wordlexicon, key=lambda i: len(i), reverse=True)  # 按长度大小排序
    # print(wordlis)
    re=[]
    for i in range(len(data)):
        s1 = data[i]
        #print(s1)
        s2 = ''
        maxlen = 5
        w = s1[:maxlen]  # 逆向
        #print(w)
        while (w):
            if len(w) != 1:
                if w in wordlis:
                    s2 = s2 + w+ ' '
                    s1 = s1[len(w):]
                    w = s1[:maxlen]
                    #print(s2,s1)
                else:
                    w = w[:len(w)-1]
                    #print(w)
            else:
                s2 = s2 + w + ' '
                s1 = s1[len(w):]
                w = s1[:maxlen]
                #print(s2, s1)
        re.append(s2)
    print(re)
    return re

4、实践

我选了一篇新闻,用作待分词文本。
正向逆向最大匹配算法实现自动分词python_第3张图片
逆向结果:
正向逆向最大匹配算法实现自动分词python_第4张图片
正向结果:
正向逆向最大匹配算法实现自动分词python_第5张图片

5、评估

从处理速度、总体词数、分词粒度、以及未登录词等各方面都可以进行评估比较正向和逆向分词的效果。
一般来说,总体词数越少越好,在相同字数的情况下,总词数越少,说明语义单元越少,那么相对的单个语义单元的权重会越大,因此准确性会越高。
一般又说,分词的颗粒度越大,即单字词的数量越少,所能表示的含义越确切,比如对于“公安局长”可以分为“公安 局长”、“公安局 长”、“公安局长”都算对,但是要用于语义分析,则“公安局长”的分词结果最好。
下面是一个简单实现计算单字的程序。

# 单字
def word(data):
    sum=0
    for word in data.keys():
        if len(word)==1:
            sum+=1
    return sum


# 非词典单字
def non_word(data):
    num=0
    for word in data.keys():
        if len(word)==1 and word not in wordlist:
            num+=1
    return num

完整代码见

你可能感兴趣的:(python,自然语言处理)