1. 程式人生 > >開源中文分詞工具探析(七):LTP

開源中文分詞工具探析(七):LTP

LTP是哈工大開源的一套中文語言處理系統,涵蓋了基本功能:分詞、詞性標註、命名實體識別、依存句法分析、語義角色標註、語義依存分析等。

【開源中文分詞工具探析】系列:

1. 前言

同THULAC一樣,LTP也是基於結構化感知器(Structured Perceptron, SP),以最大熵準則建模標註序列\(Y\)在輸入序列\(X\)的情況下的score函式:

\[ S(Y,X) = \sum_s \alpha_s \Phi_s(Y,X) \]

其中,\(\Phi_s(Y,X)\)為本地特徵函式。中文分詞問題等價於給定\(X\)序列,求解score函式最大值對應的\(Y\)序列:

\[ \mathop{\arg \max}_Y S(Y,X) \]

2. 分解

以下原始碼分析基於版本3.4.0。

分詞流程

分詞流程與其他分詞器別無二致,先提取字元特徵,計算特徵權重值,然後Viterbi解碼。程式碼詳見__ltp_dll_segmentor_wrapper::segment()

int segment(const char *str, std::vector<std::string> &words) {
    ltp::framework::ViterbiFeatureContext ctx;
    ltp::framework::ViterbiScoreMatrix scm;
    ltp::framework::ViterbiDecoder decoder;
    ltp::segmentor::Instance inst;

    int ret = preprocessor.preprocess(str, inst.raw_forms, inst.forms, 
inst.chartypes);

    if (-1 == ret || 0 == ret) {
        words.clear();
        return 0;
    }

    ltp::segmentor::SegmentationConstrain con;
    con.regist(&(inst.chartypes));
    build_lexicon_match_state(lexicons, &inst);
    extract_features(inst, model, &ctx, false);
    calculate_scores(inst, (*model), ctx, true, &scm);

    // allocate a new decoder so that the segmentor support multithreaded
    // decoding. this modification was committed by niuox
    decoder.decode(scm, con, inst.predict_tagsidx);
    build_words(inst.raw_forms, inst.predict_tagsidx, words);

    return words.size();
}

訓練模型

模型檔案cws.model包含了類別、特徵、權重、內部詞典(internal lexicon)等。我用Java 重寫了模型解析,程式碼如下:

DataInputStream is = new DataInputStream(new FileInputStream(path));
char[] octws = readCharArray(is, 128);

// 1. read label
SmartMap label = readSmartMap(is);
int[] entries = readIntArray(is, label.numEntries);

// 2. read feature Space
char[] space = readCharArray(is, 16);
int offset = readInt(is);
int sz = readInt(is);
SmartMap[] dicts = new SmartMap[sz];
for (int i = 0; i < sz; i++) {
    dicts[i] = readSmartMap(is);
}

// 3. read param
char[] param = readCharArray(is, 16);
int dim = readInt(is);
double[] w = readDoubleArray(is, dim);
double[] wSum = readDoubleArray(is, dim);
int lastTimestamp = readInt(is);

// 4. read internal lexicon
SmartMap internalLexicon = readSmartMap(is);

// read char array
private static char[] readCharArray(DataInputStream is, int length) throws IOException {
    char[] chars = new char[length];
    for (int i = 0; i < length; i++) {
        chars[i] = (char) is.read();
    }
    return chars;
}

// read int array
private static int[] readIntArray(DataInputStream is, int length) throws IOException {
    byte[] bytes = new byte[4 * length];
    is.read(bytes);
    IntBuffer intBuffer = ByteBuffer.wrap(bytes)
            .order(ByteOrder.LITTLE_ENDIAN)
            .asIntBuffer();
    int[] array = new int[length];
    intBuffer.get(array);
    return array;
}

LTP共用到了15類特徵,故sz為15;特徵是採用Map表示,LTP稱之為SmartMap,看程式碼本質上是一個HashMap。分詞工具測評結果表明,LTP分詞速度較THULAC要慢。究其原因,THULAC採用雙陣列Trie來表示模型,特徵檢索速度要優於LTP。

特徵

LTP所用到的特徵大致可分為以下幾類:

  • unigram字元特徵 ch[-2], ch[-1], ch[0], ch[1], ch[2]
  • bigram字元特徵 ch[-2]ch[-1], ch[-1]ch[0],ch[0]ch[1],ch[1]ch[2]
  • 字元型別特徵 ct[-1], ct[0], ct[1]
  • 詞典屬性特徵 ch[0]是否為詞典開始字元、中間字元、結束字元

原始碼見extractor.cpp

