Lucene5學習之使用MMSeg4j分詞器
MMSeg4j是一款中文分詞器,詳細介紹如下:
1、mmseg4j 用 Chih-Hao Tsai 的 MMSeg 演算法(http://technology.chtsai.org/mmseg/ )實現的中文分詞器,並實現 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用。
2、MMSeg 演算法有兩種分詞方法:Simple和Complex,都是基於正向最大匹配。Complex 加了四個規則過慮。官方說:詞語的正確識別率達到了 98.41%。mmseg4j 已經實現了這兩種分詞演算法。
1.5版的分詞速度simple演算法是 1100kb/s左右、complex演算法是 700kb/s左右,(測試機:AMD athlon 64 2800+ 1G記憶體 xp)。
1.6版在complex基礎上實現了最多分詞(max-word)。“很好聽” -> "很好|好聽"; “中華人民共和國” -> "中華|華人|共和|國"; “中國人民銀行” -> "中國|人民|銀行"。
1.7-beta 版, 目前 complex 1200kb/s左右, simple 1900kb/s左右, 但記憶體開銷了50M左右. 上幾個版都是在10M左右
可惜的是,MMSeg4j最新版1.9.1不支援Lucene5.0,於是我就修改了它的原始碼將它升級咯,使其支援Lucene5.x,至於我是怎樣修改,這裡就不一一說明的,我把我修改過的MMSeg4j最新原始碼上傳到了我的百度網盤,現分享給你們咯:
下面是一個MMSeg4j分詞器簡單使用示例:
Java程式碼- package com.chenlb.mmseg4j.analysis;
- import java.io.IOException;
- import org.apache.lucene.analysis.Analyzer;
- import org.apache.lucene.analysis.TokenStream;
- import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
- import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
- import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
- import org.junit.Assert;
- import org.junit.Before;
- import org.junit.Ignore;
- import org.junit.Test;
- /**
- * MMSegAnalyzer分詞器測試
- * @author Lanxiaowei
- *
- */
- public class MMSegAnalyzerTest {
- String txt = "";
- @Before
- public void before() throws Exception {
- txt = "京華時報2009年1月23日報道 昨天,受一股來自中西伯利亞的強冷空氣影響,本市出現大風降溫天氣,白天最高氣溫只有零下7攝氏度,同時伴有6到7級的偏北風。";
- txt = "2009年ゥスぁま是中 ABcc國абвгαβγδ首次,我的ⅠⅡⅢ在chenёlbēū全國ㄦ範圍ㄚㄞㄢ內①ē②㈠㈩⒈⒑發行地方政府債券,";
- txt = "大S小3U盤浙BU盤T恤T臺A股牛B";
- }
- @Test
- //@Ignore
- public void testSimple() throws IOException {
- Analyzer analyzer = new SimpleAnalyzer();
- displayTokens(analyzer,txt);
- }
- @Test
- @Ignore
- public void testComplex() throws IOException {
- //txt = "1999年12345日報道了一條新聞,2000年中法國足球比賽";
- /*txt = "第一卷 雲天落日圓 第一節 偷歡不成倒大黴";
- txt = "中國人民銀行";
- txt = "我們";
- txt = "工信處女幹事每月經過下屬科室都要親口交代24口交換機等技術性器件的安裝工作";*/
- //ComplexSeg.setShowChunk(true);
- Analyzer analyzer = new ComplexAnalyzer();
- displayTokens(analyzer,txt);
- }
- @Test
- @Ignore
- public void testMaxWord() throws IOException {
- //txt = "1999年12345日報道了一條新聞,2000年中法國足球比賽";
- //txt = "第一卷 雲天落日圓 第一節 偷歡不成倒大黴";
- //txt = "中國人民銀行";
- //txt = "下一個 為什麼";
- //txt = "我們家門前的大水溝很難過";
- //ComplexSeg.setShowChunk(true);
- Analyzer analyzer = new MaxWordAnalyzer();
- displayTokens(analyzer,txt);
- }
- /*@Test
- public void testCutLeeterDigitFilter() {
- String myTxt = "mb991ch cq40-519tx mmseg4j ";
- List<String> words = toWords(myTxt, new MMSegAnalyzer("") {
- @Override
- protected TokenStreamComponents createComponents(String text) {
- Reader reader = new BufferedReader(new StringReader(text));
- Tokenizer t = new MMSegTokenizer(newSeg(), reader);
- return new TokenStreamComponents(t, new CutLetterDigitFilter(t));
- }
- });
- //Assert.assertArrayEquals("CutLeeterDigitFilter fail", words.toArray(new String[words.size()]), "mb 991 ch cq 40 519 tx mmseg 4 j".split(" "));
- for(String word : words) {
- System.out.println(word);
- }
- }*/
- public static void displayTokens(Analyzer analyzer,String text) throws IOException {
- TokenStream tokenStream = analyzer.tokenStream("text", text);
- displayTokens(tokenStream);
- }
- public static void displayTokens(TokenStream tokenStream) throws IOException {
- OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
- PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class);
- CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
- TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class);
- tokenStream.reset();
- int position = 0;
- while (tokenStream.incrementToken()) {
- int increment = positionIncrementAttribute.getPositionIncrement();
- if(increment > 0) {
- position = position + increment;
- System.out.print(position + ":");
- }
- int startOffset = offsetAttribute.startOffset();
- int endOffset = offsetAttribute.endOffset();
- String term = charTermAttribute.toString();
- System.out.println("[" + term + "]" + ":(" + startOffset + "-->" + endOffset + "):" + typeAttribute.type());
- }
- }
- /**
- * 斷言分詞結果
- * @param analyzer
- * @param text 源字串
- * @param expecteds 期望分詞後結果
- * @throws IOException
- */
- public static void assertAnalyzerTo(Analyzer analyzer,String text,String[] expecteds) throws IOException {
- TokenStream tokenStream = analyzer.tokenStream("text", text);
- CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
- for(String expected : expecteds) {
- Assert.assertTrue(tokenStream.incrementToken());
- Assert.assertEquals(expected, charTermAttribute.toString());
- }
- Assert.assertFalse(tokenStream.incrementToken());
- tokenStream.close();
- }
- }
mmseg4j分詞器有3個字典檔案,如圖:
chars.dic是漢字字典檔案,裡面有12638個漢字
units.dic裡是中文單位詞語,如小時,分鐘,米,釐米等等,具體自己開啟看看就明白了
words.dic就是使用者自定義字典檔案,比如:麼麼噠,T恤,牛B等這些詞,放在這個字典檔案裡,分詞器就能把它當作一個詞
我們在使用mmseg4j分詞器時,是這樣用的:
Java程式碼- Analyzer analyzer = new SimpleAnalyzer();
檢視SimpleAnalyzer的建構函式,
Java程式碼- public SimpleAnalyzer() {
- super();
- }
呼叫的是父類MMSegAnalyzer的無參建構函式,接著檢視MMSegAnalyzer類的無參建構函式:
Java程式碼- public MMSegAnalyzer() {
- dic = Dictionary.getInstance();
- }
你會發現是通過Dictionary.getInstance()單例項模式去載入字典檔案的,接著檢視getInstance方法,
這裡的程式碼註釋寫的很清楚,告訴了我們字典檔案的載入邏輯。
File path = getDefalutPath();用來獲取預設的字典檔案路徑,
然後根據字典檔案路徑呼叫getInstance(path)方法去載入字典檔案,接著檢視該方法,
先從快取dics裡去字典檔案,如果快取裡沒有找到,則才會根據字典檔案路徑去載入,然後把載入到的字典檔案放入快取dics即dics.put(),
接著看看Dictionary字典是如何初始化的,檢視Dictionary的建構函式原始碼:
你會發現內部實際是通過呼叫init(path);方法進行字典初始化的,繼續查閱init方法,
內部又是呼叫的reload方法載入的字典,繼續跟蹤至reload方法,
內部通過loadDic去載入words和chars兩個字典檔案,通過loadUnit方法去載入units字典檔案,wordsLastTime是用來存放每個字典檔案的最後一次修改時間,引入這個map的目的是為了實現字典檔案重新載入,通過字典檔案的最後一次修改時間來判定檔案是否修改過,如果這個map裡不存在某字典檔案的最後一次修改時間,則表明該字典檔案是新加入的,需要重新載入至記憶體,這是loadDic方法的原始碼:
- private Map<Character, CharNode> loadDic(File wordsPath) throws IOException {
- InputStream charsIn = null;
- File charsFile = new File(wordsPath, "chars.dic");
- if(charsFile.exists()) {
- charsIn = new FileInputStream(charsFile);
- addLastTime(charsFile); //chars.dic 也檢測是否變更
- } else { //從 jar 里加載
- charsIn = this.getClass().getResourceAsStream("/data/chars.dic");
- charsFile = new File(this.getClass().getResource("/data/chars.dic").getFile()); //only for log
- }
- final Map<Character, CharNode> dic = new HashMap<Character, CharNode>();
- int lineNum = 0;
- long s = now();
- long ss = s;
- lineNum = load(charsIn, new FileLoading() { //單個字的
- public void row(String line, int n) {
- if(line.length() < 1) {
- return;
- }
- String[] w = line.split(" ");
- CharNode cn = new CharNode();
- switch(w.length) {
- case 2:
- try {
- cn.setFreq((int)(Math.log(Integer.parseInt(w[1]))*100));//字頻計算出自由度
- } catch(NumberFormatException e) {
- //eat...
- }
- case 1:
- dic.put(w[0].charAt(0), cn);
- }
- }
- });
- log.info("chars loaded time="+(now()-s)+"ms, line="+lineNum+", on file="+charsFile);
- //try load words.dic in jar
- InputStream wordsDicIn = this.getClass().getResourceAsStream("/data/words.dic");
- if(wordsDicIn != null) {
- File wordsDic = new File(this.getClass().getResource("/data/words.dic").getFile());
- loadWord(wordsDicIn, dic, wordsDic);
- }
- File[] words = listWordsFiles(); //只要 wordsXXX.dic的檔案
- if(words != null) { //擴充套件詞庫目錄
- for(File wordsFile : words) {
- loadWord(new FileInputStream(wordsFile), dic, wordsFile);
- addLastTime(wordsFile); //用於檢測是否修改
- }
- }
-
相關推薦
Lucene5學習之使用MMSeg4j分詞器
MMSeg4j是一款中文分詞器,詳細介紹如下: 1、mmseg4j 用 Chih-Hao Tsai 的 MMSeg 演算法(http://technology.chtsai.org/mmseg/ )實現的中文分詞器,並實現 lucene 的 analy
13.solr學習速成之IK分詞器
更新 api 一個 廣泛 針對 -i 處理器 多個 -1 IKAnalyzer簡介 IKAnalyzer是一個開源的,基於java語言開發的輕量級的中文分詞工具包。 IKAnalyzer特性 a. 算法采用“正向叠代最細粒度切分算法”,支持細粒度和最大詞
Elasticsearch之IK分詞器 java api
一、Elasticsearch分詞 在elasticsearch自帶的分詞器中,對中文分詞是支援的,只是所有的分詞都是按照單字進行分詞的,例如所帶的標準的分詞器standard分詞器,可以按照如下的方式查詢是如何進行分詞的 http://localhost:9200/iktest/_anal
Elasticsearch筆記六之中文分詞器及自定義分詞器
中文分詞器 在lunix下執行下列命令,可以看到本來應該按照中文”北京大學”來查詢結果es將其分拆為”北”,”京”,”大”,”學”四個漢字,這顯然不符合我的預期。這是因為Es預設的是英文分詞器我需要為其配置中文分詞器。 curlHTTP://192.168.79.131:9
Elasticsearch之中文分詞器
Elasticsearch的中文分詞器 1、單字分詞: 如:“我們是中國人” 效果:“我”“們”“是”“中”“國”“人” 2、二分法分詞:按兩個字進行切分。 如:“我們是中國人”,效果:“我們”、“們是”、“是中”、“中國”、“國人
solr安裝mmseg4j 分詞器
1.下載資料 https://github.com/chenlb/mmseg4j-solr 注意版本: mmseg4j-solr-2.0.0.jar 要求 lucene/solr >= 4.3.0。在 lucene/solr [4.3.0, 4.7.1]
MMSeg4j 分詞器
MMSeg4j用Chih-Hao Tsai 的MMSeg演算法實現的中文分詞器,並實現lucene的analyzer和solr的TokenizerFactory以方便在Lucene和Solr中使用。 MMSeg 演算法有兩種分詞方法:Simple和Comple
自然語言處理之中文分詞器詳解
中文分詞是中文文字處理的一個基礎步驟,也是中文人機自然語言互動的基礎模組,不同於英文的是,中文句子中沒有詞的界限,因此在進行中文自然語言處理時,通常需要先進行分詞,分詞效果將直接影響詞性,句法樹等模組
自然語言處理之中文分詞器-jieba分詞器詳解及python實戰
中文分詞是中文文字處理的一個基礎步驟,也是中文人機自然語言互動的基礎模組,在進行中文自然語言處理時,通常需要先進行分詞。本文詳細介紹現在非常流行的且開源的分詞器結巴jieba分詞器,並使用python實
Elasticsearch之中文分詞器外掛es-ik的自定義詞庫
開發十年,就只剩下這套架構體系了! >>>
es學習(三):分詞器介紹以及中文分詞器ik的安裝與使用
什麼是分詞 把文字轉換為一個個的單詞,分詞稱之為analysis。es預設只對英文語句做分詞,中文不支援,每個中文字都會被拆分為獨立的個體。 示例 POST http://192.168.247.8:9200/_analyze { "analyzer":"standar
ElasticSearch學習筆記之三十三 IK分詞器擴充套件字典及text全文型別資料分詞聚合查詢
ElasticSearch學習筆記之三十三 IK分詞器擴充套件字典及text全文型別資料分詞聚合查詢 專屬詞彙分詞失敗 擴充套件字典 檢視當前詞庫 自定義詞典 更新配置 再次檢視分詞 text全文型別資料分詞聚合
如何開發自己的搜索帝國之安裝ik分詞器
style utf-8 編碼 ref 文本 需要 shell pack 用戶 you Elasticsearch默認提供的分詞器,會把每個漢字分開,而不是我們想要的根據關鍵詞來分詞,我是中國人 不能簡單的分成一個個字,我們更希望 “中國人”,&
Elasticsearch入門之從零開始安裝ik分詞器
gpo article terms n) rm -rf 從零開始 系列 pack 默認 起因 需要在ES中使用聚合進行統計分析,但是聚合字段值為中文,ES的默認分詞器對於中文支持非常不友好:會把完整的中文詞語拆分為一系列獨立的漢字進行聚合,顯然這並不是我的初衷。我們來看個
Lucene.net(4.8.0) 學習問題記錄五: JIEba分詞和Lucene的結合,以及對分詞器的思考
+= d+ ext eth reac chart rdl ret start 前言:目前自己在做使用Lucene.net和PanGu分詞實現全文檢索的工作,不過自己是把別人做好的項目進行遷移。因為項目整體要遷移到ASP.NET Core 2.0版本,而Lucene使用的版本
docker之es+es-head+kibana+ik分詞器安裝
data elastics work str search url 使用 數據 head 一、es 第一步:搜索docker search elasticsearch第二步:下載鏡像第三步:創建數據文件夾和配置文件宿主服務器創建文件夾mkdir -p /docker/es1
Solr 7.5配置、資料庫連線、Java(學習篇(2)IK分詞器配置)
2、配置IK分詞器 (本人已把需要用到的所有工具、檔案、jar包上傳至百度網盤,有需要者可下載使用, 連結:https://pan.baidu.com/s/1G_L-h0PN2GAaPcreKuuhlg 提取碼:qnwe ) 在ikanalyzer-solr6.5資料夾中找到核心jar包
Es學習第五課, 分詞器介紹和中文分詞器配置
上課我們介紹了倒排索引,在裡面提到了分詞的概念,分詞器就是用來分詞的。 分詞器是ES中專門處理分詞的元件,英文為Analyzer,定義為:從一串文字中切分出一個一個的詞條,並對每個詞條進行標準化。它由三部分組成, Character Filters:分詞之前進行預處
jieba分詞器學習
如有侵權,一定刪除。 結巴分詞分為三種模式:精確模式(預設)、全模式和搜尋引擎模式。 精確模式: import jieba s = '武漢大學是一所還不錯的大學' result = jieba.cut(s) print(','.join(result)) 輸出:
elasticsearch之分詞器
1.概念 在elasticsearch中索引分析模組是可以通過註冊分詞器來進行配置的。分詞器的作用就是當一個文件被索引的時候,分詞器從文件中提取若干詞元(token)來支援索引的儲存和搜尋。elasticsearch內建了很多分詞器,分解器,和詞元過濾器. 索引分析模組包括: 分