Elasticsearch 默認分詞器和中分分詞器之間的比較及使用方法

首發地址:http://www.54tianzhisheng.cn/...html

介紹:ElasticSearch 是一個基於 Lucene 的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於 RESTful web 接口。Elasticsearch 是用 Java 開發的,並做爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,可以達到實時搜索,穩定,可靠,快速,安裝使用方便。java

Elasticsearch中,內置了不少分詞器(analyzers)。下面來進行比較下系統默認分詞器和經常使用的中文分詞器之間的區別。
<!-- more -->git

系統默認分詞器:

一、standard 分詞器

https://www.elastic.co/guide/...github

如何使用:http://www.yiibai.com/lucene/...web

英文的處理能力同於StopAnalyzer.支持中文采用的方法爲單字切分。他會將詞彙單元轉換成小寫形式,並去除停用詞和標點符號。正則表達式

/**StandardAnalyzer分析器*/
    public void standardAnalyzer(String msg){
        StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);
        this.getTokens(analyzer, msg);
    }

二、simple 分詞器

https://www.elastic.co/guide/...算法

如何使用: http://www.yiibai.com/lucene/...apache

功能強於WhitespaceAnalyzer, 首先會經過非字母字符來分割文本信息,而後將詞彙單元統一爲小寫形式。該分析器會去掉數字類型的字符。數組

/**SimpleAnalyzer分析器*/
    public void simpleAnalyzer(String msg){
        SimpleAnalyzer analyzer = new SimpleAnalyzer(Version.LUCENE_36);
        this.getTokens(analyzer, msg);
    }

三、Whitespace 分詞器

https://www.elastic.co/guide/...瀏覽器

如何使用:http://www.yiibai.com/lucene/...

僅僅是去除空格,對字符沒有lowcase化,不支持中文;
而且不對生成的詞彙單元進行其餘的規範化處理。

/**WhitespaceAnalyzer分析器*/
    public void whitespaceAnalyzer(String msg){
        WhitespaceAnalyzer analyzer = new WhitespaceAnalyzer(Version.LUCENE_36);
        this.getTokens(analyzer, msg);
    }

四、Stop 分詞器

https://www.elastic.co/guide/...

如何使用:http://www.yiibai.com/lucene/...

StopAnalyzer的功能超越了SimpleAnalyzer,在SimpleAnalyzer的基礎上增長了去除英文中的經常使用單詞(如the,a等),也能夠更加本身的須要設置經常使用單詞;不支持中文

/**StopAnalyzer分析器*/
   public void stopAnalyzer(String msg){
       StopAnalyzer analyzer = new StopAnalyzer(Version.LUCENE_36);
       this.getTokens(analyzer, msg);
   }

五、keyword 分詞器

KeywordAnalyzer把整個輸入做爲一個單獨詞彙單元,方便特殊類型的文本進行索引和檢索。針對郵政編碼,地址等文本信息使用關鍵詞分詞器進行索引項創建很是方便。

六、pattern 分詞器

https://www.elastic.co/guide/...

一個pattern類型的analyzer能夠經過正則表達式將文本分紅"terms"(通過token Filter 後獲得的東西 )。接受以下設置:

一個 pattern analyzer 能夠作以下的屬性設置:

lowercase terms是不是小寫. 默認爲 true 小寫.
pattern 正則表達式的pattern, 默認是 W+.
flags 正則表達式的flags
stopwords 一個用於初始化stop filter的須要stop 單詞的列表.默認單詞是空的列表

七、language 分詞器

https://www.elastic.co/guide/...

一個用於解析特殊語言文本的analyzer集合。( arabic,armenian, basque, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english, finnish, french,galician, german, greek, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian,persian, portuguese, romanian, russian, sorani, spanish, swedish, turkish, thai.)惋惜沒有中文。不予考慮

八、snowball 分詞器

一個snowball類型的analyzer是由standard tokenizer和standard filter、lowercase filter、stop filter、snowball filter這四個filter構成的。

