日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IK分词器原理

發布時間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IK分词器原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

IKAnalyzer是一個開源的,基于Java語言開發的輕量級的中文分詞語言包,它是以Lucene為應用主體,結合詞典分詞和文法分析算法的中文詞組組件。從3.0版本開始,IK發展為面向java的公用分詞組件,獨立Lucene項目,同時提供了對Lucene的默認優化實現。

以下這篇博客是我在通讀IK分詞代碼后對IK分詞的理解,如果有什么地方出現紕漏請大家指正。

回到最初

如果讓我自己在看IK分詞之前自己寫一個分詞器,那我會怎么做? 如果我會想到的是:比如對"周末有歐冠決賽"做分詞處理,人為的分詞是:“周末|有|歐冠|決賽”,那為什么會出現這樣的分詞效果,首先必須有一個詞典,詞典中可以標記出“周末”、“歐冠”、“決賽”這些詞,因為分詞器并不具備人工智能的能力,所以它所做的就是把文本和詞典中的詞進行比較,按照詞典中已有的詞進行匹配,匹配完成之后即達到了分詞的效果。

現在雖然找不到第一個寫分詞的人是如何設計分詞的算法的,但是我想是差不多的。

K分詞其實也是這么來做的。將一段文字進行IK分詞處理一般經過:詞典加載、預處理、分詞器分詞、歧義處理、善后結尾 五個部分。

詞典加載:

主程序需要加載詞典。IK分詞的詞典主要包括 main2012.dic(主詞典)、quantifier.dic(量詞)、stopword.dic(停用詞)、ext.dic(擴展詞,可選)四個字典。字典的結構使用字典樹進行存儲。關于字典樹的具體介紹可以參考:?http://www.cnblogs.com/rush/archive/2012/12/30/2839996.html

預處理:

預處理是在加載文檔的時候做的,其實預處理部分只是做兩件事情:

  • 識別出每個字符的字符類型
  • 字符轉化:全角轉半角,大寫轉小寫

字符類型是在分詞的時候需要,不同的分詞器會根據不同的字符類型做特別處理。而字符轉化則是要求文本字符與詞典中的字符想匹配,比如對于12288、32這兩個字符,分別是漢字和英文的空格,如果一篇文本中包含了漢字包含了這兩個字符,那么分詞器在分詞的時候需要判斷兩個都是空格。同理在英文大小寫上也存在類似的問題。預處理主要在org.wltea.analyzer.core.CharacterUtil.java類中實現。

package org.wltea.analyzer.core;import java.lang.Character.UnicodeBlock;class CharacterUtil {public static final int CHAR_USELESS = 0;public static final int CHAR_ARABIC = 1;public static final int CHAR_ENGLISH = 2;public static final int CHAR_CHINESE = 4;public static final int CHAR_OTHER_CJK = 8;CharacterUtil() {}static int identifyCharType(char input) {if(input >= 48 && input <= 57) {//數字0-9return 1;} else if(input >= 97 && input <= 122 || input >= 65 && input <= 90) {//a-z,A-Zreturn 2;} else {UnicodeBlock ub = UnicodeBlock.of(input);return ub != UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS && ub != UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS && ub != UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A?(ub != UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS && ub != UnicodeBlock.HANGUL_SYLLABLES && ub != UnicodeBlock.HANGUL_JAMO && ub != UnicodeBlock.HANGUL_COMPATIBILITY_JAMO && ub != UnicodeBlock.HIRAGANA && ub != UnicodeBlock.KATAKANA && ub != UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS?0:8):4;}}static char regularize(char input, boolean lowercase) {if(input == 12288) {//全角空格input = 32;//半角空格} else if(input > '\uff00' && input < '⦅') {input -= 'ﻠ';} else if(input >= 65 && input <= 90 && lowercase) {input = (char)(input + 32);}return input;} }

分詞器分詞:

IK分詞包括三個分詞器:LetterSegmenter(字符分詞器),CN_QuantifierSegmenter(中文數量詞分詞器),CJKSegmenter(中日韓文分詞器)。分詞器分詞有兩種模式,即:smart模式和非smart模式,非smart模式可以認為是最小力度的分詞,smart模式則反之。

具體的實例:張三說的確實在理smart模式的下分詞結果為: 張三 | 說的 | 確實 | 在理而非smart模式下的分詞結果為:張三 || 說的 | 的確 | 的 | 確實 | 實在 | 在理

IK分詞使用了”正向迭代最細粒度切分算法“,簡單說來就是: Segmenter會逐字識別詞元,設輸入”中華人民共和國“并且”中“單個字也是字典里的一個詞,那么過程是這樣的:”中“是詞元也是前綴(因為有各種中開頭的詞),加入詞元”中“;繼續下一個詞”華“,由于中是前綴,那么可以識別出”中華“,同時”中華“也是前綴因此加入”中華“詞元,并把其作為前綴繼續;接下來繼續發現“華人”是詞元,“中華人”是前綴,以此類推……

關于IK分詞的三個分詞器,基本上邏輯是一樣的,如果有興趣了解的話,重點看一下CJKSegmenter就好了。

歧義處理:

非smart模式所做的就是將能夠分出來的詞全部輸出;smart模式下,IK分詞器則會根據內在方法輸出一個認為最合理的分詞結果,這就涉及到了歧義判斷。

以“張三說的確實在理”為依據,分詞的結果為:

張三 | 三 | 說的 | 的確 || 確實 | 實在 | 在理

在判斷歧義的時候首先要看詞與詞之間是否用沖突,“張三”與“三”相沖突,“說的”,“的確”,“的”,“確實”,“實在”,“在理”相沖突,所以分成兩部分進行歧義判斷。我們以后一種為例:“說的”,“的確”,“的”,“確實”,“實在”, 按照默認的生成的一組結果為“說的|確實|在理”,與這個結果相沖突的詞是“的確”、“的”、“實在”。回滾生成的結果,將這三個詞倒敘逐一放入到生成的結果中,生成可選分詞方案是:

"實在"放入后,分詞方案為:"說的|實在|"; "的"放入后,生成的分詞方案為:"的|確實|在理"; "的確"放入后,生成的分詞方案為:"的確|實在";

這樣加上原有的一共四種可選的分詞方案,從中選取最優的方案。選取的原則順序如下:

1、比較有效文本長度 2、比較詞元個數,越少越好 3、路徑跨度越大越好 4、最后一個詞元的位置越靠后約好(根據統計學結論,逆向切分概率高于正向切分,因此位置越靠后的優先) 5、詞長越平均越好 6、詞元位置權重比較

總體說來就是: 主要使用的就是貪心算法獲取局部最優解,然后繼續處理來獲取最終的結果。

善后結尾:

  • 處理遺漏中文字符,遍歷輸入文本,把詞之間每個中文字符也作為詞輸出,雖然詞典中沒有這樣的詞。
  • 處理數量詞,如果中文量詞剛好出現在中文數詞的后面,或者中文量詞剛好出現在阿拉伯數字的后面,則把數詞和量詞合并。比如"九寸""十二畝"。

其它

Ik的排序方法特別粗略,如果比較發現path1的詞個數,比path2的個數少,就直接判定path1更優。其實這樣的規則,并未完整的參考各個分出來的詞的實際情況,我們可能想加入每個詞經統計出現的頻率等信息,做更全面的打分,這樣IK原有的比較方法就是不可行的。

總結

以上是生活随笔為你收集整理的IK分词器原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。