Jieba 中文分詞 -二- ——詞性標註與關鍵詞提取

jieba 分詞

上一篇 jieba 中文分詞(一)分詞與自定義字典已介紹了 jieba 中文分詞安裝,分詞原理,分詞方法,自定義字典,添加字典等多種常用分詞方法。本篇將繼續介紹 jieba 分詞關鍵詞提取、詞性標註、及常見問題。

關鍵詞提取

關鍵詞提取,將文本中最能表達文本含義的詞語抽取出來,有點類似於論文的關鍵詞或者摘要。關鍵詞抽取可以採取:

基於 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]

一般步驟:

代碼示例:

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 x

Paddle enabled successfully......
paddle 模式
我 r
關注 v
了 u
微信公衆號數據 STUDIO nz

默認模式詞性和專名類別標籤集合如下表。

t2Vhiq

paddle 模式詞性和專名類別標籤集合如下表,其中詞性標籤 24 個(小寫字母),專名類別標籤 4 個(大寫字母)。

weJfnp

並行分詞

原理:將目標文本按行分隔後,把各行文本分配到多個 Python 進程並行分詞,然後歸併結果,從而獲得分詞速度的可觀提升。

基於 python 自帶的 multiprocessing 模塊,目前暫不支持 Windows。

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)

kOiyOQ

搜索模式

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)

4sDPyr

延遲加載機制

jieba 採用延遲加載,import jiebajieba.Tokenizer() 不會立即觸發詞典的加載,一旦有必要纔開始加載詞典構建前綴字典。如果你想手工初始 jieba,也可以手動初始化。

import jieba
jieba.initialize()  # 手動初始化(可選)

有了延遲加載機制後,你可以改變主詞典的路徑:

jieba.set_dictionary('data/dict.txt.big')

常見問題

  1. “臺中” 總是被切成 “臺 中”?(以及類似情況)

P(臺中) < P(臺)×P(中),“臺中” 詞頻不夠導致其成詞概率較低

解決方法:強制調高詞頻

jieba.add_word('臺中') 或者 jieba.suggest_freq('臺中', True)

  1. “今天天氣 不錯” 應該被切成 “今天 天氣 不錯”?(以及類似情況)

解決方法:強制調低詞頻

jieba.suggest_freq(('今天', '天氣'), True)

或者直接刪除該詞 jieba.del_word('今天天氣')

  1. 切出了詞典中沒有的詞語,效果不理想?

解決方法:關閉新詞發現

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