中文分詞工具探析(一):ICTCLAS (NLPIR)
【開源中文分詞工具探析】系列:
1. 前言
ICTCLAS是張華平老師推出的中文分詞系統,於2009年更名為NLPIR。ICTCLAS是中文分詞界元老級工具了,作者開放出了free版本的原始碼(1.0整理版本在此). 作者在論文[1] 中宣稱ICTCLAS是基於HHMM(Hierarchical Hidden Markov Model)實現,後在論文[2]中改成了基於層疊隱馬爾可夫模型CHMM(Cascaded Hidden Markov Model)。我把HHMM的原論文[3]讀了一遍,對照ICTCLAS原始碼,發現ICTCLAS本質上就是一個Bigram的Word-Based Generative Model
\begin{equation}
P(w_1^m) = \prod_i P(w_{i} | w_{i-1})
\label{eq:bigram}
\end{equation}
2. ICTCLAS分解
ICTCLAS Free版的C++原始碼實在是佶屈聱牙,因本人水平有限,故參照的原始碼為sinboy的Java實現 ictclas4j ("com.googlecode.ictclas4j" % "ictclas4j" % "1.0.1"
- 按照核心詞典進行第一次切詞;
- 在第一次切詞的基礎上,求解最大聯合概率\eqref{eq:bigram},作者稱之為“二元切分詞圖”;
- HMM識別未登入詞,諸如:人名、翻譯人名、地名、機構名等;
- 分詞結果整理,詞性標註。
詞典
ICTCLAS的詞典包括六種:
import org.ictclas4j.segment._ // 核心詞典 val coreDict = new Dictionary("data/coreDict.dct") // 二元詞典 val bigramDict = new Dictionary("data/bigramDict.dct") // 人名詞典 val personTagger = new PosTagger(Utility.TAG_TYPE.TT_PERSON, "data/nr", coreDict) // 翻譯人名詞典 val transPersonTagger = new PosTagger(Utility.TAG_TYPE.TT_TRANS_PERSON, "data/tr", coreDict) // 地名詞典 val placeTagger = new PosTagger(Utility.TAG_TYPE.TT_TRANS_PERSON, "data/ns", coreDict) // 詞性標註 val lexTagger = new PosTagger(Utility.TAG_TYPE.TT_NORMAL, "data/lexical", coreDict)
其中,核心詞典(coreDict)用於初始切詞,二元詞典(bigramDict)記錄了兩個詞聯合出現的頻數。coreDict與bigramDict的資料格式如下
# coreDict
塊0
count:4
wordLen:0 frequency:3 handle:25856 word:(啊)
wordLen:0 frequency:69 handle:30976 word:(啊)
wordLen:2 frequency:0 handle:25856 word:(啊)呀
wordLen:2 frequency:0 handle:25856 word:(啊)喲
塊1
count:133
wordLen:0 frequency:0 handle:26624 word:(阿)
wordLen:0 frequency:94 handle:27136 word:(阿)
...
# bigramDict
塊0
count:9
wordLen:3 frequency:3 handle:3 word:(啊)@、
wordLen:3 frequency:4 handle:3 word:(啊)@。
wordLen:3 frequency:1 handle:3 word:(啊)@”
wordLen:3 frequency:39 handle:3 word:(啊)@!
wordLen:3 frequency:20 handle:3 word:(啊)@,
其中,frequency
表示詞頻,handle
表示詞性:
讓我們先看一個具體的例子:
wordLen:4 frequency:12 handle:28275 word:(愛)爾蘭
handle = 28275, 轉成HEX表示,為0x6E73。
把0x6E73解釋為字元陣列,0x6E -> 'n', 0x73 -> 's', 所以0x6E73 -> "ns"。
查北大的《漢語文字詞性標註標記集》, ns ~ 地名 (名詞程式碼n和處所詞程式碼s並在一起)。
計算
為了計算聯合概率\eqref{eq:bigram}最大值,ICTCLAS做了一個巧妙的轉換——求對數並做Linear interpolation平滑:
\[ \begin{aligned} \arg \max \prod_i P(w_{i} | w_{i-1}) & = \arg \min - \sum_i \log P(w_{i} | w_{i-1}) \\ & \approx \arg \min - \sum_i \log \left[ aP(w_{i-1}) + (1-a) P(w_{i}|w_{i-1}) \right] \end{aligned} \]
將所有的可能分詞組合構建成一個有向圖,邊的權重設為(上式中)平滑後的log值。由此,將求解最大聯合概率轉化成一個圖論中最短路徑問題。有時最大聯合概率對應的分詞結果不一定是最優的。為了解決這個問題,ICTCLAS採取了N-best策略,即求解N-最短路徑而不是直接求解最短路徑。然後在N-最短路徑的分詞結果上,做HMM修正——識別未登入詞與詞性標註。為了更清晰地瞭解分詞流程,我用scala把分詞函式SegTag::split()
重新寫了一遍:
import java.util
import org.ictclas4j.bean.{Dictionary, SegNode}
import org.ictclas4j.segment._
import org.ictclas4j.utility.{POSTag, Utility}
import scala.collection.JavaConversions._
val sentence = "深夜的穆赫蘭道發生一樁車禍,女子麗塔在車禍中失憶了"
val pathCount = 1
// 儲存分詞結果
val stringBuilder = StringBuilder.newBuilder
// 按[空格|回車]分隔句子
val sentenceSeg = new SentenceSeg(sentence)
sentenceSeg.getSens.filter(_.isSeg).foreach { sen =>
// 原子切分
val as: AtomSeg = new AtomSeg(sen.getContent)
// 全切分:根據核心詞典,生成所有的可能詞
val segGraph: SegGraph = GraphGenerate.generate(as.getAtoms, coreDict)
// 二元切分詞圖
val biSegGraph: SegGraph = GraphGenerate.biGenerate(segGraph, coreDict, bigramDict)
val nsp: NShortPath = new NShortPath(biSegGraph, pathCount)
nsp.getPaths.foreach { onePath =>
// 得到初次分詞路徑
val segPath = getSegPath(segGraph, onePath)
val firstPath = AdjustSeg.firstAdjust(segPath)
// 處理未登陸詞,進對初次分詞結果進行優化
val optSegGraph: SegGraph = new SegGraph(firstPath)
personTagger.recognition(optSegGraph, firstPath)
transPersonTagger.recognition(optSegGraph, firstPath)
placeTagger.recognition(optSegGraph, firstPath)
// 根據優化後的結果,重新進行生成二叉分詞圖表
val optBiSegGraph: SegGraph = GraphGenerate.biGenerate(optSegGraph, coreDict, bigramDict)
// 重新求取N-最短路徑
val optNsp: NShortPath = new NShortPath(optBiSegGraph, pathCount)
val optBipath: util.ArrayList[util.ArrayList[Integer]] = optNsp.getPaths
// 詞性標記
optBipath.foreach { optOnePath =>
val optSegPath: util.ArrayList[SegNode] = getSegPath(optSegGraph, optOnePath)
lexTagger.recognition(optSegPath)
// 對分詞結果做最終的調整,主要是人名的拆分或重疊詞的合併
val adjResult = AdjustSeg.finaAdjust(optSegPath, personTagger, placeTagger)
val adjrs: String = outputResult(adjResult)
stringBuilder ++= adjrs
}
}
}
println(stringBuilder.toString())
// 深夜/t 的/u 穆赫蘭/nr 道/q 發生/v 一/m 樁/q 車禍/n ,/w 女子/n 麗塔/nr 在/p 車禍/n 中/f 失/v 憶/vg 了/y
其中,呼叫了函式:
// 根據二叉分詞路徑生成分詞路徑
private def getSegPath(sg: SegGraph, biPath: util.ArrayList[Integer]): util.ArrayList[SegNode] = {
sg != null && biPath != null match {
case true =>
val path = biPath.map { t => sg.getSnList.get(t) }
new util.ArrayList[SegNode](path)
case _ => null
}
}
// 根據分詞路徑生成分詞結果
private def outputResult(wrList: util.ArrayList[SegNode]): String = {
...
}
後記:據聞ICTCLAS的第一版是作者在中科院讀碩期間完成的,雖說程式碼質量惹人吐槽,但是不得不驚歎於作者的程式碼功底以及在訓練模型上所下的功夫。
3. 參考資料
[1] Zhang, Hua-Ping, et al. "HHMM-based Chinese lexical analyzer ICTCLAS." Proceedings of the second SIGHAN workshop on Chinese language processing-Volume 17. Association for Computational Linguistics, 2003.
[2] 劉群, et al. "基於層疊隱馬模型的漢語詞法分析." 計算機研究與發展 41.8 (2004): 1421-1429.
[3] Fine, Shai, Yoram Singer, and Naftali Tishby. "The hierarchical hidden Markov model: Analysis and applications." Machine learning 32.1 (1998): 41-62.
相關推薦
中文分詞工具探析(一):ICTCLAS (NLPIR)
【開源中文分詞工具探析】系列: 1. 前言 ICTCLAS是張華平老師推出的中文分詞系統,於2009年更名為NLPIR。ICTCLAS是中文分詞界元老級工具了,作者開放出了free版本的原始碼(1.0整理版本在此). 作者在論文[1] 中宣稱ICTCLAS是基於HHMM(Hierarchical Hid
開源中文分詞工具探析(六):Stanford CoreNLP
inf git deb seq 效果 analysis stream fix sps CoreNLP是由斯坦福大學開源的一套Java NLP工具,提供諸如:詞性標註(part-of-speech (POS) tagger)、命名實體識別(named entity recog
開源中文分詞工具探析(七):LTP
LTP是哈工大開源的一套中文語言處理系統,涵蓋了基本功能:分詞、詞性標註、命名實體識別、依存句法分析、語義角色標註、語義依存分析等。 【開源中文分詞工具探析】系列: 1. 前言 同THULAC一樣,LTP也是基於結構化感知器(Structured Perceptron, SP),以最大熵準則建模標註序列
開源中文分詞工具探析(四):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高效地實現檢
中文分詞工具探析(二):Jieba
【開源中文分詞工具探析】系列: 1. 前言 Jieba是由fxsjy大神開源的一款中文分詞工具,一款屬於工業界的分詞工具——模型易用簡單、程式碼清晰可讀,推薦有志學習NLP或Python的讀一下原始碼。與採用分詞模型Bigram + HMM 的ICTCLAS 相類似,Jieba採用的是Unigram +
NLP詞法分析(一):中文分詞
##1.中文分詞介紹 中文分詞相較於英文分詞要難許多,因為英文字身就是由單詞與空格組成的,而中文則是由獨立的字組成的,但同時語義卻是有詞來表達的。因此對於中文的分析與研究,首先應尋找合適的方法進行分詞。現有的中文分詞技術主要分為規則分詞,統計分詞與規則加統計相結
在PyCharm(Python整合開發環境)中安裝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分詞系
Elasticsearch外掛(一):ik分詞
在Elasticsearch的對於中文的檢索,ik效果最好也是使用最火的一款中文分詞外掛。支援自定義詞庫和動態修改詞庫。對於一般情況的的中文檢索,ik分詞是一個很好的選擇。 安裝 版本號要跟Elasticsearch版本對應。 手動安裝: 1.在plugins
北大開源全新中文分詞工具包:準確率遠超THULAC、結巴分詞
選自GitHub,作者:羅睿軒、許晶晶、孫栩,機器之心編輯。 最近,北大開源了一箇中文分詞工具包,它在多個分詞資料集上都有非常高的分詞準確率。其中廣泛使用的結巴分詞誤差率高達 18.55% 和 20.42,而北大的 pkuseg 只有 3.25% 與 4.32%。 pkuseg 是由北京
中文分詞工具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裡提到的資料。 如果
Java中文分詞工具AnsjSeg使用
中文分詞是進行中文文字分析的一個重要步驟。對於Java語言,有許多可選的分詞工具,如中科院計算所的NLPIR(原ICTCLASS)、盤古分詞、IKAnalyzer、PaodingAnalyzer,其中,試用過ICTCLASS及其後續版本,剛開始感覺不錯,但是Java呼叫C語言的方式實在是受
分布式利器Zookeeper(一)
zookeeperZookeeper不論是在實際項目中,還是在各種分布式開源項目中都得到了廣泛應用,從本篇博客開始,將為大家帶來我對Zookeeper的認識。這個系列將會涵蓋Zookeeper的介紹、環境搭建、配置說明、Java操作Zookeeper(原生API方式)、zkclient操作Zookeeper方
[linux][MongoDB] mongodb學習(一):MongoDB安裝、管理工具、
ole ont mon mkdir man 管理工具 tar end 認證 參考原文:http://www.cnblogs.com/kaituorensheng/p/5118226.html linux安裝完美實現! 1. mongoDB安裝、啟動、關閉 1.1