IK分詞處理過程 原始碼分析

2023-01-16 01:54:04 字數 3185 閱讀 8003

ik的整個分詞處理過程

首先,介紹一下ik的整個分詞處理過程:

1. lucene的分詞基類是analyzer,所以ik提供了analyzer的乙個實現類ikanalyzer。首先,我們要例項化乙個ikanalyzer,它有乙個構造方法接收乙個引數ismaxwordlength,這個引數是標識ik是否採用最大詞長分詞,還是採用最細粒度切分兩種分詞演算法。

實際兩種演算法的實現,最大詞長切分是對最細粒度切分的一種後續處理,是對最細粒度切分結果的過濾,選擇出最長的分詞結果。

2. ikanalyzer類重寫了analyzer的createcomponents方法,這個方法接收兩個引數,fieldname和輸入流reader,其中fieldname是lucene的屬性列,是對文字內容進行過分詞處理和建立索引之後,索引對應的乙個名稱,類似資料庫的列名。因為ik僅僅涉及分詞處理,所以對fieldname沒有進行任何處理,所以此處不做任何討論。

3. createcomponents方法在lucene對文字輸入流reader進行分詞處理時被呼叫,,該類繼承了lucene的tokenizer類。並重寫了incrementtoken方法,該方法的作用是處理文字輸入流生成token,也就是lucene的最小詞元term,在ik裡面叫做lexeme。

4. 在iktokenizer的構造方法裡面例項化了ik裡面最終要的分詞類iksegmenter,也稱為主分詞器。它的構造方法接收兩個引數,reader和ismaxwordlength。

5. iksegmenter的構造方法裡面,主要做了三個工作,建立上下文物件analyzecontext,載入詞典,建立子分詞器。

6. analyzecontext主要是儲存分詞結果集和記錄分詞處理的游標位置。

7. 詞典是作為乙個單例被建立的,主要有量詞詞典、主詞典和停詞詞典。詞典是被儲存在字典片段類dictsegment 這個字典核心類裡面的。

dictsegment有乙個靜態的儲存結構charmap,是公共詞典表,用來儲存所有漢字,key和value都是乙個中文漢字,目前ik裡面的charmap大概有7100多的鍵值對。另外,dictsegment還有兩個最重要的資料結構,是用來儲存字典樹的,乙個是dictsegment的陣列childrenarray,另乙個是key為單個漢字(每個詞條的第乙個漢字),value是dictsegment的hashmap childrenmap。這兩個資料結構二者取其一,用來儲存字典樹。

8. 子分詞器才是真正的分詞類,ik裡面有三個子分詞器,量詞分詞器,cjk分詞器(處理中文),停詞分詞器。主分詞器iksegmenter遍歷這三個分詞器對文字輸入流進行分詞處理。

9. iktokenizer的incrementtoken方法呼叫了iksegmenter的next方法,next的作用是獲得下乙個分詞結果。next在第一次被呼叫的時候,需要載入文字輸入流,並將其讀入buffer,此時便遍歷子分詞器,對buffer種的文字內容進行分詞處理,然後把分詞結果新增到analyzecontext的results陣列中。

下面,以cjksegmenter子分詞器為例介紹一下生成分詞結果集的流程:

1. iksegmenter遍歷segmenter時,呼叫cjksegmenter的analyze方法,該方法接收兩個引數,segmentbuf和analyzecontext,segmentbuf是乙個character陣列,檔案輸入流分解後得到,analyzecontext即ik的context類例項,用來記錄segmentbuf游標以及儲存切分後的詞元lexeme。

2. 進入analyze方法,首先判斷是否中文字元,然後判斷是否存在詞段佇列,舉例來說「中華人民共和國」,這個詞條,就會存在乙個詞段佇列,分別儲存「中華」、「中華人民」、「中華人民共和」、「中華人民共和國」,前面詞段依次是後面詞段的字首。這個詞段佇列也是在analyze方法中填充的。

當乙個詞條和字典中的詞匹配成功,並且也是字典中某個詞條的字首,則被加入佇列,當乙個詞條不再是某個詞條的字首,移除出佇列。

