05.27 技術專欄-結巴中文分詞介紹

內容導讀

結巴中文分詞涉及到的算法包括: (1) 基於Trie樹結構實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG); (2) 採用了動態規劃查找最大概率路徑, 找出基於詞頻的最大切分組合; (3) 對於未登錄詞,採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法。結巴中文分詞支持的三種分詞模式包括: (1) 精確模式:試圖將句子最精確地切開,適合文本分析; (2) 全模式:把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義問題; (3) 搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分詞。可以看到,新添加的兩個專有名詞已經被結巴分詞工具辨別出來了。在構建VSM向量空間模型過程或者把文本轉換成數學形式計算中,你需要運用到關鍵詞提取的技術。其中sentence為待提取的文本,topK為返回幾個TF/IDF權重最大的關鍵詞,默認值為20。在信息檢索中,為節省存儲空間和提高搜索效率,在處理自然語言數據(或文本)之前或之後會自動過濾掉某些字或詞,比如“的”、“是”、“而且”、“但是”、”非常“等。

Python中分分詞工具很多,包括盤古分詞、Yaha分詞、Jieba分詞、清華THULAC等。它們的基本用法都大同小異,這裡先了解一下結巴分詞。

一、安裝

pip install jieba

若使用PyCharm,從左上角的File-->Setting-->Project:工程名-->Project Interpreter,點擊右側的“+”,在彈出界面的搜索欄中輸入“jieba”,Install Package

技術專欄-結巴中文分詞介紹

1.png

二、算法介紹

結巴中文分詞涉及到的算法包括:

(1) 基於Trie樹結構實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG);

(2) 採用了動態規劃查找最大概率路徑, 找出基於詞頻的最大切分組合;

(3) 對於未登錄詞,採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法。

三、分詞模式

結巴中文分詞支持的三種分詞模式包括:

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

(2) 全模式:把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義問題;

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

import jieba
# 全模式

text = "我來到北京清華大學"
seg_list = jieba.cut(text, cut_all=True)
print(u"[全模式]: ", "/ ".join(seg_list))
# 精確模式
seg_list = jieba.cut(text, cut_all=False)
print(u"[精確模式]: ", "/ ".join(seg_list))
# 默認是精確模式
seg_list = jieba.cut(text)
print(u"[默認模式]: ", "/ ".join(seg_list))
# 搜索引擎模式
seg_list = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/ ".join(seg_list))

運行結果:

[全模式]: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學
[精確模式]: 我/ 來到/ 北京/ 清華大學
[默認模式]: 我/ 來到/ 北京/ 清華大學
[搜索引擎模式]: 我/ 來到/ 北京/ 清華/ 華大/ 大學/ 清華大學

四、新詞識別

import jieba
#新詞識別 “杭研”並沒有在詞典中,但是也被Viterbi算法識別出來了
seg_list = jieba.cut("他來到了網易杭研大廈")
print (u"[新詞識別]: ", "/ ".join(seg_list))

運行結果:

[新詞識別]: 他/ 來到/ 了/ 網易/ 杭研/ 大廈 

五、自定義詞典

先看一個例子:

import jieba
text = "故宮的著名景點包括乾清宮、太和殿和黃琉璃瓦等"
# 全模式
seg_list = jieba.cut(text, cut_all=True)
print(u"[全模式]: ", "/ ".join(seg_list))
# 精確模式
seg_list = jieba.cut(text, cut_all=False)
print(u"[精確模式]: ", "/ ".join(seg_list))
# 搜索引擎模式
seg_list = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/ ".join(seg_list))

運行結果:

[全模式]: 故宮/ 的/ 著名/ 著名景點/ 景點/ 包括/ 乾/ 清宮/ / / 太和/ 太和殿/ 和/ 黃/ 琉璃/ 琉璃瓦/ 等
[精確模式]: 故宮/ 的/ 著名景點/ 包括/ 乾/ 清宮/ 、/ 太和殿/ 和/ 黃/ 琉璃瓦/ 等
[搜索引擎模式]: 故宮/ 的/ 著名/ 景點/ 著名景點/ 包括/ 乾/ 清宮/ 、/ 太和/ 太和殿/ 和/ 黃/ 琉璃/ 琉璃瓦/ 等

可以看到,結巴分詞工具認出了專有名詞"太和殿",但沒有認出"乾清宮"和"黃琉璃瓦"。

也就是說,專有名詞"乾清宮"和"黃琉璃瓦"可能因分詞而分開,這也是很多分詞工具的一個缺陷。

為此,Jieba分詞支持開發者使用自定定義的詞典,以便包含jieba詞庫裡沒有的詞語。雖然結巴有新詞識別能力,但自行添加新詞可以保證更高的正確率,尤其是專有名詞。

基本用法:

jieba.load_userdict(file_name) #file_name為自定義詞典的路徑

詞典格式和dict.txt一樣,一個詞佔一行;

每一行分三部分,第一部分為詞語,中間部分為詞頻,最後部分為詞性(可省略,ns為地點名詞),用空格隔開。

咱們在jieba的安裝目錄下添加mydict.txt,內容為

乾清宮 1 n
黃琉璃瓦 1 n
技術專欄-結巴中文分詞介紹

2.png

更新代碼,主要是添加加載mydict.txt的代碼:

import jieba
jieba.load_userdict("D:\\Program Files\\Python36\\Lib\\site-packages\\jieba\\mydict.txt")
text = "故宮的著名景點包括乾清宮、太和殿和黃琉璃瓦等"
# 全模式
seg_list = jieba.cut(text, cut_all=True)
print(u"[全模式]: ", "/ ".join(seg_list))
# 精確模式
seg_list = jieba.cut(text, cut_all=False)
print(u"[精確模式]: ", "/ ".join(seg_list))
# 搜索引擎模式
seg_list = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/ ".join(seg_list))

運行結果:

[全模式]: 故宮/ 的/ 著名/ 著名景點/ 景點/ 包括/ 乾清宮/ 清宮/ / / 太和/ 太和殿/ 和/ 黃琉璃瓦/ 琉璃/ 琉璃瓦/ 等
[精確模式]: 故宮/ 的/ 著名景點/ 包括/ 乾清宮/ 、/ 太和殿/ 和/ 黃琉璃瓦/ 等
[搜索引擎模式]: 故宮/ 的/ 著名/ 景點/ 著名景點/ 包括/ 清宮/ 乾清宮/ 、/ 太和/ 太和殿/ 和/ 琉璃/ 琉璃瓦/ 黃琉璃瓦/ 等

可以看到,新添加的兩個專有名詞已經被結巴分詞工具辨別出來了。

六、關鍵詞提取

在構建VSM向量空間模型過程或者把文本轉換成數學形式計算中,你需要運用到關鍵詞提取的技術。

基本方法:

jieba.analyse.extract_tags(sentence, topK) 

其中sentence為待提取的文本,topK為返回幾個TF/IDF權重最大的關鍵詞,默認值為20。

程序:

import jieba
import jieba.analyse
#導入自定義詞典
jieba.load_userdict("D:\\Program Files\\Python36\\Lib\\site-packages\\jieba\\mydict.txt")
#精確模式
text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮非常精美,午門是紫禁城的正門,午門居中向陽。"
seg_list = jieba.cut(text, cut_all=False)
print (u"分詞結果:")
print ("/".join(seg_list))
#獲取關鍵詞
tags = jieba.analyse.extract_tags(text, topK=5)
print (u"關鍵詞:")
print (" ".join(tags))

運行結果:

故宮/的/著名景點/包括/乾清宮/、/太和殿/和/午門/等/。/其中/乾清宮/非常/精美/,/午門/是/紫禁城/的/正門/,/午門/居中/向陽/。 

關鍵詞:
午門 乾清宮 著名景點 太和殿 向陽

這裡“午門”出現了3次,所以先輸出。“乾清宮”出現了2次,第二個輸出。

其他詞都出現1次,那麼為什麼接下來輸出的是“著名景點”、“太和殿”和“向陽”呢?

這是因為,在詞頻一樣的前題下,根據TF/IDF的順序來輸出,因為其他詞的TF一樣(都是1),所以IDF小的會先輸出來。

不知道結巴分詞是根據什麼來判斷IDF的,假如是根據dict.txt中的第二列詞頻來判斷,那麼確實是“著名景點” < “太陽殿” < “向陽” < 其他詞語。這樣第三個輸出的就是“著名景點”,最後兩個依次為“太陽殿”和“向陽”。

七、去除停用詞

在信息檢索中,為節省存儲空間和提高搜索效率,在處理自然語言數據(或文本)之前或之後會自動過濾掉某些字或詞,比如“的”、“是”、“而且”、“但是”、”非常“等。這些字或詞即被稱為Stop Words(停用詞)。

import jieba 

# 去除停用詞
stopwords = {}.fromkeys(['的', '包括', '等', '是'])
text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮非常精美,午門是紫禁城的正門。"
# 精確模式
segs = jieba.cut(text, cut_all=False)
final = ''
for seg in segs:
if seg not in stopwords:
final += seg
print (final)
seg_list = jieba.cut(final, cut_all=False)
print ("/ ".join(seg_list))

運行結果:

故宮著名景點乾清宮、太和殿和午門。其中乾清宮非常精美,午門紫禁城正門。
故宮/ 著名景點/ 乾/ 清宮/ 、/ 太和殿/ 和/ 午門/ 。/ 其中/ 乾/ 清宮/ 非常/ 精美/ ,/ 午門/ 紫禁城/ 正門/ 。

八、參考

https://blog.csdn.net/eastmount/article/details/50256163

TopCoder & Codeforces & AtCoder交流QQ群:648202993

wechat_public_header.jpg


分享到:


相關文章: