MMSEG是中文分詞中一個常見的、基於詞典的分詞演算法(作者首頁:http://chtsai.org/index_tw.html),簡單、效果相對較好。由於它的簡易直觀性,實現起來不是很複雜,運行速度也比較快。關於演算法的原文,可以參 見:http://technology.chtsai.org/mmseg/
總的來說現在的中文分詞演算法,大概可以籠統的分為兩大類:一種基於詞典的,一種是非基於詞典的。
基於詞典的分詞演算法比較常見,比如正向/逆向最大匹配,最小切分(使一句話中的詞語數量最少)等。具體使用的時候,通常是多種演算法合用,或者一種為主、多種為輔,同時還會加入詞性、詞頻等屬性來輔助處理(運用某些簡單的數學模型)。
非 基於詞典的演算法,一般主要是運用機率統計、機器學習等方面的方法,目前常見的是CRF(Conditional random field, http://en.wikipedia.org/wiki/Conditional_random_field)。此類方法可以讓電腦根據現成的資 料,“學習”如何分詞。具體的實現可參考(http://nlp.stanford.edu/software/segmenter.shtml)。
一般來說,這兩類方法各有優缺點:基於詞典的方法,實現、部署比較容易,但是分詞精度有限,且對於未登入 詞(詞典裡沒有的詞語)識別較差;非基於詞 典的方法,速度較快,對未登入詞識別效果較好,能夠根據使用領域達到較高的分詞精度,但是實現比較複雜,通常需要大量的前期工作。
MMSEG是一種基於詞典的分詞演算法,以正向最大匹配為主,多種消除歧義的規則為輔。下面來具體看一下:
根 據作者在原文中的闡述,對MMSEG的解釋分為“匹配演算法(Matching algorithm)”和“消除歧義的規則(Ambiguity resolution rules)”這兩部分。“匹配演算法”是說如何根據詞典裡儲存的詞語,對要切分的語句進行匹配(正向?逆向?粒度?);“消除歧義的規則”是說當一句話可 以這樣分,也可以那樣分的時候,用什麼規則來判定使用哪中分法,比如“設施和服務”這個短語,可以分成“設施_和服_務”,也可以分成“設施_和_服 務”,選擇哪個分詞結果,就是“消除歧義的規則”的功能。
MMSEG的“匹配方法”有兩種:
1.Simple方法,即簡單的正向匹配,根據開頭的字,列出所有可能的結果。比如“一個勁兒的說話”,可以得到
一個
一個勁
一個勁兒
一個勁兒的
這四個匹配結果(假設這四個詞都包含在詞典裡)。
2.Complex方法,匹配出所有的“三個詞的片語”(原文中使用了chunk,這裡感覺用“片語”比較合適),即從某一既定的字為起始位置,得到所有可能的“以三個詞為一組”的所有組合。比如“研究生命起源”,可以得到
研_究_生
研_究_生命
研究生_命_起源
研究_生命_起源
這些“片語”(根據詞典,可能遠不止這些,僅此舉例)
“消除歧義的規則”有四個,使用中依次用這四個規則進行過濾,直到只有一種結果或者第四個規則使用完畢。這個四個規則分別是:
1.Maximum matching (最大匹配),有兩種情況,分別對應於使用“simple”和“complex”的匹配方法。對“simple”匹配方法,選擇長度最大的詞,用在上文的 例子中即選擇“一個勁兒的”;對“complex”匹配方法,選擇“片語長度最大的”那個片語,然後選擇這個片語的第一個詞,作為切分出的第一個詞,上文 的例子中即“研究生_命_起源”中的“研究生”,或者“研究_生命_起源”中的“研究”。
2.Largest average word length(最大平均詞語長度)。經過規則1過濾後,如果剩餘的片語超過1個,那就選擇平均詞語長度最大的那個(平均詞長=片語總字數/詞語數量)。比如“生活水平”,可能得到如下片語:
生_活水_平 (4/3=1.33)
生活_水_平 (4/3=1.33)
生活_水平 (4/2=2)
根據此規則,就可以確定選擇“生活_水平”這個片語
3.Smallest variance of word lengths(詞語長度的最小變動率),由於詞語長度的變動率可以由標準差(http://baike.baidu.com/view/78339.htm)反映,所以此處直接套用標準差公式即可。比如
研究_生命_起源 (標準差=sqrt(((2-2)^2+(2-2)^2+(2-2^2))/3)=0)
研究生_命_起源 (標準差=sqrt(((2-3)^2+(2-1)^2+(2-2)^2)/3)=0.8165)
於是選擇“研究_生命_起源”這個片語。
4.Largest sum of degree of morphemic freedom of one-character words,其中degree of morphemic freedom可以用一個數學公式表達:log(frequency),即詞頻的自然對數(這裡log表示數學中的ln)。這個規則的意思是“計算片語中的所有單字詞詞頻的自然對數,然後將得到的值相加,取總和最大的片語”。比如:
設施_和服_務
設施_和_服務
這兩個片語中分別有“務”和“和”這兩個單字詞,假設“務”作為單字詞時候的頻率是5,“和”作為單字詞時候的頻率是10,對5和10取自然對數,然後取最大值者,所以取“和”字所在的片語,即“設施_和_服務”。
也許會問為什麼要對“詞頻”取自然對數呢?可以這樣理解,片語中單字詞詞頻總和可能一樣,但是實際的效果並不同,比如
A_BBB_C (單字詞詞頻,A:3, C:7)
DD_E_F (單字詞詞頻,E:5,F:5)
表示兩個片語,A、C、E、F表示不同的單字詞,如果不取自然對數,單純就詞頻來計算,那麼這兩個片語是一樣的(3+7=5+5),但實際上不同的詞頻範圍所表示的效果也不同,所以這裡取自然對數,以表區分(ln(3)+ln(7) < ln(5)+ln(5), 3.0445<3.2189)。
這個四個過濾規則中,如果使用simple的匹配方法,只能使用第一個規則過濾,如果使用complex的匹配方法,則四個規則都可以使用。實際使用中,一般都是使用complex的匹配方法+四個規則過濾。(simple的匹配方法實質上就是正向最大匹配,實際中很少只用這一個方法)
看到這裡也許對MMSEG的分詞方法有了一個大致的瞭解,正如文章開頭所述,它是一個“直觀”的分詞方法。它把一個句子“儘可能長(這裡的長,是指所切分的詞儘可能的長)”“儘可能均勻”的區切分,稍微想象一下,便感覺與中文的文法習慣比較相符。如果對分詞精度要求不是特別高,MMSEG是一個簡單、可行、快速的方法。
在具體實現一個分詞程式的時候,大概有以下幾點需要考慮:
1.“方法”決定“速度”。在基於詞典的分詞演算法中,詞典的結構對速度的影響是比較大的(詞典的結構一般決定了匹配的方法和速度)。一般的構造詞典的方法有很多,比如“首字索引+整詞二分”,將所有詞語的首字用某一Hash演算法索引,然後將詞體部分排序,使用二分尋找。這樣的方法可行,但不是最快的。對於這樣的詞典匹配,trie結構一般是首選。trie也有一些變種和實現方法,對於大量待用資料的匹配(比如詞典,一旦建立,便很少去修改裡面的內容,故稱之為“靜態”),一般採用“雙數組trie樹結構(Double array trie
tree)”,其相關資料網上有很多,可以Google或者Baidu。這裡提幾個可供參考的類庫:
Darts, http://chasen.org/~taku/software/darts/ , C++
Darts-clone, http://code.google.com/p/darts-clone/ , C++, 某些方面比Darts好一些
2.MMSEG的分詞效果與詞典關係較大(這裡是說詞典裡有哪些詞語,以及詞頻的精確度),尤其是詞典中單字詞的頻率。可以根據使用領域,專門定製詞典(比如電腦類詞庫,生活資訊類詞庫,旅遊類詞庫等),儘可能的細分詞典,這樣得到的分詞效果會好很多。同時也可以通過詞典達到一些特殊目的(地址分詞等)。關於詞庫,可以參考“搜狗”的細胞詞庫(http://pinyin.sogou.com/dict/)以及其提供的語料庫(可以根據其劃分好的語料庫,統計某一方面的詞頻,http://www.sogou.com/labs/resources.html)。
3.中文分詞的處理,與編碼關係很大(GBK, GB2312, BIG5, UTF-8),一般是以UTF-8為主,減少編碼的複雜性。
4.MMSEG演算法中取得所有的“chunk”是比較複雜的部分,根據不同的詞典結構會有不同的方法。如果使用“雙數組trie樹”結構,會簡單一些,可以用“遞迴”實現,也可以用“三層for迴圈實現”。出於效能考慮,一般是使用for迴圈。
這裡是一個基於MMSEG演算法的PHP中文分詞擴充 http://code.google.com/p/xsplit/ 並加入了一些常用函數