1. 程式人生 > >Lucene中文切分原理及其他常見切分演算法

Lucene中文切分原理及其他常見切分演算法

1、 什麼是中文分詞

學過英文的都知道,英文是以單詞為單位的,單詞與單詞之間以空格或者逗號句號隔開。而中文則以字為單位,字又組成詞,字和詞再組成句子。所以對於英文,我們可以簡單以空格判斷某個字串是否為一個單詞,比如I love China,love 和 China很容易被程式區分開來;但中文“我愛中國”就不 一樣了,電腦不知道“中國”是一個詞語還是“愛中”是一個詞語。把中文的句子切分成有意義的詞,就是中文分詞,也稱切詞。我愛中國,分詞的結果是:我 愛 中國。

目前中文分詞還是一個難題———對於需要上下文區別的詞以及新詞(人名、地名等)很難完美的區分。國際上將同樣存在分詞問題的韓國、日本和中國並稱為CJK(Chinese Japanese Korean),對於CJK這個代稱可能包含其他問題,分詞只是其中之一。

2、 中文分詞的實現

Lucene中對中文的處理是基於自動切分的單字切分,或者二元切分。除此之外,還有最大切分(包括向前、向後、以及前後相結合)、最少切分、全切分等等。
Lucene自帶了幾個分詞器WhitespaceAnalyzer, SimpleAnalyzer, StopAnalyzer, StandardAnalyzer, ChineseAnalyzer, CJKAnalyzer等。前面三個只適用於英文分詞,StandardAnalyzer對可最簡單地實現中文分詞,即二分法,每個字都作為一個詞,比如:”北京天安門” ==> “北京 京天 天安 安門”。這樣分出來雖然全面,但有很多缺點,比如,索引檔案過大,檢索時速度慢等。ChineseAnalyzer是按字分的,與StandardAnalyzer對中文的分詞沒有大的區別。 CJKAnalyzer是按兩字切分的, 比較武斷,並且會產生垃圾Token,影響索引大小。以上分詞器過於簡單,無法滿足現實的需求,所以我們需要實現自己的分詞演算法。
這樣,在查詢的時候,無論是查詢”北京” 還是查詢”天安門”,將查詢片語按同樣的規則進行切分:”北京”,”天安安門”,多個關鍵詞之間按與”and”的關係組合,同樣能夠正確地對映到相應的索引中。這種方式對於其他亞洲語言:韓文,日文都是通用的。

基於自動切分的最大優點是沒有詞表維護成本,實現簡單,缺點是索引效率低,但對於中小型應用來說,基於2元語法的切分還是夠用的。基於2元切分後的索引一般大小和原始檔差不多,而對於英文,索引檔案一般只有原檔案的30%-40%不同。
這裡寫圖片描述
目前比較大的搜尋引擎的語言分析演算法一般是基於以上2個機制的結合。關於中文的語言分析演算法,大家可以在Google查關鍵詞”wordsegment search”能找到更多相關的資料。

以下跟Lucene沒啥關係!!!

中文分詞技術分類

我們討論的分詞演算法可分為三大類:

1.基於詞典:基於字典、詞庫匹配的分詞方法;(字串匹配、機械分詞法)

2.基於統計:基於詞頻度統計的分詞方法;

3.基於規則:基於知識理解的分詞方法。

第一類方法應用詞典匹配、漢語詞法或其它漢語語言知識進行分詞,如:最大匹配法、最小分詞方法等。這類方法簡單、分詞效率較高,但漢語語言現象複雜豐富,詞典的完備性、規則的一致性等問題使其難以適應開放的大規模文字的分詞處理。第二類基於統計的分詞方法則基於字和詞的統計資訊,如把相鄰字間的資訊、詞頻及相應的共現資訊等應用於分詞,由於這些資訊是通過調查真實語料而取得的,因而基於統計的分詞方法具有較好的實用性。

下面簡要介紹幾種常用方法:

