自然语言处理之jieba分词
在處理英文文本時,由于英文文本天生自帶分詞效果,可以直接通過詞之間的空格來分詞(但是有些人名、地名等需要考慮作為一個整體,比如New York)。而對于中文還有其他類似形式的語言,我們需要根據(jù)來特殊處理分詞。而在中文分詞中最好用的方法可以說是jieba分詞。接下來我們來介紹下jieba分詞的特點、原理與及簡單的應(yīng)用
1、特點
1)支持三種分詞模式
精確模式:試圖將句子最精確的切開,適合文本分析
全模式:把句子中所有的可以成詞的詞語都掃描出來,速度非常快,但是不能解決歧義
搜索引擎模式:在精確模式的基礎(chǔ)上,對長詞再次切分,提高召回率,適合用于搜索引擎分詞
2)支持繁體分詞
3)支持自定義詞典(支持載入新的詞典或者更新自帶的詞典)
?
2、原理
jieba分詞的算法原理主要有以下三項:
1)基于前綴詞典實現(xiàn)高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構(gòu)成的有向無環(huán)圖(DAG)
2)采用了動態(tài)規(guī)劃查找最大概率路徑,找出基于詞頻的最大切分組合
3)對于未登錄詞,采用了基于漢字成詞能力的HMM模型,使用了Viterbi算法
接下來我們來逐步的講解這三種方法。
第一條:基于Tier樹結(jié)構(gòu)實現(xiàn)高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構(gòu)成的有向無環(huán)圖。
首先我們來介紹下Tier樹,Tier樹中文名叫字典樹、前綴樹等等。它的用途主要是將字符串整合成樹形。首先我們來看一下由 “清華大學(xué)” 、“清華” 、“清新” 、“中華” 、“華人” 五個中文詞構(gòu)成的Tier樹。樹的結(jié)構(gòu)如下
這個樹里面每一個方塊代表一個節(jié)點,其中 ”Root” 表示根節(jié)點,不代表任何字符;紫色代表分支節(jié)點;綠色代表葉子節(jié)點。除根節(jié)點外每一個節(jié)點都只包含一個字符。從根節(jié)點到葉子節(jié)點,路徑上經(jīng)過的字符連接起來,構(gòu)成一個詞。而葉子節(jié)點內(nèi)的數(shù)字代表該詞在字典樹中所處的鏈路(字典中有多少個詞就有多少條鏈路),具有共同前綴的鏈路稱為串。除此之外,還需特別強調(diào) Trie 樹的以下幾個特點:
1)具有相同前綴的詞必須位于同一個串內(nèi);例如 “清華”、“清新” 兩個詞都有“清”這個前綴,那么在 Trie 樹上只需構(gòu)建一個 “清” 節(jié)點,“華” 和 “新” 節(jié)點共用一個父節(jié)點即可,如此兩個詞便只需三個節(jié)點便可存儲,這在一定程度上減少了字典的存儲
空間。)
2)Trie 樹中的詞只可共用前綴,不可共用詞的其他部分;例如 “中華”、“華人” 這兩個詞雖然前一個詞的后綴是后一個詞的前綴,但在樹形上必須是獨立的兩條鏈路,而不可以通過首尾交接構(gòu)建這兩個詞,這也說明 Trie 樹僅能依靠公共前綴壓縮字典的存
儲空間,并不能共享詞中的所有相同的字符;當(dāng)然,這一點也有 “例外” ,對于復(fù)合詞,可能會出現(xiàn)兩詞首尾交接的假象,比如 “清華大學(xué)” 這個詞在上例 Trie 樹中看起來似乎是由 “清華” 、“大學(xué)” 兩詞首尾交接而成,但是葉子節(jié)點的標(biāo)識已經(jīng)明
確說明 Trie 樹里面只有 ”清華“ 和 ”清華大學(xué)“ 兩個詞,它們之間共用了前綴,而非由 “清華” 和 ”大學(xué)“ 兩詞首尾交接所得,因此上例 Trie 樹中若需要 “大學(xué)” 這個詞則必須從根節(jié)點開始重新構(gòu)建該詞。)
3)Trie 樹中任何一個完整的詞,都必須是從根節(jié)點開始至葉子節(jié)點結(jié)束,這意味著對一個詞進行檢索也必須從根節(jié)點開始,至葉子節(jié)點才算結(jié)束。
在 Trie 樹中搜索一個字符串,會從根節(jié)點出發(fā),沿著某條鏈路向下逐字比對字符串的每個字符,直到抵達底部的葉子節(jié)點才能確認字符串為該詞,這種檢索方式具有以下兩個優(yōu)點:
1)公共前綴的詞都位于同一個串內(nèi),查詞范圍因此被大幅縮小(比如首字不同的字符串,都會被排除)。)
2)Trie 樹實質(zhì)是一個有限狀態(tài)自動機((Definite Automata, DFA),這就意味著從 Trie 樹的一個節(jié)點(狀態(tài))轉(zhuǎn)移到另一個節(jié)點(狀態(tài))的行為完全由狀態(tài)轉(zhuǎn)移函數(shù)控制,而狀態(tài)轉(zhuǎn)移函數(shù)本質(zhì)上是一種映射,這意味著:逐字搜索 Trie 樹時,從一個字符到下
一個字符比對是不需要遍歷該節(jié)點的所有子節(jié)點的。
構(gòu)建完Tier樹之后就可以根據(jù)Tier樹生成句子的有向無環(huán)圖(DAG)
如果待切分的字符串有m個字符,考慮每個字符左邊和右邊的位置,則有m+1個點對應(yīng),點的編號從0到m。把候選詞看成邊,可以根據(jù)詞典生成一個切分詞圖。切分詞圖是一個有向正權(quán)重的圖。"有意見分歧" 這句話的切分詞圖如下所示。
在 "有意見分歧" 的切分詞圖中:"有" 這條邊的起點是0,終點是1;"有意" 這條邊的起點是0,終點是2,以此類推。切分方案就是從源點0到終點5之間的路徑,共存在兩條切分路徑。
路徑1:0-1-3-5??? 對應(yīng)切分方案S1:有/? 意見/? 分歧/
路徑2:0-2-3-5??? 對應(yīng)切分方案S2:有意/? 見/? 分歧/
第二條:采用了動態(tài)規(guī)劃查找最大概率路徑,找出基于詞頻的最大切分組合
在jieba分詞中的Tier樹會標(biāo)記每個詞的頻率(等于出現(xiàn)的次數(shù)除以總數(shù),當(dāng)總體樣本很大時,可以近似的看做詞的概率),在知道每個詞出現(xiàn)的頻率之后,就可以基于動態(tài)規(guī)劃的方法來尋找概率最大的分詞路徑。一般的動態(tài)規(guī)劃尋找最優(yōu)路徑都是從左往右,然而在這里是從右往左去尋找最優(yōu)路徑。這主要是因為漢語句子中的重心往往在后面,后面才是句子的主干,因此從右往左計算的正確率往往要高于從左往右的正確率。
第三條:對于未登錄詞,采用了基于漢字成詞能力的HMM模型,使用了Viterbi算法
未登錄詞就是在詞典(Tier樹)中未記錄的詞。對于這類詞就是采用HMM模型來生成的(因此如果刪除了詞典,也是可以進行分詞的)。那么HMM模型是如何構(gòu)建的呢?首先定義了四種狀態(tài)BEMS,B是開始,begin位置;E是end,是結(jié)束位置;M是middle,是中間位置;S是singgle,單獨成詞的位置,沒有前,也沒有后。也就是說,他采用了狀態(tài)為(B、E、M、S)這四種狀態(tài)來標(biāo)記中文詞語,比如北京可以標(biāo)注為 BE,即 北/B 京/E,表示北是開始位置,京是結(jié)束位置;中華民族可以標(biāo)注為BMME,就是開始、中間、中間、結(jié)束。
jieba分詞的作者對大量語料進行的訓(xùn)練,得到了finalseg目錄下的三個文件(prob_trans.py 、prob_emit.py 、prob_start.py?)
要統(tǒng)計的主要有三個概率表:
prob_trans.py
1)位置轉(zhuǎn)換概率,即B(開頭),M(中間),E(結(jié)尾),S(獨立成詞)四種狀態(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,說明當(dāng)我們處于一個詞的開頭時,下一個字是結(jié)尾的概率要遠高于下一個字是中間字的概率,符合我們的直覺,因為二個字的詞比多個字的詞更常見。
prob_emit.py?
2)位置到單字的發(fā)射概率,比如P(“和”|M)表示一個詞的中間出現(xiàn)”和”這個字的概率;?
prob_start.py?
3)詞語以某種狀態(tài)開頭的概率,其實只有兩種,要么是B,要么是S。這個就是起始向量,就是HMM系統(tǒng)的最初模型狀態(tài)實際上,BEMS之間的轉(zhuǎn)換有點類似于2元模型,就是2個詞之間的轉(zhuǎn)移二元模型考慮一個單詞后出現(xiàn)另外一個單詞的概率,
是N元模型中的一種。例如:一般來說,”中國”之后出現(xiàn)”北京”的概率大于”中國”之后出現(xiàn)”北海”的概率,也就是:中國北京 比 中國北海出現(xiàn)的概率大些, 更有可能是一個中文詞語。但是這里并不能確定作者是不是使用了二元模型。不過jieba分詞的
性能這么好,應(yīng)該不是使用了二元模型。
因此jieba分詞的過程:
1)生成Tier樹
2)給定句子,使用正則獲取連續(xù)的中文字符和英文字符,切分成短語列表,構(gòu)建有向無環(huán)圖(先生成,然后去詞典中匹配尋找最大概率路徑)和使用動態(tài)規(guī)劃,得到概率最大的路徑。對DAG中那些沒有在字典中查到的詞,組合成一個新的片段短語,
使用HMM模型進行分詞。
3)使用python中的yield語法生成一個詞語生成器返回.
?
3、應(yīng)用
1)分詞
jieba.cut?方法接受三個輸入?yún)?shù): 需要分詞的字符串;cut_all 參數(shù)用來控制是否采用全模式;HMM 參數(shù)用來控制是否使用 HMM 模型
jieba.cut_for_search?方法接受兩個參數(shù):需要分詞的字符串;是否使用 HMM 模型。該方法適合用于搜索引擎構(gòu)建倒排索引的分詞,粒度比較細。待分詞的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。
注意:不建議直接輸入 GBK 字符串,可能無法預(yù)料地錯誤解碼成 UTF-8
jieba.cut?以及?jieba.cut_for_search?返回的結(jié)構(gòu)都是一個可迭代的 generator,可以使用 for 循環(huán)來獲得分詞后得到的每一個詞語(unicode),或者用
jieba.lcut?以及?jieba.lcut_for_search?直接返回 list
jieba.Tokenizer(dictionary=DEFAULT_DICT)?新建自定義分詞器,可用于同時使用不同詞典。jieba.dt?為默認分詞器,所有全局分詞相關(guān)函數(shù)都是該分詞器的映射。
2)添加自定義詞典
載入詞典:
開發(fā)者可以指定自己自定義的詞典,以便包含 jieba 詞庫里沒有的詞。雖然 jieba 有新詞識別能力,但是自行添加新詞可以保證更高的正確率
用法: jieba.load_userdict(file_name) # file_name 為文件類對象或自定義詞典的路徑
詞典格式和?dict.txt?一樣,一個詞占一行;每一行分三部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。file_name?若為路徑或二進制方式打開的文件,則文件必須為 UTF-8 編碼。
詞頻省略時使用自動計算的能保證分出該詞的詞頻。
調(diào)整詞典:
使用?add_word(word, freq=None, tag=None)?和?del_word(word)?可在程序中動態(tài)修改詞典。
使用?suggest_freq(segment, tune=True)?可調(diào)節(jié)單個詞語的詞頻,使其能(或不能)被分出來。
注意:自動計算的詞頻在使用 HMM 新詞發(fā)現(xiàn)功能時可能無效。
3)關(guān)鍵詞提取
基于TF-IDF算法的關(guān)鍵詞抽取:
import jieba.analyse
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
sentence 為待提取的文本
topK 為返回幾個 TF/IDF 權(quán)重最大的關(guān)鍵詞,默認值為 20
withWeight 為是否一并返回關(guān)鍵詞權(quán)重值,默認值為 False
allowPOS 僅包括指定詞性的詞,默認值為空,即不篩選
jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 實例,idf_path 為 IDF 頻率文件
基于TextRank算法的關(guān)鍵詞抽取:
jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v')) 直接使用,接口相同,注意默認過濾詞性。
jieba.analyse.TextRank() 新建自定義 TextRank 實例
4)詞性標(biāo)注
ieba.posseg.POSTokenizer(tokenizer=None)?新建自定義分詞器,tokenizer?參數(shù)可指定內(nèi)部使用的jieba.Tokenizer?分詞器。jieba.posseg.dt?為默認詞性標(biāo)注分詞器。
5)并行分詞
原理:將目標(biāo)文本按行分隔后,把各行文本分配到多個 Python 進程并行分詞,然后歸并結(jié)果,從而獲得分詞速度的可觀提升
基于 python 自帶的 multiprocessing 模塊,目前暫不支持 Windows
用法:
jieba.enable_parallel(4)?# 開啟并行分詞模式,參數(shù)為并行進程數(shù)
jieba.disable_parallel()?# 關(guān)閉并行分詞模式
6)Tokenize:返回詞語在原文中的起止位置
jieba.tokenize(text)
7)延遲加載機制
jieba 采用延遲加載,import jieba?和?jieba.Tokenizer()?不會立即觸發(fā)詞典的加載,一旦有必要才開始加載詞典構(gòu)建前綴字典。如果你想手工初始 jieba,也可以手動初始化。
jieba.initialize()
轉(zhuǎn)載于:https://www.cnblogs.com/jiangxinyang/p/9330876.html
總結(jié)
以上是生活随笔為你收集整理的自然语言处理之jieba分词的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安装仪表盘控件Iocomp会遇到的几个常
- 下一篇: 电梯引发的思考