snowball analyzer 在Lucene中一般是不推薦使用的。

九、Custom 分詞器

是自定義的analyzer。容許多個零到多個tokenizer,零到多個 Char Filters. custom analyzer 的名字不能以 "_"開頭.

The following are settings that can be set for a custom analyzer type:

Setting Description
tokenizer 通用的或者註冊的tokenizer.
filter 通用的或者註冊的token filters
char_filter 通用的或者註冊的 character filters
position_increment_gap 距離查詢時,最大容許查詢的距離,默認是100

自定義的模板:

index :
    analysis :
        analyzer :
            myAnalyzer2 :
                type : custom
                tokenizer : myTokenizer1
                filter : [myTokenFilter1, myTokenFilter2]
                char_filter : [my_html]
                position_increment_gap: 256
        tokenizer :
            myTokenizer1 :
                type : standard
                max_token_length : 900
        filter :
            myTokenFilter1 :
                type : stop
                stopwords : [stop1, stop2, stop3, stop4]
            myTokenFilter2 :
                type : length
                min : 0
                max : 2000
        char_filter :
              my_html :
                type : html_strip
                escaped_tags : [xxx, yyy]
                read_ahead : 1024

十、fingerprint 分詞器

https://www.elastic.co/guide/...


中文分詞器:

一、ik-analyzer

https://github.com/wks/ik-ana...

IKAnalyzer是一個開源的,基於java語言開發的輕量級的中文分詞工具包。

採用了特有的「正向迭代最細粒度切分算法「,支持細粒度和最大詞長兩種切分模式;具備83萬字/秒(1600KB/S)的高速處理能力。

採用了多子處理器分析模式,支持:英文字母、數字、中文詞彙等分詞處理,兼容韓文、日文字符

優化的詞典存儲,更小的內存佔用。支持用戶詞典擴展定義

針對Lucene全文檢索優化的查詢分析器IKQueryParser(做者吐血推薦);引入簡單搜索表達式,採用歧義分析算法優化查詢關鍵字的搜索排列組合,能極大的提升Lucene檢索的命中率。

Maven用法:

<dependency>
    <groupId>org.wltea.ik-analyzer</groupId>
    <artifactId>ik-analyzer</artifactId>
    <version>3.2.8</version>
</dependency>

在IK Analyzer加入Maven Central Repository以前,你須要手動安裝,安裝到本地的repository,或者上傳到本身的Maven repository服務器上。

要安裝到本地Maven repository,使用以下命令,將自動編譯,打包並安裝:
mvn install -Dmaven.test.skip=true

Elasticsearch添加中文分詞

安裝IK分詞插件

https://github.com/medcl/elas...

進入elasticsearch-analysis-ik-master

更多安裝請參考博客:

一、爲elastic添加中文分詞

二、如何在Elasticsearch中安裝中文分詞器(IK+pinyin)

三、Elasticsearch 中文分詞器 IK 配置和使用

二、結巴中文分詞

特色:

一、支持三種分詞模式:

  • 精確模式,試圖將句子最精確地切開,適合文本分析;

  • 全模式,把句子中全部的能夠成詞的詞語都掃描出來, 速度很是快,可是不能解決歧義;

  • 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提升召回率,適合用於搜索引擎分詞。

二、支持繁體分詞

三、支持自定義詞典

三、THULAC

THULAC(THU Lexical Analyzer for Chinese)由清華大學天然語言處理與社會人文計算實驗室研製推出的一套中文詞法分析工具包,具備中文分詞和詞性標註功能。THULAC具備以下幾個特色:

能力強。利用咱們集成的目前世界上規模最大的人工分詞和詞性標註中文語料庫(約含5800萬字)訓練而成,模型標註能力強大。

準確率高。該工具包在標準數據集Chinese Treebank(CTB5)上分詞的F1值可達97.3%,詞性標註的F1值可達到92.9%,與該數據集上最好方法效果至關。