一、基於詞典分詞

  1. 逐詞遍歷法
    逐詞遍歷法將詞典中的所有詞按由長到短的順序在文章中逐字搜尋,直至文章結束。也就是說,不管文章有多短,詞典有多大,都要將詞典遍歷一遍。這種方法效率比較低,大一點的系統一般都不使用。

  2. 基於字典、詞庫匹配的分詞方法(機械分詞法
    它是按照一定的策略將待分析的漢字串與一個“充分大的”機 器詞典中的詞條進行配,若在詞典中找到某個字串,則匹配成功(識別出一個詞)。按照掃描方向的不同,串匹配分詞方法可以分為正向匹配和逆向匹配;按照不 同長度優先匹配的情況,可以分為最大(最長)匹配和最小(最短)匹配;按照是否與詞性標註過程相結合,又可以分為單純分詞方法和分詞與標註相結合的一體化 方法。常用的幾種機械分詞方法如下:

    1)正向最大匹配法(由左到右的方向);

    2)逆向最大匹配法(由右到左的方向);

    3)最少切分(使每一句中切出的詞數最小)。

這種分詞方法,首先要有一個詞庫。一個好的分詞器需要一個龐大優良的詞庫以及設計優秀的資料結構來快取該詞庫。下面使用一個名為MMAnalyzer的開源分詞器做簡單的分詞演示,然後大致講下怎麼樣基於lucene實現自己的分詞器。MMAnalyzer 簡介:

1、支援英文、數字、中文(簡體)混合分詞
2、常用的數量和人名的匹配
3、超過22萬詞的詞庫整理
4、實現正向最大匹配演算法
5、詞典的動態擴充套件
6、分詞效率: 第一次分詞需要1-2秒(讀取詞典),之後速度基本與Lucene自帶分詞器持平。記憶體消耗: 30M+

MMAnalyzer的分詞演算法如下:

1、讀取一個字,然後聯想,直到聯想到不能為止。如果當前可以構成詞,便返回一個Token。
2、如果當前不能構成詞語,便回溯到最近的可以構成詞語的節點,返回。
3、最差的情況就是返回第一個單字。
4、然後從返回結果的下一個字重新開始聯想。

public static void main(String[] args) throws IOException {
String text = “2008年前三季度,美國次貸危機升級,全球金融持續動盪,世界經濟增長全面放緩,全球經濟增長動力減弱,世界主要經濟體與新興市場正面臨巨大的外部衝擊。”;

Analyzer analyzer = new MMAnalyzer();
TokenStream stream = analyzer.tokenStream("xxx", new StringReader(text));
        while (true) {
            Token token = stream.next();
            if (token == null) break;
            System.out.print("[" + token.termText() + "] ");
        }
}

返回結果如下:
[2008] [年前] [三季度] [美國] [次] [貸] [危機] [升級] [全球] [金融] [持續] [動盪] [世界經濟] [增長] [全面] [放] [緩] [全球] [經濟] [增長] [動力] [減弱] [世界] [主要] [經濟] [體] [新興] [市場] [正] [面臨] [巨大] [外部] [衝擊]

MMAnalyzer分詞器有兩個建構函式MMAnalyzer()和MMAnalyzer(int n)。

MMAnalyzer():採用正向最大匹配的中文分詞演算法,相當於分詞粒度等於0。

MMAnalyzer(int n):引數為分詞粒度:當字數 >= n,且能成詞,該詞就被切分出來。

另外MMAnalyzer還有以下常用方法:

addDictionary(FileReader reader):增加一個新詞典,採用每行一個詞的讀取方式。

addWord(String newWord):往詞庫裡新增加一個新詞。

其中addWord方法測試了好像只會把新詞加入到快取了的詞庫中,並不會並永久性寫入詞典檔案中。如果需要寫入詞典檔案,可再按以下方法處理。

URL dictionaryPath = URLUtil.getResourceFileUrl("resources/dictionary.txt");
if(dictionaryPath != null){
    // new FileWriter(String, boolean) 第二個引數true表示追加檔案到尾部
    BufferedWriter bw = new BufferedWriter(new FileWriter(dictionaryPath.getPath(), true));  
    bw.write(searchStr);//追加檔案內容  
    bw.newLine();
    bw.close();
}

