最大匹配法:最大匹配是指以詞典為依據,取詞典中最長單詞為第一個次取字數量的掃描串,在詞典中進行掃描(為提升掃描效率,還可以跟據字數多少設計多個字典,然后根據字數分別從不同字典中進行掃描)。例如:詞典中最長詞為“中華人民共和國”共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