Jieba 中文分詞 -二- ——詞性標註與關鍵詞提取
jieba 分詞
上一篇 jieba 中文分詞(一)分詞與自定義字典已介紹了 jieba 中文分詞安裝,分詞原理,分詞方法,自定義字典,添加字典等多種常用分詞方法。本篇將繼續介紹 jieba 分詞關鍵詞提取、詞性標註、及常見問題。
關鍵詞提取
關鍵詞提取,將文本中最能表達文本含義的詞語抽取出來,有點類似於論文的關鍵詞或者摘要。關鍵詞抽取可以採取:
-
有監督學習:
文本作爲輸入,關鍵詞作爲標註,進行訓練得到模型。此方法難點在於需要大量人工標註。 -
無監督學習:
先抽取出候選詞,對每個候選詞打分,取出前 K 個分值高的作爲最後的關鍵詞。jieba 分詞實現了基於 TF-IDF 和基於 TextRank 的關鍵詞抽取算法。
基於 TF-IDF 算法的關鍵詞抽取
基於 TF-IDF 的關鍵詞抽取算法,目標是獲取文本中詞頻高,也就是 TF 大的,且語料庫其他文本中詞頻低的,也就是 IDF 大的。這樣的詞可以作爲文本的標誌,用來區分其他文本。
import jieba.analyse
jieba.analyse.extract_tags(sentence,
topK=20,
withWeight=False,
allowPOS=())
sentence: 爲待提取的文本
topK: 爲返回幾個 TF/IDF 權重最大的關鍵詞,默認值爲 20
withWeight: 爲是否一併返回關鍵詞權重值,默認值爲 False
allowPOS: 僅包括指定詞性的詞,默認值爲空,即不篩選
代碼示例:
import jieba
import jieba.analyse
topK = 5
file_name = 'test.txt'
"""
test.txt
西三旗硅谷先鋒小區半地下室出租,便宜可合租硅谷
工信處女幹事每月經過下屬科室都要親口交代24口交換機等技術性器件的安裝工作
"""
with open(file_name, 'rb') as f:
content = f.read()
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)
# 關鍵詞提取所使用逆向文件頻率(IDF)文本語料庫可以切換成自定義語料庫的路徑
jieba.analyse.set_idf_path("../extra_dict/idf.txt.big");
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)
# 關鍵詞提取所使用停止詞文本語料庫可以切換成自定義語料庫的路徑
jieba.analyse.set_stop_words("../extra_dict/stop_words.txt")
jieba.analyse.set_idf_path("../extra_dict/idf.txt.big");
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)
# 關鍵詞一併返回關鍵詞權重值示例
withWeight = True
tags = jieba.analyse.extract_tags(content, topK=topK, withWeight=withWeight)
for tag in tags:
print("tag: %s\t\t weight: %f" % (tag[0],tag[1]))
硅谷, 西三旗, 工信處, 女幹事, 24
硅谷, 西三旗, 先鋒, 小區, 合租
硅谷, 西三旗, 先鋒, 小區, 合租tag: 硅谷 weight: 1.039545
tag: 西三旗 weight: 0.519773
tag: 先鋒 weight: 0.519773
tag: 小區 weight: 0.519773
tag: 合租 weight: 0.519773
基於 TextRank 算法的關鍵詞抽取
jieba.analyse.textrank(sentence,
topK=20,
withWeight=False,
allowPOS=('ns', 'n', 'vn', 'v'))
sentence: 爲待提取的文本
topK: 爲返回幾個權重最大的關鍵詞,默認值爲 20
withWeight: 爲是否一併返回關鍵詞權重值,默認值爲 False
allowPOS: 僅包括指定詞性的詞,默認過濾詞性
算法論文:TextRank: Bringing Order into Texts[1]
一般步驟:
-
先將文本進行分詞和詞性標註,將特定詞性的詞(比如名詞)作爲節點添加到圖中。
-
出現在一個窗口中的詞語之間形成一條邊,窗口大小可設置爲 2~10 之間,默認爲 5,它表示一個窗口中有多少個詞語。
-
對節點根據入度節點個數以及入度節點權重進行打分,入度節點越多,且入度節點權重大,則打分高。
-
然後根據打分進行降序排列,輸出指定個數的關鍵詞。
代碼示例:
tags = jieba.analyse.textrank(content,
topK=5,
withWeight=True)
for tag in tags:
print("tag: %s\t\t weight: %f" % (tag[0],tag[1]))
tag: 硅谷 weight: 1.000000
tag: 女幹事 weight: 0.847395
tag: 技術性 weight: 0.800966
tag: 器件 weight: 0.794530
tag: 交換機 weight: 0.766318
詞性標註
通過查詢字典的方式獲取識別詞的詞性,通過 HMM 隱馬爾科夫模型來獲取未登錄詞的詞性,從而完成整個語句的詞性標註。但可以看到查詢字典的方式不能解決一詞多詞性的問題,也就是詞性歧義問題。故精度上還是有所欠缺的。
標註句子分詞後每個詞的詞性,詞性標示兼容 ICTCLAS 漢語詞性標註集。
除了 jieba 默認分詞模式,提供 paddle 模式下的詞性標註功能。
代碼示例:
import jieba
import jieba.posseg as pseg
jieba.add_word('數據STUDIO')
words = pseg.cut("我關注了微信公衆號數據STUDIO")
print('jieba默認模式')
for word, flag in words:
print('%s %s' % (word, flag))
print('+'*10)
jieba.enable_paddle() #啓動paddle模式。
words = pseg.cut("我關注了微信公衆號數據STUDIO",use_paddle=True) #paddle模式
print('paddle模式')
for word, flag in words:
print('%s %s' % (word, flag))
print('+'*10)
jieba 默認模式
我 r
關注 v
了 ul
微信 vn
公衆 n
號 m
數據 STUDIO xPaddle enabled successfully......
paddle 模式
我 r
關注 v
了 u
微信公衆號數據 STUDIO nz
默認模式詞性和專名類別標籤集合如下表。
paddle 模式詞性和專名類別標籤集合如下表,其中詞性標籤 24 個(小寫字母),專名類別標籤 4 個(大寫字母)。
並行分詞
原理:將目標文本按行分隔後,把各行文本分配到多個 Python 進程並行分詞,然後歸併結果,從而獲得分詞速度的可觀提升。
基於 python 自帶的 multiprocessing 模塊,目前暫不支持 Windows。
-
jieba.enable_parallel(4)
開啓並行分詞模式,參數爲並行進程數 -
jieba.disable_parallel()
關閉並行分詞模式
Tokenize:返回詞語在原文的起止位置
注意,輸入參數只接受 unicode
默認模式
import jieba
import jieba.posseg as pseg
from prettytable import PrettyTable
jieba.add_word('數據STUDIO')
jieba.add_word('微信公衆號')
result = jieba.tokenize(u'我關注了微信公衆號數據STUDIO')
x = PrettyTable(["word", "start", "end"])
x.align["word"] = "l"# 左對齊
x.padding_width = 2 # 列邊和內容之間有兩個空格(默認爲一個空格)
for tk in result:
x.add_row([tk[0], tk[1], tk[2]])
print(x)
搜索模式
result = jieba.tokenize(u'我關注了微信公衆號數據STUDIO', mode='search')
x = PrettyTable(["word", "start", "end"])
x.align["word"] = "l"# 左對齊
x.padding_width = 2 # 列邊和內容之間有兩個空格(默認爲一個空格)
for tk in result:
x.add_row([tk[0], tk[1], tk[2]])
print(x)
延遲加載機制
jieba 採用延遲加載,import jieba
和 jieba.Tokenizer()
不會立即觸發詞典的加載,一旦有必要纔開始加載詞典構建前綴字典。如果你想手工初始 jieba,也可以手動初始化。
import jieba
jieba.initialize() # 手動初始化(可選)
有了延遲加載機制後,你可以改變主詞典的路徑:
-
下載你所需要的詞典,然後覆蓋 jieba/dict.txt 即可;
-
或者用:
jieba.set_dictionary('data/dict.txt.big')
常見問題
- “臺中” 總是被切成 “臺 中”?(以及類似情況)
P(臺中) < P(臺)×P(中),“臺中” 詞頻不夠導致其成詞概率較低
解決方法:強制調高詞頻
jieba.add_word('臺中')
或者 jieba.suggest_freq('臺中', True)
- “今天天氣 不錯” 應該被切成 “今天 天氣 不錯”?(以及類似情況)
解決方法:強制調低詞頻
jieba.suggest_freq(('今天', '天氣'), True)
或者直接刪除該詞 jieba.del_word('今天天氣')
- 切出了詞典中沒有的詞語,效果不理想?
解決方法:關閉新詞發現
jieba.cut('豐田太省了', HMM=False)``jieba.cut('我們中出了一個叛徒', HMM=False)
更多問題 [2]
參考資料
[1] TextRank 算法論文: http://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf
[2] 更多問題: https://github.com/fxsjy/jieba/issues?sort=updated&state=closed
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/2p7dJg3zq-HcESjWOMLYSA