NLP-中文分詞:最大正向匹配算法

語言: CN / TW / HK

本文已參與「新人創作禮」活動,一起開啟掘金創作之路。


一、前言

1、什麼是分詞

在講分詞算法之前,先來研究一下什麼是分詞? 分詞是將語句按照語境,以字詞為單位劃分的一個過程,如下圖所示: image.png

2、為什麼需要分詞

那為什麼需要分詞呢?筆者認為主要有一下幾個原因:

1、漢語的基本組成單位是字詞,造成了字詞成為了理解語句的基本單位(這其實是文化思維定式) 2、中文的自然語言處理技術好多事借鑑於英文的,而英文語句是單詞構成語句,以空格分隔,在處理上也就就從單詞角度為起點 3、人類的思維方式很容易以自我意識為主導,習慣於將自己的認知方式賦予其他生物或者機器,我們從字詞開始理解語言,也認為機器需要從字詞開始...

二、最大正向匹配算法

1、原理

本文主要講述一種比較傳統的分詞算法--最大正向匹配算法,所謂的最大正向,也就是從句子左側開始匹配,匹配到的詞以最大長度為準,當然有最大正向,也就有最大逆向,雙向等等。從匹配兩個字可以看出該算法的核心在於匹配,而且是徹徹底底地基於詞典的匹配!

看到這裏你可能會覺得很low,沒錯,就是很low,但這是因為我們站在高等生物的角度去俯瞰它,俯瞰的同時,我們心中還有個對比參照的詞,那就是智能!

你想象那是一個機器,一個只認識01代碼的傢伙,更深了説,它連0和1都不認識,只認識有電和沒電,這樣一想,你或許覺得該算法也沒那麼low! 扯完了題外話,下面説一説他的原理。

(1)第一步:定義詞典

既然是基於詞典的匹配,那我們首先的有個詞典,這個詞典裏包含了我們所要使用各種詞語:

python words= ["你好","查詢","城市","天氣","明天","後天","今天","如花似玉"...]

(2)定義需要分詞句子

python input_sentence = "你好,幫我查詢一下明天的天氣"

(3)選取詞典中最大匹配長度

python max_match_length = len("如花似玉") = 4

(4)開始匹配

截取input_sentence的前四位,進行正向匹配 :

python match_sentence = input_sentence[0:4] = "你好,幫"

在詞典words中無法匹配,此時去掉match_sentence的最後一位,剩下的匹配句子為:

python match_sentence = "你好,"

在詞典words中依舊無法匹配,此時去掉match_sentence的最後一位,剩下的匹配句子為:

python match_sentence = "你好" 發現“你好”在詞典words中,那麼得到第一個分詞結果 python cut_result = ["你好"] 此時,剩下需要分詞的句子為: python input_sentence = input_sentence - match_sentence = "你好,幫我查詢一下明天的天氣" - "你好" = ",幫我查詢一下明天的天氣" 依舊截取input_sentence的前四位 : python match_sentence = input_sentence[0:4] = ",幫我查" 在詞典words中無法匹配,此時去掉match_sentence的最後一位,剩下的匹配句子為: ```python match_sentence = ",幫我"

沒有匹配上,去除最後一位

match_sentence = ",幫"

沒有匹配上,去除最後一位

match_sentence = ","

遇到單字沒有匹配上,獨立為一個詞

此時分詞結果為

cut_result = ["你好",","]

還剩餘的句子

input_sentence = "幫我查詢一下明天的天氣"

重複上述的過程,最後得到分詞結果為:python cut_result = ["你好",",","幫","我","查詢","一下","明天","的","天氣"] ```

2、代碼實戰

由於本人懶,之前寫過Java的,直接搬過來了,就不轉化為Python版本了,相信表達方式的差異化並不會影響到事物的原理本身(你就是不想寫,廢話那麼多)! java /** * 分詞功能 基於最大正向匹配算法 * @param message */ public List<String > cut(String message) { List<String > cutResult = new ArrayList <String>(); while (message.length() > 0) { String matchMessage = message.substring(0, this.maxWordLength>message.length()?message.length():this.maxWordLength); while (!words.contains(matchMessage)) { if (matchMessage.length() > 1) { matchMessage = matchMessage.substring(0, matchMessage.length() - 1); } else{ break; } } cutResult.add(matchMessage); message = message.substring(matchMessage.length()); } return cutResult; }