Extractor::Extractor() {
    // delimit feature templates
    templates.push_back(new Template("1={c-2}"));
    templates.push_back(new Template("2={c-1}"));
    templates.push_back(new Template("3={c-0}"));
    templates.push_back(new Template("4={c+1}"));
    templates.push_back(new Template("5={c+2}"));
    templates.push_back(new Template("6={c-2}-{c-1}"));
    templates.push_back(new Template("7={c-1}-{c-0}"));
    templates.push_back(new Template("8={c-0}-{c+1}"));
    templates.push_back(new Template("9={c+1}-{c+2}"));
    templates.push_back(new Template("14={ct-1}"));
    templates.push_back(new Template("15={ct-0}"));
    templates.push_back(new Template("16={ct+1}"));
    templates.push_back(new Template("17={lex1}"));
    templates.push_back(new Template("18={lex2}"));
    templates.push_back(new Template("19={lex3}"));
}

#define TYPE(x) (strutils::to_str(inst.chartypes[(x)]&0x07))
            data.set("c-2", (idx - 2 < 0 ? BOS : inst.forms[idx - 2]));
            data.set("c-1", (idx - 1 < 0 ? BOS : inst.forms[idx - 1]));
            data.set("c-0", inst.forms[idx]);
            data.set("c+1", (idx + 1 >= len ? EOS : inst.forms[idx + 1]));
            data.set("c+2", (idx + 2 >= len ? EOS : inst.forms[idx + 2]));
            data.set("ct-1", (idx - 1 < 0 ? BOT : TYPE(idx - 1)));
            data.set("ct-0", TYPE(idx));
            data.set("ct+1", (idx + 1 >= len ? EOT : TYPE(idx + 1)));
            data.set("lex1", strutils::to_str(inst.lexicon_match_state[idx] & 0x0f));
            data.set("lex2", strutils::to_str((inst.lexicon_match_state[idx] >> 4) & 0x0f));
            data.set("lex3", strutils::to_str((inst.lexicon_match_state[idx] >> 8) & 0x0f));
#undef TYPE

相關推薦

開源中文工具LTP

LTP是哈工大開源的一套中文語言處理系統,涵蓋了基本功能:分詞、詞性標註、命名實體識別、依存句法分析、語義角色標註、語義依存分析等。 【開源中文分詞工具探析】系列: 1. 前言 同THULAC一樣,LTP也是基於結構化感知器(Structured Perceptron, SP),以最大熵準則建模標註序列

開源中文工具Stanford CoreNLP

