Text-Mining

自動關鍵字提取:使用餘弦相似度作為特徵

  • May 2, 2015

我有一個文檔術語矩陣,現在我想使用監督學習方法(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 找到一些示例應該不是什麼大問題

來源

引用自:https://stats.stackexchange.com/questions/149327

comments powered by Disqus