3. 如果詞段佇列裡面不存在詞段,把當前的character與字典中的詞匹配,建立乙個新的hit,如果字典種存在這個character,把hit新增進詞段佇列。如果詞段佇列裡面已經存在詞段,遍歷詞段佇列,判斷當前character是否可以以詞段佇列中的詞為字首,組成乙個字典中存在的詞,如果可以,則加入results中,如果不能匹配成詞,則將這個字首hit從佇列種移除,因為以後也不會匹配成詞了,故刪除。

4. 如此迴圈執行analyze方法,最終將文字輸入流切分成的詞元lexeme完全放入analyzecontext的results中。這時,再次呼叫iksegmenter類的next方法時,則會直接讀取results中已經切分好的詞元。

所以所有的切分工作都在第一次呼叫iksegmenter的next的時候完成。

5. ik 分詞演算法理解

根據作者官方說法 ik 分詞器採用「正向迭代最細粒度切分演算法」, 分析它的源**, 可以看到分詞工具類 ikqueryparser 起至關重要的作用, 它對搜尋關鍵詞採用從最大詞到最小詞層層迭代檢索方式切分,比如搜尋詞:「中華人民共和國成立了」, 首先到詞庫中檢索該搜尋詞中最大分割詞, 即分割為: 「中華人民共和國」和「成立了」, 然後對「中華人民共和國」切分為「中華人民」和「人民共和國」,以此類推。

最後,「中華人民共和國成立了」切分為:「中華人民 | 中華 | 華人 | 人民 | 人民共和國 | 共和國 | 共和 | 成立 | 立了」,當然, 該切分方式為預設的細粒度切分,若按最大詞長切分,結果為:「中華人民共和國 | 成立 | 立了」。

核心演算法**如下

boolean accept(lexeme _lexeme)else //如果所有的子branch不能接納,則由當前branch接納 if(!acceptedbychild) break;

case tonext : //把lexeme放入當前branch的相鄰分支 if( == null) break; }

return true; }

從**中可以了解到,作者採用了遞迴演算法(**中加粗的部分)切分搜尋詞。若詞存在子詞則遞迴該函式,繼續切分。

ik 分詞弱點、缺點分詞弱點弱點、

總體來說,ik 是乙個很不錯的中文分詞工具,但它自身也存在一些缺點,比如: a. 對歧義分詞還需要擴充套件、改進,比如:」湖北石首」 和 「蔣介石首次訪問」,

如果使用者搜尋」石首」會把」蔣介石首次訪問」也顯示出來。 b. 對英文單詞的搜尋還需改進,比如:

」ikanalyzer」或」uu **」,如果使用者輸入搜尋關鍵詞」ikanaly」或」u」則無法搜尋出結果。 c. 中關於詞典的配置,暫不支援萬用字元方式,這樣導致如果有大批詞典配置檔案時會很麻煩。

顧客糾紛的處理過程與方法

a 詳細傾聽顧客的抱怨。發生顧客投訴時,首先要仔細聆聽顧客的話語,讓他把心裡想說的話全部說完,這是最基本的態度。如果工作人員不能仔細聽完顧客的理論而中途打斷他的陳述,就可能引起顧客更大的反感。通常顧客只有在精神或物質上受到了某種程度的損害才會產生不滿情緒,因此在抱怨時很可能會不理智,甚至說出一些粗魯...

SUN 3510硬碟故障處理過程

更換硬碟處理過程 sun 3510硬碟故障,更換硬碟處理過程 sun 3510jbod在sun cluster環境更換硬碟 有一套3510 jbod v890 x2組成的sun cluster環境,當3510 jbod中有磁碟損壞時,不容易定位故障硬碟的槽位。3510 jbod設計時並未作為單獨的j...

不鏽鋼表面處理過程常見問題及預防措施

不鏽鋼具有獨特的強度 較高的耐磨性 優越的防腐效能及不易生鏽等優良的特性。故廣泛應用於化工行業,食品機械,機電行業,環保行業,家用電器行業及家庭裝潢,精飾行業,給予人們以華麗高貴的感覺。不鏽鋼的應用發展前景會越來越廣,但不鏽鋼的應用發展很大程度上決定它的表面處理技術發展程度。1不鏽鋼常用表面處理方法...