inf git deb seq 效果 analysis stream fix sps CoreNLP是由斯坦福大學開源的一套Java NLP工具,提供諸如:詞性標註(part-of-speech (POS) tagger)、命名實體識別(named entity recog

開源中文工具THULAC

THULAC是一款相當不錯的中文分詞工具,準確率高、分詞速度蠻快的;並且在工程上做了很多優化,比如:用DAT儲存訓練特徵(壓縮訓練模型),加入了標點符號的特徵(提高分詞準確率)等。 【開源中文分詞工具探析】系列: 1. 前言 THULAC所採用的分詞模型為結構化感知器(Structured Percep

開源中文工具FNLP

FNLP是由Fudan NLP實驗室的邱錫鵬老師開源的一套Java寫就的中文NLP工具包,提供諸如分詞、詞性標註、文字分類、依存句法分析等功能。 【開源中文分詞工具探析】系列: 1. 前言 類似於THULAC,FNLP也是採用線性模型(linear model)分詞。較於對數線性模型(log-linea

開源中文工具Ansj

Ansj是由孫健(ansjsun)開源的一箇中文分詞器,為ICTLAS的Java版本,也採用了Bigram + HMM分詞模型(可參考我之前寫的文章):在Bigram分詞的基礎上,識別未登入詞,以提高分詞準確度。雖然基本分詞原理與ICTLAS的一樣,但是Ansj做了一些工程上的優化,比如:用DAT高效地實現檢

中文工具ICTCLAS (NLPIR)

【開源中文分詞工具探析】系列: 1. 前言 ICTCLAS是張華平老師推出的中文分詞系統,於2009年更名為NLPIR。ICTCLAS是中文分詞界元老級工具了,作者開放出了free版本的原始碼(1.0整理版本在此). 作者在論文[1] 中宣稱ICTCLAS是基於HHMM(Hierarchical Hid

中文工具Jieba

【開源中文分詞工具探析】系列: 1. 前言 Jieba是由fxsjy大神開源的一款中文分詞工具,一款屬於工業界的分詞工具——模型易用簡單、程式碼清晰可讀,推薦有志學習NLP或Python的讀一下原始碼。與採用分詞模型Bigram + HMM 的ICTCLAS 相類似,Jieba採用的是Unigram +

北大開源全新中文工具準確率遠超THULAC、結巴

選自GitHub,作者:羅睿軒、許晶晶、孫栩,機器之心編輯。 最近,北大開源了一箇中文分詞工具包,它在多個分詞資料集上都有非常高的分詞準確率。其中廣泛使用的結巴分詞誤差率高達 18.55% 和 20.42,而北大的 pkuseg 只有 3.25% 與 4.32%。 pkuseg 是由北京

在PyCharmPython整合開發環境中安裝jieba中文工具

PyCharm IDE中,可以直接引入各種工具包。jieba中文分詞工具包安裝非常方便。 1、開啟Pycharm,點選左上角  >>File  >>Settings。 2、在settings介面中點選Project :***(專案名稱)  >

PyNLPIR python中文工具

命名 hub 兩個 工具 ict mage ret wid tty 官網:https://pynlpir.readthedocs.io/en/latest/ github:https://github.com/tsroten/pynlpir NLPIR分詞系

7個優秀的開源中文庫推薦

中文分詞是中文文字處理的基礎步驟,也是中文人機自然語言互動的基礎模組。由於中文句子中沒有詞的界限,因此在進行中文自然語言處理時,通常需要先進行分詞。 縱觀整個開源領域,陸陸續續做中文分詞的也有不少,不過目前仍在維護的且質量較高的並不多。下面整理了一些個人認為比較優秀的中文分詞庫,以供大家

Hanlp等種優秀的開源中文庫推薦

中文分詞是中文文字處理的基礎步驟,也是中文人機自然語言互動的基礎模組。由於中文句子中沒有詞的界限,因此在進行中文自然語言處理時,通常需要先進行分詞。 縱觀整個開源領域,陸陸續續做中文分詞的也有不少,不過目前仍在維護的且質量較高的並不多。下面整理了一些個人認為比較優秀的中文分

10大Java開源中文器的使用方法和效果對比

原文地址:http://my.oschina.net/apdplat/blog/412921 本文的目標有兩個: 1、學會使用10大Java開源中文分詞器 2、對比分析10 大Java開源中文分詞器的分詞效果 本文給出了10大Java開源中文分詞的使用方法以及分詞

【NLP】11大Java開源中文器的使用方法和效果對比

本文的目標有兩個: 1、學會使用11大Java開源中文分詞器 2、對比分析11大Java開源中文分詞器的分詞效果 本文給出了11大Java開源中文分詞的使用方法以及分詞結果對比程式碼,至於效果哪個好,那要用的人結合自己的應用場景自己來判斷。 11大Java開源中文分詞器,不同的分詞器

Solr與開源中文(ansj)整合

1. ansj分詞原始碼及jar包下載地址 原始碼: https://github.com/NLPchina/ansj_seg jar包: http://maven.nlpcn.org/org/ansj/ http://maven.nlpcn.org/org/nlpcn/n

中文工具thulac4j釋出

1. 介紹 thulac4j是THULAC的Java 8工程化實現,具有分詞速度快、準、強的特點;支援 自定義詞典 繁體轉簡體 停用詞過濾 若想在專案中使用thulac4j,可新增依賴: <dependency> <groupId>io.github.yizhiru</g

乾貨 | 史上最全中文工具整理

作者 | fendouai 一.中文分詞  分詞服務介面列表 二.準確率評測: THULAC:與代表性分詞軟體的效能對比 我們選擇LTP-3.2.0 、ICTCLAS(2015版) 、jieba(C++版)等國內具代表性的分詞軟體與THULAC做效能

中文工具

THULAC 四款python中中文分詞的嘗試。嘗試的有:jieba、SnowNLP(MIT)、pynlpir(大資料搜尋挖掘實驗室(北京市海量語言資訊處理與雲端計算應用工程技術研究中心))、thulac(清華大學自然語言處理與社會人文計算實驗室) 四款都

python中文工具結巴jieba

結巴分詞jieba特點    支援三種分詞模式:        精確模式,試圖將句子最精確地切開,適合文字分析;        全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;        搜尋引擎模式,在精確模式的基礎上,對長詞再次切分,提

jieba.NET是jieba中文的.NET版本C#實現

jieba.NET是jieba中文分詞的.NET版本(C#實現)。 當前版本為0.38.2,基於jieba 0.38,提供與jieba一致的功能與介面,以後可能會在jieba基礎上提供其它擴充套件功能。關於jieba的實現思路,可以看看這篇wiki裡提到的資料。 如果