速度較快。同時進行分詞和詞性標註速度爲300KB/s,每秒可處理約15萬字。只進行分詞速度可達到1.3MB/s。

中文分詞工具thulac4j發佈

一、規範化分詞詞典,並去掉一些無用詞;

二、重寫DAT(雙數組Trie樹)的構造算法,生成的DAT size減小了8%左右,從而節省了內存;

三、優化分詞算法,提升了分詞速率。

<dependency>
  <groupId>io.github.yizhiru</groupId>
  <artifactId>thulac4j</artifactId>
  <version>${thulac4j.version}</version>
</dependency>

http://www.cnblogs.com/en-hen...

thulac4j支持兩種分詞模式:

SegOnly模式,只分詞沒有詞性標註;

SegPos模式,分詞兼有詞性標註。

// SegOnly mode
String sentence = "滔滔的流水,向着波士頓灣無聲逝去";
SegOnly seg = new SegOnly("models/seg_only.bin");
System.out.println(seg.segment(sentence));
// [滔滔, 的, 流水, ,, 向着, 波士頓灣, 無聲, 逝去]

// SegPos mode
SegPos pos = new SegPos("models/seg_pos.bin");
System.out.println(pos.segment(sentence));
//[滔滔/a, 的/u, 流水/n, ,/w, 向着/p, 波士頓灣/ns, 無聲/v, 逝去/v]

四、NLPIR

中科院計算所 NLPIR:http://ictclas.nlpir.org/nlpir/ (可直接在線分析中文)

下載地址:https://github.com/NLPIR-team...

中科院分詞系統(NLPIR)JAVA簡易教程: http://www.cnblogs.com/wukong...

五、ansj分詞器

https://github.com/NLPchina/a...

這是一個基於n-Gram+CRF+HMM的中文分詞的java實現.

分詞速度達到每秒鐘大約200萬字左右(mac air下測試),準確率能達到96%以上

目前實現了.中文分詞. 中文姓名識別 .

用戶自定義詞典,關鍵字提取,自動摘要,關鍵字標記等功能
能夠應用到天然語言處理等方面,適用於對分詞效果要求高的各類項目.

maven 引入:

<dependency>
            <groupId>org.ansj</groupId>
            <artifactId>ansj_seg</artifactId>
            <version>5.1.1</version>
</dependency>

調用demo

String str = "歡迎使用ansj_seg,(ansj中文分詞)在這裏若是你遇到什麼問題均可以聯繫我.我必定盡我所能.幫助你們.ansj_seg更快,更準,更自由!" ;
 System.out.println(ToAnalysis.parse(str));

 歡迎/v,使用/v,ansj/en,_,seg/en,,,(,ansj/en,中文/nz,分詞/n,),在/p,這裏/r,若是/c,你/r,遇到/v,什麼/r,問題/n,都/d,能夠/v,聯繫/v,我/r,./m,我/r,必定/d,盡我所能/l,./m,幫助/v,你們/r,./m,ansj/en,_,seg/en,更快/d,,,更/d,準/a,,,更/d,自由/a,!

六、哈工大的LTP

https://link.zhihu.com/?targe...

LTP制定了基於XML的語言處理結果表示,並在此基礎上提供了一整套自底向上的豐富並且高效的中文語言處理模塊(包括詞法、句法、語義等6項中文處理核心技術),以及基於動態連接庫(Dynamic Link Library, DLL)的應用程序接口、可視化工具,而且可以以網絡服務(Web Service)的形式進行使用。

關於LTP的使用,請參考: http://ltp.readthedocs.io/zh_...

七、庖丁解牛

下載地址:http://pan.baidu.com/s/1eQ88SZS