當然也可自己實現分詞器,實現過程很簡單,首先實現一個Tokenizer(需要繼承lucene包裡的Tokenizer抽象類),覆寫裡面的next()方法,這也是lucene分詞器實現的最關鍵的地方。然後再實現一個Analyzer(需要繼承lucene包裡的Analyzer抽象類),將上面實現的Tokenizer指定給該Analyzer。

(1)最大正向匹配法(MM, MaximumMatching Method)

通常簡稱為MM法。其基本思想為:假定分詞詞典中的最長詞有i個漢字字元,則用被處理文件的當前字串中的前i個字作為匹配欄位,查詢字典。若字典中存在這樣的一個i字詞,則匹配成功,匹配欄位被作為一個詞切分出來。如果詞典中找不到這樣的一個i字詞,則匹配失敗,將匹配欄位中的最後一個字去掉,對剩下的字串重新進行匹配處理…… 如此進行下去,直到匹配成功,即切分出一個詞或剩餘字串的長度為零為止。這樣就完成了一輪匹配,然後取下一個i字字串進行匹配處理,直到文件被掃描完為止。

其演算法描述如下:

step1: 從左向右取待切分漢語句的m個字元作為匹配欄位,m為大機器詞典中最長詞條個數。

step2: 查詢大機器詞典並進行匹配。若匹配成功,則將這個匹配欄位作為一個詞切分出來。若匹配不成功,則將這個匹配欄位的最後一個字去掉,剩下的字串作為新的匹配欄位,進行再次匹配,重複以上過程,直到切分出所有詞為止。

(2)逆向最大匹配法(ReverseMaximum Matching Method)

通常簡稱為RMM法。RMM法的基本原理與MM法相同 ,不同的是分詞切分的方向與MM法相反,而且使用的分詞辭典也不同。逆向最大匹配法從被處理文件的末端開始匹配掃描,每次取最末端的2i個字元(i字字串)作為匹配欄位,若匹配失敗,則去掉匹配欄位最前面的一個字,繼續匹配。相應地,它使用的分詞詞典是逆序詞典,其中的每個詞條都將按逆序方式存放。在實際處理時,先將文件進行倒排處理,生成逆序文件。然後,根據逆序詞典,對逆序文件用正向最大匹配法處理即可。

由於漢語中偏正結構較多,若從後向前匹配,可以適當提高精確度。所以,逆向最大匹配法比正向最大匹配法的誤差要小。統計結果表明 ,單純使用正向最大匹配的錯誤率為 1/16 9,單純使用逆向最大匹配的錯誤率為 1/245。例如切分欄位“碩士研究生產”,正向最大匹配法的結果會是“碩士研究生 / 產”,而逆向最大匹配法利用逆向掃描,可得到正確的分詞結果“碩士 / 研究 / 生產”。

當然,最大匹配演算法是一種基於分詞詞典的機械分詞法,不能根據文件上下文的語義特徵來切分詞語,對詞典的依賴性較大,所以在實際使用時,難免會造成一些分詞錯誤,為了提高系統分詞的準確度,可以採用正向最大匹配法和逆向最大匹配法相結合的分詞方案(見“雙向匹配法”)

(3)最少切分法

使每一句中切出的詞數最小。

(4)雙向匹配法

將正向最大匹配法與逆向最大匹配法組合。先根據標點對文件進行粗切分,把文件分解成若干個句子,然後再對這些句子用正向最大匹配法和逆向最大匹配法進行掃描切分。如果兩種分詞方法得到的匹配結果相同,則認為分詞正確,否則,按最小集處理。

二、 全切分、基於詞的頻度統計(無字典分詞)

基於詞的頻度統計的分詞方法是一種全切分方法。在討論這個方法之前我們先要明白有關全切分的相關內容。

(1) 全切分

