中文分詞--最大正向與逆向匹配算法python實現


最大匹配法:最大匹配是指以詞典為依據,取詞典中最長單詞為第一個次取字數量的掃描串,在詞典中進行掃描(為提升掃描效率,還可以跟據字數多少設計多個字典,然后根據字數分別從不同字典中進行掃描)。例如:詞典中最長詞為“中華人民共和國”共7個漢字,則最大匹配起始字數為7個漢字。然后逐字遞減,在對應的詞典中進行查找。

下面以“我們在野生動物園玩”為例詳細說明一下正向與逆向最大匹配方法:

  • 1、正向最大匹配法:

正向即從前往后取詞,從7->1,每次減一個字,直到詞典命中或剩下1個單字。

第1次:“我們在野生動物”,掃描7字詞典,無

第2次:“我們在野生動”,掃描6字詞典,無

。。。。

第6次:“我們”,掃描2字詞典,有

掃描中止,輸出第1個詞為“我們”,去除第1個詞后開始第2輪掃描,即:

第2輪掃描:

第1次:“在野生動物園玩”,掃描7字詞典,無

第2次:“在野生動物園”,掃描6字詞典,無

。。。。

第6次:“在野”,掃描2字詞典,有

掃描中止,輸出第2個詞為“在野”,去除第2個詞后開始第3輪掃描,即:

第3輪掃描:

第1次:“生動物園玩”,掃描5字詞典,無

第2次:“生動物園”,掃描4字詞典,無

第3次:“生動物”,掃描3字詞典,無

第4次:“生動”,掃描2字詞典,有

掃描中止,輸出第3個詞為“生動”,第4輪掃描,即:

第4輪掃描:

第1次:“物園玩”,掃描3字詞典,無

第2次:“物園”,掃描2字詞典,無

第3次:“物”,掃描1字詞典,無

掃描中止,輸出第4個詞為“物”,非字典詞數加1,開始第5輪掃描,即:

第5輪掃描:

第1次:“園玩”,掃描2字詞典,無

第2次:“園”,掃描1字詞典,有

掃描中止,輸出第5個詞為“園”,單字字典詞數加1,開始第6輪掃描,即:

第6輪掃描:

第1次:“玩”,掃描1字字典詞,有

掃描中止,輸出第6個詞為“玩”,單字字典詞數加1,整體掃描結束。

正向最大匹配法,最終切分結果為:“我們/在野/生動/物/園/玩”

  • 2、正向python代碼實現
 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Thu Jul 19 08:57:56 2018
 4 
 5 @author: Lenovo
 6 """
 7 
 8 test_file = 'train/train.txt'#訓練語料
 9 test_file2 = 'test/test.txt'#測試語料
10 test_file3 = 'test_sc/test_sc_zhengxiang.txt'#生成結果
11 
12 def get_dic(test_file): #讀取文本返回列表
13     with open(test_file,'r',encoding='utf-8',) as f:
14         try:
15             file_content = f.read().split()
16         finally:
17             f.close()
18     chars = list(set(file_content))
19     return chars
20 
21 dic = get_dic(test_file)           
22 def readfile(test_file2):
23     max_length = 5 
24     
25     h = open(test_file3,'w',encoding='utf-8',) 
26     with open(test_file2,'r',encoding='utf-8',) as f:
27         lines = f.readlines()
28 
29     for line in lines:#分別對每行進行正向最大匹配處理
30         max_length = 5 
31         my_list = []
32         len_hang = len(line)
33         while len_hang>0 :
34             tryWord = line[0:max_length]
35             while tryWord not in dic:
36                 if len(tryWord)==1:
37                     break
38                 tryWord=tryWord[0:len(tryWord)-1]
39             my_list.append(tryWord)
40             line = line[len(tryWord):]
41             len_hang = len(line)
42         
43         for t in my_list:#將分詞結果寫入生成文件
44             if t == '\n' :
45                 h.write('\n')
46             else:
47                 h.write(t + "  ")
48     
49     h.close()
50         
51 readfile(test_file2)
  • 3、逆向最大匹配算法

逆向即從后往前取詞,其他邏輯和正向相同。即:

第1輪掃描:“在野生動物園玩”

第1次:“在野生動物園玩”,掃描7字詞典,無

第2次:“野生動物園玩”,掃描6字詞典,無

。。。。

第7次:“玩”,掃描1字詞典,有

掃描中止,輸出“玩”,單字字典詞加1,開始第2輪掃描

第2輪掃描:“們在野生動物園”

第1次:“們在野生動物園”,掃描7字詞典,無

第2次:“在野生動物園”,掃描6字詞典,無

第3次:“野生動物園”,掃描5字詞典,有

掃描中止,輸出“野生動物園”,開始第3輪掃描

第3輪掃描:“我們在”

第1次:“我們在”,掃描3字詞典,無

第2次:“們在”,掃描2字詞典,無

第3次:“在”,掃描1字詞典,有

掃描中止,輸出“在”,單字字典詞加1,開始第4輪掃描

第4輪掃描:“我們”

第1次:“我們”,掃描2字詞典,有

掃描中止,輸出“我們”,整體掃描結束。

逆向最大匹配法,最終切分結果為:“我們/在/野生動物園/玩

  • 4、逆向python代碼實現
 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Thu Jul 19 08:57:56 2018
 4 
 5 @author: Lenovo
 6 """
 7 test_file = 'train/train.txt'
 8 test_file2 = 'test/test.txt'
 9 test_file3 = 'test_sc/test_sc.txt'