使用分爲以下幾步:

  1. 配置dic文件:
    修改paoding-analysis.jar中的paoding-dic-home.properties文件,將「#paoding.dic.home=dic」的註釋去掉,並配置成本身dic文件的本地存放路徑。eg:/home/hadoop/work/paoding-analysis-2.0.4-beta/dic

  2. 把Jar包導入到項目中:
    將paoding-analysis.jar、commons-logging.jar、lucene-analyzers-2.2.0.jar和lucene-core-2.2.0.jar四個包導入到項目中,這時就能夠在代碼片斷中使用庖丁解牛工具提供的中文分詞技術,例如:

Analyzer analyzer = new PaodingAnalyzer(); //定義一個解析器
String text = "庖丁系統是個徹底基於lucene的中文分詞系統,它就是從新建了一個analyzer,叫作PaodingAnalyzer,這個analyer的核心任務就是生成一個能夠切詞TokenStream。"; <span style="font-family: Arial, Helvetica, sans-serif;">//待分詞的內容</span>
TokenStream tokenStream = analyzer.tokenStream(text, new StringReader(text)); //獲得token序列的輸出流
try {
    Token t;
    while ((t = tokenStream.next()) != null)
    {
           System.out.println(t); //輸出每一個token
    }
} catch (IOException e) {
    e.printStackTrace();
}

八、sogo在線分詞

sogo在線分詞采用了基於漢字標註的分詞方法,主要使用了線性鏈鏈CRF(Linear-chain CRF)模型。詞性標註模塊主要基於結構化線性模型(Structured Linear Model)

在線使用地址爲:
http://www.sogou.com/labs/web...

九、word分詞

地址: https://github.com/ysc/word

word分詞是一個Java實現的分佈式的中文分詞組件,提供了多種基於詞典的分詞算法,並利用ngram模型來消除歧義。能準確識別英文、數字,以及日期、時間等數量詞,能識別人名、地名、組織機構名等未登陸詞。能經過自定義配置文件來改變組件行爲,能自定義用戶詞庫、自動檢測詞庫變化、支持大規模分佈式環境,能靈活指定多種分詞算法,能使用refine功能靈活控制分詞結果,還能使用詞頻統計、詞性標註、同義標註、反義標註、拼音標註等功能。提供了10種分詞算法,還提供了10種文本類似度算法,同時還無縫和Lucene、Solr、ElasticSearch、Luke集成。注意:word1.3須要JDK1.8

maven 中引入依賴:

<dependencies>
    <dependency>
        <groupId>org.apdplat</groupId>
        <artifactId>word</artifactId>
        <version>1.3</version>
    </dependency>
</dependencies>

ElasticSearch插件:

一、打開命令行並切換到elasticsearch的bin目錄
cd elasticsearch-2.1.1/bin

二、運行plugin腳本安裝word分詞插件:
./plugin install http://apdplat.org/word/archive/v1.4.zip

安裝的時候注意:
    若是提示:
        ERROR: failed to download
    或者
        Failed to install word, reason: failed to download
    或者
        ERROR: incorrect hash (SHA1)
    則從新再次運行命令,若是仍是不行,多試兩次

若是是elasticsearch1.x系列版本,則使用以下命令:
./plugin -u http://apdplat.org/word/archive/v1.3.1.zip -i word

三、修改文件elasticsearch-2.1.1/config/elasticsearch.yml,新增以下配置:
index.analysis.analyzer.default.type : "word"
index.analysis.tokenizer.default.type : "word"

四、啓動ElasticSearch測試效果,在Chrome瀏覽器中訪問:
http://localhost:9200/_analyze?analyzer=word&text=楊尚川是APDPlat應用級產品開發平臺的做者

五、自定義配置
修改配置文件elasticsearch-2.1.1/plugins/word/word.local.conf

六、指定分詞算法
修改文件elasticsearch-2.1.1/config/elasticsearch.yml,新增以下配置:
index.analysis.analyzer.default.segAlgorithm : "ReverseMinimumMatching"
index.analysis.tokenizer.default.segAlgorithm : "ReverseMinimumMatching"

這裏segAlgorithm可指定的值有:
正向最大匹配算法:MaximumMatching
逆向最大匹配算法:ReverseMaximumMatching
正向最小匹配算法:MinimumMatching
逆向最小匹配算法:ReverseMinimumMatching
雙向最大匹配算法:BidirectionalMaximumMatching
雙向最小匹配算法:BidirectionalMinimumMatching
雙向最大最小匹配算法:BidirectionalMaximumMinimumMatching
全切分算法:FullSegmentation
最少詞數算法:MinimalWordCount
最大Ngram分值算法:MaxNgramScore
如不指定,默認使用雙向最大匹配算法:BidirectionalMaximumMatching

十、jcseg分詞器

https://code.google.com/archi...

十一、stanford分詞器

Stanford大學的一個開源分詞工具,目前已支持漢語。

首先,去【1】下載Download Stanford Word Segmenter version 3.5.2,取得裏面的 data 文件夾,放在maven project的 src/main/resources 裏。

而後,maven依賴添加:

<properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <corenlp.version>3.6.0</corenlp.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>${corenlp.version}</version>
        </dependency>
        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>${corenlp.version}</version>
            <classifier>models</classifier>
        </dependency>
        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>${corenlp.version}</version>
            <classifier>models-chinese</classifier>
        </dependency>
    </dependencies>

測試:

import java.util.Properties;

import edu.stanford.nlp.ie.crf.CRFClassifier;

public class CoreNLPSegment {

    private static CoreNLPSegment instance;
    private CRFClassifier         classifier;

    private CoreNLPSegment(){
        Properties props = new Properties();
        props.setProperty("sighanCorporaDict", "data");
        props.setProperty("serDictionary", "data/dict-chris6.ser.gz");
        props.setProperty("inputEncoding", "UTF-8");
        props.setProperty("sighanPostProcessing", "true");
        classifier = new CRFClassifier(props);
        classifier.loadClassifierNoExceptions("data/ctb.gz", props);
        classifier.flags.setProperties(props);
    }

    public static CoreNLPSegment getInstance() {
        if (instance == null) {
            instance = new CoreNLPSegment();
        }

        return instance;
    }

    public String[] doSegment(String data) {
        return (String[]) classifier.segmentString(data).toArray();
    }

    public static void main(String[] args) {

        String sentence = "他和我在學校裏常打桌球。";
        String ret[] = CoreNLPSegment.getInstance().doSegment(sentence);
        for (String str : ret) {
            System.out.println(str);
        }

    }

}

博客

https://blog.sectong.com/blog...

http://blog.csdn.net/lightty/...

十二、Smartcn

Smartcn爲Apache2.0協議的開源中文分詞系統,Java語言編寫,修改的中科院計算所ICTCLAS分詞系統。很早之前看到Lucene上多了一箇中文分詞的contribution,當時只是簡單的掃了一下.class文件的文件名,經過文件名能夠看得出又是一個改的ICTCLAS的分詞系統。

http://lucene.apache.org/core...


自定義分詞器

雖然Elasticsearch帶有一些現成的分析器,然而在分析器上Elasticsearch真正的強大之處在於,你能夠經過在一個適合你的特定數據的設置之中組合字符過濾器、分詞器、詞彙單元過濾器來建立自定義的分析器。

字符過濾器

字符過濾器 用來 整理 一個還沒有被分詞的字符串。例如,若是咱們的文本是HTML格式的,它會包含像 <p> 或者 <div> 這樣的HTML標籤,這些標籤是咱們不想索引的。咱們可使用 html清除 字符過濾器 來移除掉全部的HTML標籤,而且像把 &Aacute; 轉換爲相對應的Unicode字符 Á 這樣,轉換HTML實體。

一個分析器可能有0個或者多個字符過濾器。

分詞器:

一個分析器 必須 有一個惟一的分詞器。 分詞器把字符串分解成單個詞條或者詞彙單元。 標準 分析器裏使用的 標準 分詞器 把一個字符串根據單詞邊界分解成單個詞條,而且移除掉大部分的標點符號,然而還有其餘不一樣行爲的分詞器存在。

詞單元過濾器:

通過分詞,做爲結果的 詞單元流 會按照指定的順序經過指定的詞單元過濾器 。

詞單元過濾器能夠修改、添加或者移除詞單元。咱們已經提到過 lowercase 和 stop 詞過濾器 ,可是在 Elasticsearch 裏面還有不少可供選擇的詞單元過濾器。 詞幹過濾器 把單詞 遏制 爲 詞幹。 ascii_folding 過濾器移除變音符,把一個像 "très" 這樣的詞轉換爲 "tres" 。 ngram 和 edge_ngram 詞單元過濾器 能夠產生 適合用於部分匹配或者自動補全的詞單元。

建立一個自定義分析器

咱們能夠在 analysis 下的相應位置設置字符過濾器、分詞器和詞單元過濾器:

PUT /my_index
{
    "settings": {
        "analysis": {
            "char_filter": { ... custom character filters ... },
            "tokenizer":   { ...    custom tokenizers     ... },
            "filter":      { ...   custom token filters   ... },
            "analyzer":    { ...    custom analyzers      ... }
        }
    }
}

這個分析器能夠作到下面的這些事:

一、使用 html清除 字符過濾器移除HTML部分。

二、使用一個自定義的 映射 字符過濾器把 & 替換爲 "和" :

"char_filter": {
    "&_to_and": {
        "type":       "mapping",
        "mappings": [ "&=> and "]
    }
}

三、使用 標準 分詞器分詞。

四、小寫詞條,使用 小寫 詞過濾器處理。

五、使用自定義 中止 詞過濾器移除自定義的中止詞列表中包含的詞:

"filter": {
    "my_stopwords": {
        "type":        "stop",
        "stopwords": [ "the", "a" ]
    }
}

咱們的分析器定義用咱們以前已經設置好的自定義過濾器組合了已經定義好的分詞器和過濾器:

"analyzer": {
    "my_analyzer": {
        "type":           "custom",
        "char_filter":  [ "html_strip", "&_to_and" ],
        "tokenizer":      "standard",
        "filter":       [ "lowercase", "my_stopwords" ]
    }
}

彙總起來,完整的 建立索引 請求 看起來應該像這樣:

PUT /my_index
{
    "settings": {
        "analysis": {
            "char_filter": {
                "&_to_and": {
                    "type":       "mapping",
                    "mappings": [ "&=> and "]
            }},
            "filter": {
                "my_stopwords": {
                    "type":       "stop",
                    "stopwords": [ "the", "a" ]
            }},
            "analyzer": {
                "my_analyzer": {
                    "type":         "custom",
                    "char_filter":  [ "html_strip", "&_to_and" ],
                    "tokenizer":    "standard",
                    "filter":       [ "lowercase", "my_stopwords" ]
            }}
}}}

索引被建立之後,使用 analyze API 來 測試這個新的分析器:

GET /my_index/_analyze?analyzer=my_analyzer
The quick & brown fox

下面的縮略結果展現出咱們的分析器正在正確地運行:

{
  "tokens" : [
      { "token" :   "quick",    "position" : 2 },
      { "token" :   "and",      "position" : 3 },
      { "token" :   "brown",    "position" : 4 },
      { "token" :   "fox",      "position" : 5 }
    ]
}

這個分析器如今是沒有多大用處的,除非咱們告訴 Elasticsearch在哪裏用上它。咱們能夠像下面這樣把這個分析器應用在一個 string 字段上:

PUT /my_index/_mapping/my_type
{
    "properties": {
        "title": {
            "type":      "string",
            "analyzer":  "my_analyzer"
        }
    }
}

最後

整理參考網上資料,若有不正確的地方還請多多指教!

相關文章
相關標籤/搜索