分享

IK的整個分詞處理過程

 梧桐话 2013-02-17

IK的整個分詞處理過程

時間:2012-06-26 16:55來源:Internet 作者:Internet 點擊: 573 次
IK的整個分詞處理過程 首先,介紹一下IK的整個分詞處理過程: 1. Lucene的分詞基類是Analyzer,所以IK提供了Analyzer的一個實現類IKAnalyzer。首先,我們要實例化一

IK的整個分詞處理過程

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

1. Lucene的分詞基類是Analyzer,所以IK提供了Analyzer的一個實現類IKAnalyzer。首先,我們要實例化一個IKAnalyzer,它有一個構造方法接收一個参數isMaxWordLength,這個参數是標識IK是否采用最大詞長分詞,還是采用最細粒度切分兩種分詞算法。實際兩種算法的實現,最大詞長切分是對最細粒度切分的一種後續處理,是對最細粒度切分結果的過滤,選擇出最長的分詞結果。

 

2. IKAnalyzer類重寫了Analyzer的tokenStream方法,這個方法接收兩個参數,field name和輸入流reader,其中filed name是Lucene的屬性列,是對文本內容進行過分詞處理和創建索引之後,索引對應的一個名稱,類似數據庫的列名。因为IK僅僅涉及分詞處理,所以對field name沒有進行任何處理,所以此處不做任何討論。

 

3. tokenStream方法在Lucene對文本輸入流reader進行分詞處理時被調用,在IKAnalyzer的tokenStream方法裏面僅僅實例化了一個IKTokenizer類,該類繼承了Lucene的Tokenizer類。並重寫了incrementToken方法,該方法的作用是處理文本輸入流生成token,也就是Lucene的最小詞元term,在IK裏面叫做Lexeme。

 

4. 在IKtokenizer的構造方法裏面實例化了IK裏面最終要的分詞類IKSegmentation,也稱为主分詞器。它的構造方法接收兩個参數,reader和isMaxWordLength。

 

5. IKsegmentation的構造方法裏面,主要做了三個工作,創建上下文對象Context,加載詞典,創建子分詞器。

 

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

 

7. 詞典是作为一個單例被創建的,主要有量詞詞典、主詞典和停詞詞典。詞典是被存儲在字典片段類DictSegment 這個字典核心類裏面的。DictSegment有一個靜態的存儲結構charMap,是公共詞典表,用來存儲所有漢字,key和value都是一個中文漢字,目前IK裏面的charMap大概有7100多的鍵值對。另外,DictSegment還有兩個最重要的數據結構,是用來存儲字典樹的,一個是DictSegment的數組childrenArray,另一個是key为單個漢字(每個詞條的第一個漢字),value是DictSegment的HashMap childrenMap。這兩個數據結構二者取其一,用來存儲字典樹。

 

8. 子分詞器才是真正的分詞類,IK裏面有三個子分詞器,量詞分詞器,CJK分詞器(處理中文),停詞分詞器。主分詞器IKSegmentation遍曆這三個分詞器對文本輸入流進行分詞處理。

 

9. IKTokenizer的incrementToken方法調用了IKSegmentation的next方法,next的作用是獲得下一個分詞結果。next在第一次被調用的時候,需要加載文本輸入流,並將其讀入buffer,此時便遍曆子分詞器,對buffer種的文本內容進行分詞處理,然後把分詞結果添加到context的lexemeSet中。


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

1.  IKSegmentation遍曆Segmenter時,調用CJKSegmenter的nextLexeme方法,該方法接收兩個参數,segmentBuf和context,segmentBuf是一個Character數組,文件輸入流分解後得到,context即IK的Context類實例,用來記錄segmentBuf遊標以及存儲切分後的詞元lexeme。

 

2.  進入nextLexeme方法,首先判斷是否中文字符,然後判斷是否存在詞段隊列,舉例來說“中華人民共和國”,這個詞條,就會存在一個詞段隊列,分別存儲“中華”、“中華人民”、“中華人民共和”、“中華人民共和國”,前面詞段依次是後面詞段的前綴。這個詞段隊列也是在nextLexeme方法中填充的。當一個詞條和字典中的詞匹配成功,並且也是字典中某個詞條的前綴,則被加入隊列,當一個詞條不再是某個詞條的前綴,移除出隊列。

 