10 
11 def get_dic(test_file): 
12     with open(test_file,'r',encoding='utf-8',) as f:
13         try:
14             file_content = f.read().split()
15         finally:
16             f.close()
17     chars = list(set(file_content))
18     return chars
19 
20 dic = get_dic(test_file)           
21 def readfile(test_file2):
22     max_length = 5 
23     
24     h = open(test_file3,'w',encoding='utf-8',) 
25     with open(test_file2,'r',encoding='utf-8',) as f:
26         lines = f.readlines()
27 
28     for line in lines:
29         my_stack = []
30         len_hang = len(line)
31         while len_hang>0 :
32             tryWord = line[-max_length:]
33             while tryWord not in dic:
34                 if len(tryWord)==1:
35                     break
36                 tryWord=tryWord[1:]
37             my_stack.append(tryWord)
38             line = line[0:len(line)-len(tryWord)]
39             len_hang = len(line)
40         
41         while len(my_stack):
42             t = my_stack.pop()
43             if t == '\n' :
44                 h.write('\n')
45             else:
46                 h.write(t + "  ")
47     
48     h.close()
49         
50 readfile(test_file2)
  • 5、正確率,召回率和F值

    正確率、召回率和F值是目標的重要評價指標。 

    正確率 = 正確識別的個體總數 / 識別出的個體總數 
    召回率 = 正確識別的個體總數 / 測試集中存在的個體總數 
    F值 = 正確率 * 召回率 * 2 / (正確率 + 召回率)

編寫評價程序:首先對生成的文本和gold文本每行通過切分形成詞匯表,然后對兩個詞匯表從第一個詞開始比較:
         如果當前詞匯相同,表明結果正確,且之前的詞匯拼成的字符串長度相等;
         如果當前詞匯不同,結果錯誤,不斷取詞匯拼字符串直到兩個字符串長度相同;
    依次對每行進行處理,計算出f值。

  評價程序實現如下:

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Fri Jul 27 15:32:46 2018
 4 
 5 @author: Lenovo
 6 """
 7 
 8 test_file = 'test_sc/test_sc_zhengxiang.txt'
 9 test_file2 = 'gold/test_gold.txt'
10 def get_word(fname):
11    
12     f = open(fname,'r',encoding='utf-8',) 
13     lines = f.readlines()
14     
15     return lines
16 
17 
18 def calc():
19     lines_list_sc = get_word(test_file)
20     lines_list_gold = get_word(test_file2)
21     
22     lines_list_num = len(lines_list_gold)
23     
24     right_num = 0
25     m = 0#m存逆向結果文本詞的總數
26     n = 0#n存gold文本詞的總數
27     
28     for i in range(lines_list_num):
29 
30         line_list_sc = list(lines_list_sc[i].split())#line_list_sc為生成結果每行通過空格切分后的詞匯表
31         line_list_gold = list(lines_list_gold[i].split())#line_list_gold為正確結果每行通過空格切分后的詞匯表
32         
33         m += len(line_list_sc)
34         n += len(line_list_gold)
35 
36         str_sc = ''#存結果文本每行無空格連接起來的字符串
37         str_gold = ''#存gold文本每行無空格連接起來的字符串
38         
39         s = 0#表示結果文本每行列表的下標
40         g = 0#表示gold文本每行列表的下標
41         
42         while s < len(line_list_sc) and g < len(line_list_gold):
43             str_word_sc = line_list_sc[s]
44             str_word_gold = line_list_gold[g]
45             
46             str_sc += str_word_sc
47             str_gold += str_word_gold
48             
49             if str_word_sc == str_word_gold:#如果當前詞匯相同,表明結果正確,且之前的詞匯拼成的字符串長度相等
50                 s += 1
51                 g += 1
52                 right_num += 1
53             
54             else:#如果當前詞匯不同,結果錯誤,不斷取詞匯拼字符串直到兩個字符串長度相同
55                
56                 while len(str_sc) > len(str_gold):
57                     g += 1
58                     str_gold += line_list_gold[g]
59                    
60              
61                 while len(str_sc) < len(str_gold):
62                     s += 1
63                     str_sc += line_list_sc[s]
64                     
65                 g += 1
66                 s += 1
67                    
68     print("生成結果詞的個數:", m)
69     print("gold文本詞的個數:", n)              
70     print("正確詞的個數:", right_num)
71     p = right_num/m
72     r = right_num/n
73     f = 2*p*r/(p+r)
74     print("正確率:", p)
75     print("召回率:", r)
76     print("正向f值:", f)
77 calc()

運行結果如下:

  • 6、訓練語料和測試語料見下百度雲盤鏈接

鏈接: https://pan.baidu.com/s/1X0coEznut6_s0jsDG9_9Dg 密碼: b393


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM