http://blog.csdn.net/john_xyz/article/details/54645527 結(jié)巴分詞是國(guó)內(nèi)程序員用Python開(kāi)發(fā)的一個(gè)中文分詞模塊,可能是最好的python中文分詞組件?
中文分詞的原理
- 1、中文分詞(Chinese Word Segmentation) 指的是將一個(gè)漢字序列切分成一個(gè)一個(gè)單獨(dú)的詞。分詞就是將連續(xù)的字序列按照一定的規(guī)范重新組合成詞序列的過(guò)程
- 2、現(xiàn)有的分詞算法可分為三大類:基于字符串匹配的分詞方法、基于理解的分詞方法和基于統(tǒng)計(jì)的分詞方法
- 基于字符串匹配的分詞方法:這種方法又叫做機(jī)械分詞方法,它是按照一定的策略將待分析的漢字串與一個(gè)“充分大的”機(jī)器詞典中的詞條進(jìn)行配,若在詞典中找到某個(gè)字符串,則匹配成功(識(shí)別出一個(gè)詞)
- 1)正向最大匹配法(由左到右的方向)
- 2)逆向最大匹配法(由右到左的方向):
- 3)最少切分(使每一句中切出的詞數(shù)最?。?/dd>
- 4)雙向最大匹配法(進(jìn)行由左到右、由右到左兩次掃描)
- 基于理解的分詞方法:這種分詞方法是通過(guò)讓計(jì)算機(jī)模擬人對(duì)句子的理解,達(dá)到識(shí)別詞的效果。其基本思想就是在分詞的同時(shí)進(jìn)行句法、語(yǔ)義分析,利用句法信息和語(yǔ)義信息來(lái)處理歧義現(xiàn)象。它通常包括三個(gè)部分:分詞子系統(tǒng)、句法語(yǔ)義子系統(tǒng)、總控部分。在總控部分的協(xié)調(diào)下,分詞子系統(tǒng)可以獲得有關(guān)詞、句子等的句法和語(yǔ)義信息來(lái)對(duì)分詞歧義進(jìn)行判斷,即它模擬了人對(duì)句子的理解過(guò)程。這種分詞方法需要使用大量的語(yǔ)言知識(shí)和信息。由于漢語(yǔ)語(yǔ)言知識(shí)的籠統(tǒng)、復(fù)雜性,難以將各種語(yǔ)言信息組織成機(jī)器可直接讀取的形式,因此目前基于理解的分詞系統(tǒng)還處在試驗(yàn)階段。
- 基于統(tǒng)計(jì)的分詞方法:給出大量已經(jīng)分詞的文本,利用統(tǒng)計(jì)機(jī)器學(xué)習(xí)模型學(xué)習(xí)詞語(yǔ)切分的規(guī)律(稱為訓(xùn)練),從而實(shí)現(xiàn)對(duì)未知文本的切分。例如最大概率分詞方法和最大熵分詞方法等。隨著大規(guī)模語(yǔ)料庫(kù)的建立,統(tǒng)計(jì)機(jī)器學(xué)習(xí)方法的研究和發(fā)展,基于統(tǒng)計(jì)的中文分詞方法漸漸成為了主流方法。
- 主要統(tǒng)計(jì)模型:N元文法模型(N-gram),隱馬爾可夫模型(Hidden Markov Model ,HMM),最大熵模型(ME),條件隨機(jī)場(chǎng)模型(Conditional Random Fields,CRF)等。
Feature
- 支持三種分詞模式
1 精確模式,試圖將句子最精確地切開(kāi),適合文本分析;
2 全模式,把句子中所有的可以成詞的詞語(yǔ)都掃描出來(lái), 速度非??欤遣荒芙鉀Q歧義;
3 搜索引擎模式,在精確模式的基礎(chǔ)上,對(duì)長(zhǎng)詞再次切分,提高召回率,適合用于搜索引擎分詞。
- 支持繁體分詞
- 支持自定義詞典
基本用法示例
1、分詞
# -*- coding: utf-8 -*-
import jieba
import jieba.posseg as pseg
import jieba.analyse
str1 = "我來(lái)到北京清華大學(xué)"
str2 = 'python的正則表達(dá)式是好用的'
str3 = "小明碩士畢業(yè)于中國(guó)科學(xué)院計(jì)算所,后在日本京都大學(xué)深造"
seg_list = jieba.cut(str1,cut_all = True) ##全模式
result = pseg.cut(str1) ##詞性標(biāo)注,標(biāo)注句子分詞后每個(gè)詞的詞性
result2 = jieba.cut(str2) ##默認(rèn)是精準(zhǔn)模式
result3 = jieba.analyse.extract_tags(str1,2)
##關(guān)鍵詞提取,參數(shù)setence對(duì)應(yīng)str1為待提取的文本,topK對(duì)應(yīng)2為返回幾個(gè)TF/IDF權(quán)重最大的關(guān)鍵詞,默認(rèn)值為20
result4 = jieba.cut_for_search(str3) ##搜索引擎模式
print " /".join(seg_list)
>>>我 /來(lái)到 /北京 /清華 /清華大學(xué) /華大 /大學(xué)
for w in result:
print w.word, "/", w.flag, ", ",
>>>我 / r , 來(lái)到 / v , 北京 / ns , 清華大學(xué) / nt ,
for t in result2:
print t,
>>>python 的 正則表達(dá)式 是 好 用 的
for s in result3:
print s
>>>清華大學(xué)
來(lái)到
print " ,".join(result4)
>>>小明 ,碩士 ,畢業(yè) ,于 ,中國(guó) ,科學(xué) ,學(xué)院 ,科學(xué)院 ,中國(guó)科學(xué)院 ,計(jì)算 ,計(jì)算所 ,, ,后 ,在 ,日本 ,京都 ,大學(xué) ,日本京都大學(xué) ,深造
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
2、返回詞所在位置
import jieba
test_sent = u"永和服裝飾品有限公司"
result = jieba.tokenize(test_sent) ##Tokenize:返回詞語(yǔ)在原文的起始位置
for tk in result:
print "word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2])
print tk
>>>
>word 永和 start: 0 end:2
(u'\u6c38\u548c', 0, 2)
word 服裝 start: 2 end:4
(u'\u670d\u88c5', 2, 4)
word 飾品 start: 4 end:6
(u'\u9970\u54c1', 4, 6)
word 有限公司 start: 6 end:10
(u'\u6709\u9650\u516c\u53f8', 6, 10)
3、自定義詞典
# -*- coding: utf-8 -*-
import sys
import jieba
jieba.load_userdict('userdict.txt')
test_sent = "大連美容美發(fā)學(xué)校中君意是你值得信賴的選擇"
test_sent2 = '江州市長(zhǎng)江大橋參加了長(zhǎng)江大橋的通車(chē)儀式'
print ", ".join(jieba.cut(test_sent))
>>>大連, 美容美發(fā), 學(xué)校, 中, 君意, 是, 你, 值得, 信賴, 的, 選擇
print ", ".join(jieba.cut(test_sent2))
>>>江州, 市長(zhǎng), 江大橋, 參加, 了, 長(zhǎng)江大橋, 的, 通車(chē), 儀式
自定義詞典的格式:一個(gè)詞占一行;每一行分三部分,一部分為詞語(yǔ),另一部分為詞頻,最后為詞性(可省略),用空格隔開(kāi)
其中user_dict.txt的內(nèi)容是:
云計(jì)算 5
李小福 2 nr
創(chuàng)新辦 3 i
easy_install 3 eng
好用 300
韓玉賞鑒 3 nz
八一雙鹿 3 nz
臺(tái)中
凱特琳 nz
Edu Trust認(rèn)證 2000
君意 3
江大橋 20000
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
jieba分詞的基本原理
第一條:基于Trie樹(shù)結(jié)構(gòu)實(shí)現(xiàn)高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構(gòu)成的有向無(wú)環(huán)圖(DAG)
這個(gè)看上面的trie樹(shù)的python實(shí)現(xiàn), 結(jié)巴分詞自帶了一個(gè)叫做dict.txt的詞典, 里面有2萬(wàn)多條詞, 包含了詞條出現(xiàn)的次數(shù)(這個(gè)次數(shù)是于作者自己基于人民日?qǐng)?bào)語(yǔ)料等資源訓(xùn)練得出來(lái)的)和詞性. 這個(gè)第一條的trie樹(shù)結(jié)構(gòu)的詞圖掃描, 說(shuō)的就是把這2萬(wàn)多條詞語(yǔ), 放到一個(gè)trie樹(shù)中, 而trie樹(shù)是有名的前綴樹(shù), 也就是說(shuō)一個(gè)詞語(yǔ)的前面幾個(gè)字一樣, 就表示他們具有相同的前綴, 就可以使用trie樹(shù)來(lái)存儲(chǔ), 具有查找速度快的優(yōu)勢(shì).
聰明的人可能會(huì)想到把 dict.txt中所有的詞匯全部刪掉, 然后再試試結(jié)巴能不能分詞, 結(jié)果會(huì)發(fā)現(xiàn), 結(jié)巴依然能夠分詞, 不過(guò)分出來(lái)的詞, 大部分的長(zhǎng)度為2.這個(gè)就是第三條, 基于HMM來(lái)預(yù)測(cè)分詞了.
接著說(shuō)DAG有向無(wú)環(huán)圖, 就是后一句的 生成句子中漢字所有可能成詞情況所構(gòu)成的有向無(wú)環(huán)圖, 這個(gè)是說(shuō)的, 給定一個(gè)句子, 要你分詞, 也就是給定一個(gè) 待分詞的句子, 對(duì)這個(gè)句子進(jìn)行生成有向無(wú)環(huán)圖. 如果對(duì)有向無(wú)環(huán)圖理解不了可以百度或者google搜索, 也可以看這篇 http://book.51cto.com/art/201106/269048.htm 比較形象的用圖來(lái)表示了一個(gè)待分詞句子的切分情況.
作者是怎么切分的呢? 1. 根據(jù)dict.txt生成trie樹(shù), 2, 對(duì)待分詞句子, 根據(jù)dict.txt生成的trie樹(shù), 生成DAG, 實(shí)際上通俗的說(shuō), 就是對(duì)待分詞句子, 根據(jù)給定的詞典進(jìn)行查詞典操作, 生成幾種可能的句子切分. dag是啥玩意?記錄了啥呢? 作者的源碼中記錄的是句子中某個(gè)詞的開(kāi)始位置, 從0到n-1(n為句子的長(zhǎng)度), 每個(gè)開(kāi)始位置作為字典的鍵, value是個(gè)list, 其中保存了可能的詞語(yǔ)的結(jié)束位置(通過(guò)查字典得到詞, 開(kāi)始位置+詞語(yǔ)的長(zhǎng)度得到結(jié)束位置)
例如:{0:[1,2,3]} 這樣一個(gè)簡(jiǎn)單的DAG, 就是表示0位置開(kāi)始, 在1,2,3位置都是詞, 就是說(shuō)0~1, 0~2,0~3這三個(gè)起始位置之間的字符, 在dict.txt中是詞語(yǔ).
第二條:采用了動(dòng)態(tài)規(guī)劃查找最大概率路徑, 找出基于詞頻的最大切分組合
關(guān)于動(dòng)態(tài)規(guī)劃查找最大概率路徑, 這個(gè)在一些大學(xué)課程中講的很多了, 不熟悉的或者忘記了的翻翻百度就行了. 上面給的那個(gè)在線書(shū)籍的鏈接中也說(shuō)的很明白了, 我這里就說(shuō)說(shuō)作者的代碼:
作者的代碼中講字典在生成trie樹(shù)的同時(shí), 也把每個(gè)詞的出現(xiàn)次數(shù)轉(zhuǎn)換為了頻率. 關(guān)于頻率和概率, 這里在啰嗦幾句: 按照定義, 頻率其實(shí)也是一個(gè)0~1之間的小數(shù), 是 事件出現(xiàn)的次數(shù)/實(shí)驗(yàn)中的總次數(shù), 因此在試驗(yàn)次數(shù)足夠大的情況下, 頻率約等于概率, 或者說(shuō)頻率的極限就是概率. 不過(guò)通常人們混淆的是頻率和次數(shù), 經(jīng)常把頻率等同于事件出現(xiàn)的次數(shù), 比如這里就是某個(gè)詞語(yǔ)出現(xiàn)的次數(shù), 所以, 頻率在引起混淆的時(shí)候, 對(duì)中國(guó)人來(lái)說(shuō), 還是先理解為出現(xiàn)次數(shù), 然后理解發(fā)現(xiàn)有問(wèn)題, 就理解為出現(xiàn)次數(shù)/總數(shù)這個(gè)比率吧.
動(dòng)態(tài)規(guī)劃中, 先查找待分詞句子中已經(jīng)切分好的詞語(yǔ), 對(duì)該詞語(yǔ)查找該詞語(yǔ)出現(xiàn)的頻率(次數(shù)/總數(shù)), 如果沒(méi)有該詞(既然是基于詞典查找, 應(yīng)該是有的), 就把詞典中出現(xiàn)頻率最小的那個(gè)詞語(yǔ)的頻率作為該詞的頻率, 也就是說(shuō)P(某詞語(yǔ))=FREQ.get(‘某詞語(yǔ)’,min_freq), 然后根據(jù)動(dòng)態(tài)規(guī)劃查找最大概率路徑的方法, 對(duì)句子從右往左反向計(jì)算最大概率(一些教科書(shū)上可能是從左往右, 這里反向是因?yàn)闈h語(yǔ)句子的重心經(jīng)常落在后面, 就是落在右邊, 因?yàn)橥ǔG闆r下形容詞太多, 后面的才是主干, 因此, 從右往左計(jì)算, 正確率要高于從左往右計(jì)算, 這個(gè)類似于逆向最大匹配), P(NodeN)=1.0, P(NodeN-1)=P(NodeN)*Max(P(倒數(shù)第一個(gè)詞))…依次類推, 最后得到最大概率路徑, 得到最大概率的切分組合.
第三條, 對(duì)于未登錄詞,采用了基于漢字成詞能力的HMM模型,使用了Viterbi算法
未登錄詞, 作者說(shuō)的是什么意思? 其實(shí)就是詞典 dict.txt 中沒(méi)有記錄的詞. 上面說(shuō)了, 把dict.txt中的所有詞語(yǔ)都刪除了, 結(jié)巴分詞一樣可以分詞, 就是說(shuō)的這個(gè).
怎么做到的? 這個(gè)就基于作者采用的HMM模型了, 中文詞匯按照BEMS四個(gè)狀態(tài)來(lái)標(biāo)記, B是開(kāi)始begin位置, E是end, 是結(jié)束位置, M是middle, 是中間位置, S是singgle, 單獨(dú)成詞的位置, 沒(méi)有前, 也沒(méi)有后. 也就是說(shuō), 他采用了狀態(tài)為(B,E,M,S)這四種狀態(tài)來(lái)標(biāo)記中文詞語(yǔ), 比如北京可以標(biāo)注為 BE, 即 北/B 京/E, 表示北是開(kāi)始位置, 京是結(jié)束位置, 中華民族可以標(biāo)注為BMME, 就是開(kāi)始, 中間, 中間, 結(jié)束.
經(jīng)過(guò)作者對(duì)大量語(yǔ)料的訓(xùn)練, 得到了finalseg目錄下的三個(gè)文件(來(lái)自結(jié)巴項(xiàng)目的issues):
要統(tǒng)計(jì)的主要有三個(gè)概率表:
prob_trans.py
1)位置轉(zhuǎn)換概率,即B(開(kāi)頭),M(中間),E(結(jié)尾),S(獨(dú)立成詞)四種狀態(tài)的轉(zhuǎn)移概率;
{‘B’: {‘E’: 0.8518218565181658, ‘M’: 0.14817814348183422},
‘E’: {‘B’: 0.5544853051164425, ‘S’: 0.44551469488355755},
‘M’: {‘E’: 0.7164487459986911, ‘M’: 0.2835512540013088},
‘S’: {‘B’: 0.48617017333894563, ‘S’: 0.5138298266610544}}
P(E|B) = 0.851, P(M|B) = 0.149,說(shuō)明當(dāng)我們處于一個(gè)詞的開(kāi)頭時(shí),下一個(gè)字是結(jié)尾的概率
要遠(yuǎn)高于下一個(gè)字是中間字的概率,符合我們的直覺(jué),因?yàn)槎€(gè)字的詞比多個(gè)字的詞更常見(jiàn)。
prob_emit.py
2)位置到單字的發(fā)射概率,比如P(“和”|M)表示一個(gè)詞的中間出現(xiàn)”和”這個(gè)字的概率;
prob_start.py
3) 詞語(yǔ)以某種狀態(tài)開(kāi)頭的概率,其實(shí)只有兩種,要么是B,要么是S。這個(gè)就是起始向量, 就是HMM系統(tǒng)的最初模型狀態(tài)
實(shí)際上, BEMS之間的轉(zhuǎn)換有點(diǎn)類似于2元模型, 就是2個(gè)詞之間的轉(zhuǎn)移
二元模型考慮一個(gè)單詞后出現(xiàn)另外一個(gè)單詞的概率,是N元模型中的一種。
例如:一般來(lái)說(shuō),”中國(guó)”之后出現(xiàn)”北京”的概率大于”中國(guó)”之后出現(xiàn)”北?!钡母怕剩簿褪牵褐袊?guó)北京 比 中國(guó)北海出現(xiàn)的概率大些, 更有可能是一個(gè)中文詞語(yǔ).
不過(guò), 作者這里應(yīng)該不是用的2元分詞模型的, 這里的BEMS只提供了單個(gè)漢字之間的轉(zhuǎn)換, 發(fā)射概率, 并沒(méi)有提供粒度更大的, 基于詞語(yǔ)的發(fā)射和轉(zhuǎn)移概率, 當(dāng)然, 也有可能我理解的不夠深入.
給定一個(gè) 待分詞的句子, 就是觀察序列, 對(duì)HMM(BEMS)四種狀態(tài)的模型來(lái)說(shuō), 就是為了找到一個(gè)最佳的BEMS序列, 這個(gè)就需要使用viterbi算法來(lái)得到這個(gè)最佳的隱藏狀態(tài)序列, 具體的python版的viterbi算法請(qǐng)看維基百科:http://zh./wiki/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95 維特比算法
通過(guò)作者之前訓(xùn)練得到的概率表和viterbi算法, 就可以得到一個(gè)概率最大的BEMS序列, 按照B打頭, E結(jié)尾的方式, 對(duì)待分詞的句子重新組合, 就得到了分詞結(jié)果. 比如 對(duì)待分詞的句子 ‘全世界都在學(xué)中國(guó)話’ 得到一個(gè)BEMS序列 [S,B,E,S,S,S,B,E,S] 這個(gè)序列只是舉例, 不一定正確, 通過(guò)把連續(xù)的BE湊合到一起得到一個(gè)詞, 單獨(dú)的S放單, 就得到一個(gè)分詞結(jié)果了: 上面的BE位置和句子中單個(gè)漢字的位置一一對(duì)應(yīng), 得到全/S 世界/BE 都/S 在/S 學(xué)/S 中國(guó)/BE 話/S 從而將句子切分為詞語(yǔ).
以上, 就是作者這三條介紹的全部理解和分析, 對(duì)于其中任何術(shù)語(yǔ)不理解, 請(qǐng)使用搜索引擎.
結(jié)巴分詞的過(guò)程:
加載字典, 生成trie樹(shù)
給定待分詞的句子, 使用正則獲取連續(xù)的 中文字符和英文字符, 切分成 短語(yǔ)列表, 對(duì)每個(gè)短語(yǔ)使用DAG(查字典)和動(dòng)態(tài)規(guī)劃, 得到最大概率路徑, 對(duì)DAG中那些沒(méi)有在字典中查到的字, 組合成一個(gè)新的片段短語(yǔ), 使用HMM模型進(jìn)行分詞, 也就是作者說(shuō)的識(shí)別新詞, 即識(shí)別字典外的新詞.
使用python的yield 語(yǔ)法生成一個(gè)詞語(yǔ)生成器, 逐詞語(yǔ)返回. 當(dāng)然, 我認(rèn)為直接返回list, 效果也差不到哪里去.
參考文獻(xiàn)
[1]: https://www.oschina.net/p/jieba?fromerr=ex7thahF
[2]:http://baike.baidu.com/linkurl=x2vBf5Kvw1vLU03kDD1qwgu8u3FqFXVRanaOeyF3p1GgWfKWxeaIoIbjmCsCe-_ls6Ay0KsUFlHdlckC_uJWcK
[3]: http://book.51cto.com/art/201106/269047.htm
[4]:http://blog.csdn.net/rav009/article/details/12196623
|