全切分要求獲得輸入序列的所有可接受的切分形式,而部分切分只取得一種或幾種可接受的切分形式,由於部分切分忽略了可能的其他切分形式,所以建立在部分切分基礎上的分詞方法不管採取何種歧義糾正策略,都可能會遺漏正確的切分,造成分詞錯誤或失敗。而建立在全切分基礎上的分詞方法,由於全切分取得了所有可能的切分形式,因而從根本上避免了可能切分形式的遺漏,克服了部分切分方法的缺陷。

全切分演算法能取得所有可能的切分形式,它的句子覆蓋率和分詞覆蓋率均為100%,但全切分分詞並沒有在文字處理中廣泛地採用,原因有以下幾點:

全切分演算法只是能獲得正確分詞的前提,因為全切分不具有歧義檢測功能,最終分詞結果的正確性和完全性依賴於獨立的歧義處理方法,如果評測有誤,也會造成錯誤的結果。

全切分的切分結果個數隨句子長度的增長呈指數增長,一方面將導致龐大的無用資料充斥於儲存資料庫;另一方面當句長達到一定長度後,由於切分形式過多,造成分詞效率嚴重下降。

(2) 基於詞的頻度統計的分詞方法

主要思想:上下文中,相鄰的字同時出現的次數越多,就越可能構成一個詞。因此字與字相鄰出現的概率或頻率能較好的反映詞的可信度。

主要統計模型為:N元文法模型(N-gram)、隱馬爾科夫模型(Hidden Markov Model, HMM)。

HMM馬爾科夫假設:一個詞的出現僅僅依賴於它前面出現的有限的一個或者幾個詞。如果一個詞的出現僅依賴於它前面出現的一個詞,那麼我們就稱之為bigram。即P(T) = P(W1W2W3…Wn) = P(W1)P(W2|W1)P(W3|W1W2)…P(Wn|W1W2…Wn-1) ≈ P(W1)P(W2|W1)P(W3|W2)…P(Wn|Wn-1)

如果一個詞的出現僅依賴於它前面出現的兩個詞,那麼我們就稱之為trigram。

在實踐中用的最多的就是bigram和trigram了,而且效果很不錯。高於四元的用的很少,因為訓練它需要更龐大的語料,而且資料稀疏嚴重,時間複雜度高,精度卻提高的不多。

設w1,w2,w3,…,wn是長度為n的字串,規定任意詞wi只與它的前兩個相關,得到三元概率模型。

以此類推,N元模型就是假設當前詞的出現概率只同它前面的N-1個詞有關。

這是一種全切分方法。它不依靠詞典,而是將文章中任意兩個字同時出現的頻率進行統計,次數越高的就可能是一個詞。它首先切分出與詞表匹配的所有可能的詞,運用統計語言模型和決策演算法決定最優的切分結果。
它的優點在於可以發現所有的切分歧義並且容易將新詞提取出來。

三、基於統計分詞(無字典分詞)

該方法主要基於句法、語法分析,並結合語義分析,通過對上下文內容所提供資訊的分析對詞進行定界,它通常包括三個部分:分詞子系統、句法語義子系統、總控部分。在總控部分的協調下,分詞子系統可以獲得有關詞、句子等的句法和語義資訊來對分詞歧義進行判斷。這類方法試圖讓機器具有人類的理解能力,需要使用大量的語言知識和資訊。由於漢語語言知識的籠統、複雜性,難以將各種語言資訊組織成機器可直接讀取的形式。因此目前基於知識的分詞系統還處在試驗階段。

四、並行分詞法

這種分詞方法藉助於一個含有分詞詞庫的管道進行 ,比較匹配過程是分步進行的 ,每一步可以對進入管道中的詞同時與詞庫中相應的詞進行比較 ,由於同時有多個詞進行比較匹配 ,因而分詞速度可以大幅度提高。這種方法涉及到多級內碼理論和管道的詞典資料結構。(詳細演算法可以參考吳勝遠的《並行分詞方法的研究》)