python - 理解和应用 k-means 聚类进行主题建模
问题描述
我有以下代码,我从https://pythonprogramminglanguage.com/kmeans-text-clustering/找到关于文档集群的代码。虽然我从整体上理解了 k-means 算法,但对于每个集群的顶级术语代表什么以及如何计算它,我有点难以理解?它是集群中出现频率最高的词吗?我读过的一篇博文说,最后输出的单词代表“最接近集群质心的前 n 个单词”(但实际单词“最接近”集群质心意味着什么)。我真的很想了解正在发生的事情的细节和细微差别。谢谢!
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score
documents = ["This little kitty came to play when I was eating at a restaurant.",
"Merley has the best squooshy kitten belly.",
"Google Translate app is incredible.",
"If you open 100 tab in google you get a smiley face.",
"Best cat photo I've ever taken.",
"Climbing ninja cat.",
"Impressed with google map feedback.",
"Key promoter extension for Google Chrome."]
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(documents)
true_k = 2
model = KMeans(n_clusters=true_k, init='k-means++', max_iter=100, n_init=1)
model.fit(X)
print("Top terms per cluster:")
order_centroids = model.cluster_centers_.argsort()[:, ::-1]
terms = vectorizer.get_feature_names()
for i in range(true_k):
print("Cluster %d:" % i),
for ind in order_centroids[i, :10]:
print(' %s' % terms[ind]),
print
解决方案
在这种情况下,“顶部”与将文本转换为数值数组的方式直接相关。通过使用 TFIDF,对于每个单独的文档,您可以根据每个单词在该文档中的流行程度为每个单词分配一个分数,这与整个文档集的流行程度相反。文档中得分高的词表明它比其他词更重要或更能代表该文档。
因此,对于每个集群的这一代顶级术语,它们是平均而言在该集群的文档中最重要的词。
它在这里完成的方式有效且有效,但我发现自己很难理解,而且我认为这不是特别直观,因为很难理解为什么,如果cluster_centers_
是质心的坐标,那么特征坐标数最高的是最上面的单词。我有点明白但不完全明白(如果有人想解释这是如何工作的,那就太好了!)。
我使用不同的方法来查找集群的最重要的术语,我觉得这更直观。我刚刚在包含 250 个文档的语料库上测试了您自己发布的方法,并且最上面的单词完全相同。我的方法的价值在于它可以工作,但是只要您可以提供集群分配列表(任何集群算法都应该提供),您就可以对文档进行集群,这意味着您不依赖于cluster_centers_
属性的存在。我认为它也更直观。
import numpy as np
def term_scorer(doc_term_matrix, feature_name_list, labels=None, target=None, n_top_words=10):
if target is not None:
filter_bool = np.array(labels) == target
doc_term_matrix = doc_term_matrix[filter_bool]
term_scores = np.sum(doc_term_matrix,axis=0)
top_term_indices = np.argsort(term_scores)[::-1]
return [feature_name_list[term_idx] for term_idx in top_term_indices[:n_top_words]]
term_scorer(X, terms, labels=model.labels_, target=1, n_top_words=10)
该model.labels_
属性为您提供每个文档的集群分配列表。在此示例中,我想找到集群 1 的最热门单词,因此我分配target=1
,该函数过滤X
数组,仅保留分配给集群 1 的行。然后它按行对文档中的所有分数求和,因此它只有一行和一列对于每个单词。然后它使用argsort
从最高值到最低值对该行进行排序,将这些值替换为单词的原始索引位置。最后,它使用列表推导从最高分中获取索引号n_top_words
,然后通过在 中查找这些索引来构建单词列表feature_name_list
。
推荐阅读
- javascript - 基于clientId值的同一页面上的多个highcharts?
- html - CSS - 两个弹性列
- azure - 使用 StrongSwan 的 Azure AD VPN 条件访问
- ios - 重新启用操作表操作
- android - google play 上的公开 alpha/beta 测试——听起来像良性吗?
- android - Android Volley .NET Rest 令牌授权失败
- d3.js - d3 - 如何在 x 轴上格式化日期
- android - 当文本出现时,Textinputlayout 更改 textcolorhint
- python - 无论哪个日志级别,都将消息添加到 python 日志记录
- ffmpeg - Ffmpeg:在 mp4 视频的末尾添加一段简短的音频