自動關鍵字提取:使用餘弦相似度作為特徵
我有一個文檔術語矩陣,現在我想使用監督學習方法(SVM、樸素貝葉斯……)為每個文檔提取關鍵字。在這個模型中,我已經使用了 Tf-idf、Pos 標籤、…
但現在我想知道下一個。我有一個矩陣與術語之間的餘弦相似性。
是否有可能將這種相似性用作我的模型的特徵?我的想法是長期的在文檔中, 使用文檔中所有術語的餘弦相似度的平均值有期限. 這有用嗎?
我不知道如何通過監督學習進行關鍵字提取,但我確實知道如何通過無監督學習來進行。
有幾種方法可以做到這一點,所以這裡它們是:
分層的
您可以直接在術語相似度矩陣上應用任何層次聚類方法(使用任何相似度函數,而不僅僅是餘弦)
在 scikit-learn 中,你會做這樣的事情:
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity from sklearn.cluster import AgglomerativeClustering vectorizer = TfidfVectorizer(stop_words='english') X = vectorizer.fit_transform(data) C = 1 - cosine_similarity(X.T) ward = AgglomerativeClustering(n_clusters=k, linkage='ward').fit(C) label = ward.labels_
資料來源:[1]
但由於它是凝聚式聚類,因此計算成本很高,並且需要一段時間來計算。
K-均值
另一種可能性是對術語文檔矩陣的行執行通常的 k-means,然後為每個質心找到最常見的術語
例如,在 scikit learn 中,這是這樣做的:
from sklearn.cluster import KMeans km = KMeans(n_clusters=k, init='k-means++', max_iter=100, n_init=1) km.fit(X) order_centroids = km.cluster_centers_.argsort()[:, ::-1] terms = vectorizer.get_feature_names() for i in range(k): print("Cluster %d:" % i, end='') for ind in order_centroids[i, :10]: print(' %s' % terms[ind], end='')
資料來源:[2]
但是k-means依賴於歐幾里得距離,這對於稀疏的高維數據是不利的。還有其他技術更適用於文本並使用餘弦相似度
餘弦 K 均值和分散/聚集
可以將 Cosine 與 K-means 一起使用(參見例如[3]):計算質心作為每個集群中所有文檔的平均值,然後使用餘弦計算到最近質心的距離。
最後,您可以像通常的 k-means 一樣提取關鍵字。
將平均質心計算為集群中所有文檔的平均值並不總是好的。Scatter/Gather 算法[4]中提出了另一種方法:集群的質心是該集群中所有文檔的串聯。
對於這種方法,您只需要為每個質心集群採用最常見的術語。
scikit learn 中沒有這些算法的實現,但是您可以通過擴展
KMeans
.請注意,在這兩種情況下,質心變得非常密集:比每個集群中的其余文檔更密集,因此您可能希望截斷質心中的術語,即刪除“不重要”的術語。(見[8])。
光譜聚類
另一種方法是應用譜聚類。您需要提供一個已有的相似度矩陣,它會在上面找到聚類。
它在
SpectralClustering
類中實現,參見[5]中的示例。請注意,由於您已經有一個預先計算的矩陣,因此您需要affinity='precumputed'
在初始化時使用屬性。Spectral clustering 與 Kernel KMeans 有關:有論文(參見 [7])表明它們是同一事物。我最近遇到了一個可能有用的內核 KMeans 實現:https ://gist.github.com/mblondel/6230787
非負矩陣分解
最後,您可以使用線性代數中的一些分解技術對術語文檔矩陣進行聚類,例如 SVD(這將是所謂的“潛在語義分析”)或非負矩陣分解。後者可以看作是聚類,它可以同時聚類矩陣的行和列。
例如,您可以通過以下方式提取關鍵字
from sklearn.decomposition import NMF nmf = NMF(n_components=k, random_state=1).fit(X) feature_names = vectorizer.get_feature_names() for topic_idx, topic in enumerate(nmf.components_): print("Topic #%d:" % topic_idx) print(" ".join([feature_names[i] for i in topic.argsort()[:-10-1:-1]])) print()
代碼來源:[6]
儘管這裡的示例是在 python scikit-learn 中,但我認為為 R 找到一些示例應該不是什麼大問題
來源
- [1]:http ://scikit-learn.org/stable/auto_examples/cluster/plot_ward_structured_vs_unstructured.html
- [2]:http ://scikit-learn.org/stable/auto_examples/text/document_clustering.html#example-text-document-clustering-py
- [3]:拉森、比約納和青松千夏。“使用線性時間文檔聚類進行快速有效的文本挖掘。” (pdf)
- [4]:切割,道格拉斯 R.,等人。“Scatter/gather:一種基於集群的瀏覽大型文檔集合的方法。” (pdf)
- [5]:http ://scikit-learn.org/stable/modules/generated/sklearn.cluster.SpectralClustering.html
- [6]:http ://scikit-learn.org/stable/auto_examples/applications/topics_extraction_with_nmf.html
- [7]:Dhillon、Inderjit S.、Yuqiang Guan 和 Brian Kulis。“核 k 均值:譜聚類和歸一化切割。” (pdf)
- [8]:Schütze、Hinrich 和 Craig Silverstein。“有效文檔聚類的預測。” (acm網站)