目錄
一、關鍵詞提取概述
關鍵詞是能夠表達文檔中心內容的詞語,常用於計算機系統標引論文內容特徵、信息檢索、系統彙集以供讀者檢閱。關鍵詞提取是文本挖掘領域的一個分支,是文本檢索、文檔比較、摘要生成、文檔分類和聚類等文本挖掘研究的基礎性工作。
從算法的角度來看,關鍵詞提取算法主要有兩類:無監督關鍵詞提取方法和有監督關鍵詞提取方法。
1、無監督關鍵詞提取方法
不需要人工標註的語料,利用某些方法發現文本中比較重要的詞作爲關鍵詞,進行關鍵詞提取。該方法是先抽取出候選詞,然後對各個候選詞進行打分,然後輸出topK個分值最高的候選詞作爲關鍵詞。根據打分的策略不同,有不同的算法,例如TF-IDF,TextRank,LDA等算法。
無監督關鍵詞提取方法主要有三類:基於統計特徵的關鍵詞提取(TF,TF-IDF);基於詞圖模型的關鍵詞提取(PageRank,TextRank);基於主題模型的關鍵詞提取(LDA)
- 基於統計特徵的關鍵詞提取算法的思想是利用文檔中詞語的統計信息抽取文檔的關鍵詞;
- 基於詞圖模型的關鍵詞提取首先要構建文檔的語言網絡圖,然後對語言進行網絡圖分析,在這個圖上尋找具有重要作用的詞或者短語,這些短語就是文檔的關鍵詞;
- 基於主題關鍵詞提取算法主要利用的是主題模型中關於主題分佈的性質進行關鍵詞提取;
2、有監督關鍵詞提取方法
將關鍵詞抽取過程視爲二分類問題,先提取出候選詞,然後對於每個候選詞劃定標籤,要麼是關鍵詞,要麼不是關鍵詞,然後訓練關鍵詞抽取分類器。當新來一篇文檔時,提取出所有的候選詞,然後利用訓練好的關鍵詞提取分類器,對各個候選詞進行分類,最終將標籤爲關鍵詞的候選詞作爲關鍵詞。
3、無監督方法和有監督方法優的缺點
無監督方法不需要人工標註訓練集合的過程,因此更加快捷,但由於無法有效綜合利用多種信息 對候選關鍵詞排序,所以效果無法與有監督方法媲美;而有監督方法可以通過訓練學習調節多種信息對於判斷關鍵詞的影響程度,因此效果更優,有監督的文本關鍵詞提取算法需要高昂的人工成本,因此現有的文本關鍵詞提取主要採用適用性較強的無監督關鍵詞提取。
4、關鍵詞提取常用工具包
- jieba
- Textrank4zh (TextRank算法工具)
- SnowNLP (中文分析)簡體中文文本處理
- TextBlob (英文分析)
二、TF-IDF關鍵詞提取算法及實現
TF-IDF算法的詳細介紹及實現方法總結參看博客:TF-IDF算法介紹及實現
三、TextRank關鍵詞提取算法實現
TextRank算法的詳細介紹及實現方法總結參看博客:TextRank算法介紹及實現
四、LDA主題模型關鍵詞提取算法及實現
1、LDA(Latent Dirichlet Allocation)文檔主題生成模型
主題模型是一種統計模型用於發現文檔集合中出現的抽象“主題”。主題建模是一種常用的文本挖掘工具,用於在文本體中發現隱藏的語義結構。
LDA也稱三層貝葉斯概率模型,包含詞、主題和文檔三層結構;利用文檔中單詞的共現關係來對單詞按主題聚類,得到“文檔-主題”和“主題-單詞”2個概率分佈。
2、基於LDA主題模型的關鍵詞提取算法實現
from gensim import corpora, models
import jieba.posseg as jp
import jieba
# 簡單文本處理
def get_text(text):
flags = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd') # 詞性
stopwords = ('的', '就', '是', '用', '還', '在', '上', '作爲') # 停用詞
words_list = []
for text in texts:
words = [w.word for w in jp.cut(text) if w.flag in flags and w.word not in stopwords]
words_list.append(words)
return words_list
# 生成LDA模型
def LDA_model(words_list):
# 構造詞典
# Dictionary()方法遍歷所有的文本,爲每個不重複的單詞分配一個單獨的整數ID,同時收集該單詞出現次數以及相關的統計信息
dictionary = corpora.Dictionary(words_list)
print(dictionary)
print('打印查看每個單詞的id:')
print(dictionary.token2id) # 打印查看每個單詞的id
# 將dictionary轉化爲一個詞袋
# doc2bow()方法將dictionary轉化爲一個詞袋。得到的結果corpus是一個向量的列表,向量的個數就是文檔數。
# 在每個文檔向量中都包含一系列元組,元組的形式是(單詞 ID,詞頻)
corpus = [dictionary.doc2bow(words) for words in words_list]
print('輸出每個文檔的向量:')
print(corpus) # 輸出每個文檔的向量
# LDA主題模型
# num_topics -- 必須,要生成的主題個數。
# id2word -- 必須,LdaModel類要求我們之前的dictionary把id都映射成爲字符串。
# passes -- 可選,模型遍歷語料庫的次數。遍歷的次數越多,模型越精確。但是對於非常大的語料庫,遍歷太多次會花費很長的時間。
lda_model = models.ldamodel.LdaModel(corpus=corpus, num_topics=2, id2word=dictionary, passes=10)
return lda_model
if __name__ == "__main__":
texts = ['作爲千元機中爲數不多擁有真全面屏的手機,OPPO K3一經推出,就簇擁不少粉絲', \
'很多人在衝着這塊屏幕購買了OPPO K3之後,發現原來K3的過人之處不止是在屏幕上', \
'OPPO K3的消費者對這部手機總體還是十分滿意的', \
'吉利博越PRO在7月3日全新吉客智能生態系統GKUI19發佈會上正式亮相', \
'今年上海車展,長安CS75 PLUS首次亮相', \
'普通版車型採用的是雙邊共雙出式排氣佈局;運動版本車型採用雙邊共四出的排氣佈局']
# 獲取分詞後的文本列表
words_list = get_text(texts)
print('分詞後的文本:')
print(words_list)
# 獲取訓練後的LDA模型
lda_model = LDA_model(words_list)
# 可以用 print_topic 和 print_topics 方法來查看主題
# 打印所有主題,每個主題顯示5個詞
topic_words = lda_model.print_topics(num_topics=2, num_words=5)
print('打印所有主題,每個主題顯示5個詞:')
print(topic_words)
# 輸出該主題的的詞及其詞的權重
words_list = lda_model.show_topic(0, 5)
print('輸出該主題的的詞及其詞的權重:')
print(words_list)
運行結果:
五、Word2Vec詞聚類的關鍵詞提取算法及實現
1、Word2Vec詞向量表示
利用淺層神經網絡模型自動學習詞語在語料庫中的出現情況,把詞語嵌入到一個高維的空間中,通常在100-500維,在高維空間中詞語被表示爲詞向量的形式。
特徵詞向量的抽取是基於已經訓練好的詞向量模型。
2、K-means聚類算法
聚類算法旨在數據中發現數據對象之間的關係,將數據進行分組,使得組內的相似性儘可能的大,組間的相似性儘可能的小。
算法思想是:首先隨機選擇K個點作爲初始質心,K爲用戶指定的所期望的簇的個數,通過計算每個點到各個質心的距離,將每個點指派到最近的質心形成K個簇,然後根據指派到簇的點重新計算每個簇的質心,重複指派和更新質心的操作,直到簇不發生變化或達到最大的迭代次數則停止。
3、基於Word2Vec詞聚類關鍵詞提取方法的實現過程
主要思路是對於用詞向量表示的詞語,通過K-Means算法對文章中的詞進行聚類,選擇聚類中心作爲文本的一個主要關鍵詞,計算其他詞與聚類中心的距離即相似度,選擇topK個距離聚類中心最近的詞作爲關鍵詞,而這個詞間相似度可用Word2Vec生成的向量計算得到。
具體步驟如下:
- 對語料進行Word2Vec模型訓練,得到詞向量文件;
- 對文本進行預處理獲得N個候選關鍵詞;
- 遍歷候選關鍵詞,從詞向量文件中提取候選關鍵詞的詞向量表示;
- 對候選關鍵詞進行K-Means聚類,得到各個類別的聚類中心(需要人爲給定聚類的個數);
- 計算各類別下,組內詞語與聚類中心的距離(歐幾里得距離或曼哈頓距離),按聚類大小進行降序排序;
- 對候選關鍵詞計算結果得到排名前TopK個詞語作爲文本關鍵詞。
注:第三方工具包Scikit-learn提供了K-Means聚類算法的相關函數,本文用到了sklearn.cluster.KMeans()函數執行K-Means算法,sklearn.decomposition.PCA()函數用於數據降維以便繪製圖形。
六、信息增益關鍵詞提取算法及實現
信息增益算法的詳細介紹及實現方法總結參看博客:信息增益算法介紹及實現
七、互信息關鍵詞提取算法及實現
1、互信息(Mutual Information,MI)
在概率論和信息論中,兩個隨機變量的互信息或轉移信息(transinformation)是變量間相互依賴性的量度。不同於相關係數,互信息並不侷限於實值隨機變量,它更加一般且決定着聯合分佈 p(X,Y) 和分解的邊緣分佈的乘積 p(X)p(Y) 的相似程度。互信息是度量兩個事件集合之間的相關性(mutual dependence)。
互信息被廣泛用於度量一些語言現象的相關性。在信息論中,互信息常被用來衡量兩個詞的相關度,也用來計算詞與類別之間的相關性。
2、互信息計算公式
3、互信息算法實現
from sklearn import metrics
import numpy as np
# 訓練集和訓練標籤
x_train = [[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1],
[3, 3, 3, 3, 3],
[1, 1, 1, 1, 1]]
y_train = [0, 1, 0, 1]
# 測試集和測試標籤
x_test = [[2, 2, 2, 2, 2], [2, 1, 1, 2, 1]]
x_train = np.array(x_train) # 轉爲array
# 存儲每個特徵與標籤相關性得分
features_score_list = []
for i in range(len(x_train[0])):
# 計算每個特徵與標籤的互信息
feature_info = metrics.mutual_info_score(y_train, x_train[:, i])
features_score_list.append(feature_info)
print(features_score_list)
運行結果:
4、信息論中的互信息和決策樹中的信息增益的關係
兩者表達意思是一樣的,都是表示得知特徵 X 的信息而使得類 Y 的信息的不確定性減少的程度。
注:
- 標準化互信息(Normalized Mutual Information,NMI)可以用來衡量兩種聚類結果的相似度。
- 標準化互信息Sklearn實現:metrics.normalized_mutual_info_score(y_train, x_train[:, i])。
- 點互信息(Pointwise Mutual Information,PMI)這個指標來衡量兩個事物之間的相關性(比如兩個詞)。
八、卡方檢驗關鍵詞提取算法及實現
1、卡方檢驗
卡方是數理統計中用於檢驗兩個變量獨立性的方法,是一種確定兩個分類變量之間是否存在相關性的統計方法,經典的卡方檢驗是檢驗定性自變量對定性因變量的相關性。
2、基本思路
- 原假設:兩個變量是獨立的
- 計算實際觀察值和理論值之間的偏離程度
- 如果偏差足夠小,小於設定閾值,就接受原假設;否則就否定原假設,認爲兩變量是相關的。
3、計算公式
其中,A爲實際值,T爲理論值。卡方檢驗可用於文本分類問題中的特徵選擇,此時不需要設定閾值,只關心找到最爲相關的topK個特徵。基本思想:比較理論頻數和實際頻數的吻合程度或者擬合優度問題。
4、基於sklearn的卡方檢驗實現
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# 訓練集和訓練標籤
x_train = [[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1],
[3, 3, 3, 3, 3],
[1, 1, 1, 1, 1]]
y_train = [0, 1, 0, 1]
# 測試集和測試標籤
x_test = [[2, 2, 2, 2, 2], [2, 1, 1, 2, 1]]
y_test = [1, 1]
# 卡方檢驗選擇特徵
chi2_model = SelectKBest(chi2, k=3) # 選擇k個最佳特徵
# 該函數選擇訓練集裏的k個特徵,並將訓練集轉化所選特徵
x_train_chi2 = chi2_model.fit_transform(x_train, y_train)
# 將測試集轉化爲所選特徵
x_test_chi2 = chi2_model.transform(x_test)
print('各個特徵的得分:', chi2_model.scores_)
print('各個特徵的p值:', chi2_model.pvalues_) # p值越小,置信度越高,得分越高
print('所選特徵的索引:', chi2_model.get_support(True))
print('特徵提取轉換後的訓練集和測試集...')
print('x_train_chi2:', x_train_chi2)
print('x_test_chi2:', x_test_chi2)
運行結果:
九、基於樹模型的關鍵詞提取算法及實現
1、樹模型
主要包括決策樹和隨機森林,基於樹的預測模型(sklearn.tree 模塊和 sklearn.ensemble 模塊)能夠用來計算特徵的重要程度,因此能用來去除不相關的特徵(結合 sklearn.feature_selection.SelectFromModel)
sklearn.ensemble模塊包含了兩種基於隨機決策樹的平均算法:RandomForest算法和Extra-Trees算法。這兩種算法都採用了很流行的樹設計思想:perturb-and-combine思想。這種方法會在分類器的構建時,通過引入隨機化,創建一組各不一樣的分類器。這種ensemble方法的預測會給出各個分類器預測的平均。
- RandomForests 在隨機森林(RF)中,該ensemble方法中的每棵樹都基於一個通過可放回抽樣(boostrap)得到的訓練集構建。另外,在構建樹的過程中,當split一個節點時,split的選擇不再是對所有features的最佳選擇。相反的,在features的子集中隨機進行split反倒是最好的split方式。sklearn的隨機森林(RF)實現通過對各分類結果預測求平均得到,而非讓每個分類器進行投票(vote)。
- Ext-Trees 在Ext-Trees中(詳見ExtraTreesClassifier和 ExtraTreesRegressor),該方法中,隨機性在劃分時會更進一步進行計算。在隨機森林中,會使用侯選feature的一個隨機子集,而非查找最好的閾值,對於每個候選feature來說,閾值是抽取的,選擇這種隨機生成閾值的方式作爲劃分原則。
2、樹模型的關鍵詞提取算法實現
(1)部分代碼實現1
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.feature_selection import SelectFromModel
# 導入SelectFromModel結合ExtraTreesClassifier計算特徵重要性,並按重要性閾值選擇特徵。
# 基於樹模型進行模型選擇
clf_model = ExtraTreesClassifier(n_estimators=250, random_state=0)
clf_model.fit(x_train, y_train)
# 獲取每個詞的特徵權重,數值越高特徵越重要
importances = clf_model.feature_importances_
# 選擇特徵重要性爲1.5倍均值的特徵
model = SelectFromModel(clf_model, threshold='1.5*mean', prefit=True)
x_train_new = model.transform(x_train) # 返回訓練集所選特徵
x_test_new = model.transform(x_test) # 返回測試集所選特徵
(2)部分代碼實現2
# 訓練集和訓練標籤
x_train, y_train
# 候選特徵詞列表
words_list
# 基於樹模型進行模型選擇
forest = RandomForestClassifier(n_estimators=250, random_state=0)
forest.fit(x_train, y_train)
importances = forest.feature_importances_ # 獲取每個詞的特徵權重
# 將詞和詞的權重存入字典
feature_words_dic = {}
for i in range(len(words_list)):
feature_words_dic[words_list[i]] = importances[i]
# 對字典按權重由大到小進行排序
words_info_dic_sort = sorted(words_info_dic.items(), key=lambda x: x[1], reverse=True)
# 將關鍵詞和詞的權重分別存入列表
keywords_list = [] # 關鍵詞列表
features_list = [] # 關鍵權重列表
for word in words_info_dic_sort:
keywords_list.append(word[0])
features_list.append(word[1])
# 選取前一千個關鍵詞和權重寫入文本文件
keywords = keywords_list[:1000]
features = features_list[:1000]
# 將含有關鍵字的文本寫入文件
with open('data/keywords_features.txt', 'a', encoding="utf-8") as f:
for i in range(len(keywords)):
f.write(keywords[i] + '\t' + features[i] + '\n')
十、總結
本文總結了本人在實驗過程中所用到的常用關鍵詞抽取方法,實驗數據是基於公司的內部數據,但此篇總結只是方法上的講解和實現,沒有針對某一具體數據集做相應的結果分析。從實驗中可以很明顯看出有監督關鍵詞抽取方法通常會顯著好於無監督方法,但是有監督方法依賴一定規模的標註數據。
參考:
6、句子相似度計算