3. 如果詞段隊列裏面不存在詞段,把當前的Character與字典中的詞匹配,創建一個新的hit,如果字典種存在這個Character,把hit添加進詞段隊列。如果詞段隊列裏面已經存在詞段,遍曆詞段隊列,判斷當前Character是否可以以詞段隊列中的詞为前綴,組成一個字典中存在的詞,如果可以,則加入lexemeSet中,如果不能匹配成詞,則將這個前綴hit從隊列種移除,因为以後也不會匹配成詞了,故刪除。

 

4. 如此循環執行nextLuxeme方法,最終將文本輸入流切分成的詞元lexeme完全放入context的lexemeSet中。這時,再次調用IKSegmentation類的next方法時,則會直接讀取lexemeSet中已經切分好的詞元。所以所有的切分工作都在第一次調用IKSegmentation的next的時候完成。

 

 

5. IK 分詞算法理解

根據作者官方說法 IK 分詞器采用“正向迭代最細粒度切分算法”, 分析它 的源代碼, 可以看到分詞工具類 IKQueryParser 起至關重要的作用, 它對搜索 關鍵詞采用從最大詞到最小詞層層迭代檢索方式切分,比如搜索詞:“中華人 民共和國成立了”, 首先到詞庫中檢索該搜索詞中最大分割詞, 即分割为: “中 華人民共和國”和“成立了”, 然後對“中華人民共和國”切分为“中華人民”和“人 民共和國”,以此類推。最後,“中華人民共和國成立了”切分为:“中華人民 | 中華 | 華人 | 人民 | 人民共和國 | 共和國 | 共和 | 成立 | 立了”,當然, 該切分方式为默認的細粒度切分,若按最大詞長切分,結果为:“中華人民共 和國 | 成立 | 立了”。核心算法代碼如下


boolean accept(Lexeme _lexeme){


/* * 檢查新的lexeme 對當前的branch 的可接受類型 * acceptType : REFUSED 不能接受


* acceptType : ACCEPTED 接受 * acceptType : TONEXT 由相鄰分支接受


*/ int acceptType = checkAccept(_lexeme); switch(acceptType){ case REFUSED: // REFUSE 情況 return false;


case ACCEPTED : if(acceptedBranchs == null){ //當前branch沒有子branch,則添加到當前branch下 acceptedBranchs = new ArrayList<TokenBranch>(2); acceptedBranchs.add(new TokenBranch(_lexeme)); }else{ boolean acceptedByChild = false; //當前branch擁有子branch,則優先由子branch接納 for(TokenBranch childBranch : acceptedBranchs){ acceptedByChild = childBranch.accept(_lexeme) || acceptedByChild; } //如果所有的子branch不能接納,則由當前branch接納 if(!acceptedByChild){ acceptedBranchs.add(new TokenBranch(_lexeme)); } } //設置branch的最大右邊界 if(_lexeme.getEndPosition() > this.rightBorder){ this.rightBorder = _lexeme.getEndPosition(); } break;


case TONEXT : //把lexeme放入當前branch的相鄰分支 if(this.nextBranch == null){ //如果還沒有相鄰分支,則建立一個不交叠的分支 this.nextBranch = new TokenBranch(null); } this.nextBranch.accept(_lexeme); break; }


return true; }


從代碼中可以了解到,作者采用了遞歸算法(代碼中加粗的部分)切分 搜索詞。若詞存在子詞則遞歸該函數,繼續切分。


IK 分詞弱點、缺點 分詞弱點 弱點、

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


如果用戶搜索”石首”會把”蔣介石首次訪問”也顯示出來。 b. 對英文單詞的搜索還需改進,比如:”IKAnalyzer”或”UU 音樂”,如果用戶輸 入搜索關鍵詞”IKAnaly”或”U”則無法搜索出結果。 c. IKAnalyzer.cfg.xml 中關於詞典的配置,暫不支持通配符方式,這样導致如果 有大批詞典配置文件時會很麻煩。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多