我如何可视化用于 kmeans 聚类的 tf-idf 向量的数据点?

Posted

技术标签:

【中文标题】我如何可视化用于 kmeans 聚类的 tf-idf 向量的数据点?【英文标题】:How do i visualize data points of tf-idf vectors for kmeans clustering? 【发布时间】:2015-02-14 03:33:58 【问题描述】:

我有一个文档列表和整个语料库中每个唯一单词的 tf-idf 分数。 如何在二维图上将其可视化,以衡量运行 k-means 需要多少个集群?

这是我的代码:

sentence_list=["Hi how are you", "Good morning" ...]
vectorizer=TfidfVectorizer(min_df=1, stop_words='english', decode_error='ignore')
vectorized=vectorizer.fit_transform(sentence_list)
num_samples, num_features=vectorized.shape
print "num_samples:  %d, num_features: %d" %(num_samples,num_features)
num_clusters=10

如您所见,我能够将我的句子转换为 tf-idf 文档矩阵。但我不确定如何绘制 tf-idf 分数的数据点。

我在想:

    添加更多变量,例如文档长度和其他内容 做 PCA 得到二维的输出

谢谢

【问题讨论】:

这个问题应该是数据科学,而不是***? 【参考方案1】:

我目前正在做类似的事情,试图以 2D 绘制文本数据集的 tf-idf 分数。我的方法,类似于其他 cmets 中的建议,是使用 scikit-learn 中的 PCA 和 t-SNE。

import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

num_clusters = 10
num_seeds = 10
max_iterations = 300
labels_color_map = 
    0: '#20b2aa', 1: '#ff7373', 2: '#ffe4e1', 3: '#005073', 4: '#4d0404',
    5: '#ccc0ba', 6: '#4700f9', 7: '#f6f900', 8: '#00f91d', 9: '#da8c49'

pca_num_components = 2
tsne_num_components = 2

# texts_list = some array of strings for which TF-IDF is being computed

# calculate tf-idf of texts
tf_idf_vectorizer = TfidfVectorizer(analyzer="word", use_idf=True, smooth_idf=True, ngram_range=(2, 3))
tf_idf_matrix = tf_idf_vectorizer.fit_transform(texts_list)

# create k-means model with custom config
clustering_model = KMeans(
    n_clusters=num_clusters,
    max_iter=max_iterations,
    precompute_distances="auto",
    n_jobs=-1
)

labels = clustering_model.fit_predict(tf_idf_matrix)
# print labels

X = tf_idf_matrix.todense()

# ----------------------------------------------------------------------------------------------------------------------

reduced_data = PCA(n_components=pca_num_components).fit_transform(X)
# print reduced_data

fig, ax = plt.subplots()
for index, instance in enumerate(reduced_data):
    # print instance, index, labels[index]
    pca_comp_1, pca_comp_2 = reduced_data[index]
    color = labels_color_map[labels[index]]
    ax.scatter(pca_comp_1, pca_comp_2, c=color)
plt.show()



# t-SNE plot
embeddings = TSNE(n_components=tsne_num_components)
Y = embeddings.fit_transform(X)
plt.scatter(Y[:, 0], Y[:, 1], cmap=plt.cm.Spectral)
plt.show()

【讨论】:

这很棒。如何在散点图中按名称标记点? 如果有人希望在稀疏表示上执行 PCA,sklearn 的 TruncatedSVD 就是专门为此目的而构建的。【参考方案2】:

我想您正在寻找 t-SNE,作者 van der Maaten 和 Hinton。

出版物: http://jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf

This links 到 IPython Notebook 以使用 sklearn 执行此操作。

简而言之,t-SNE 类似于 PCA,但更擅长在 2-dim 上对高维空间中相关的对象进行分组。地块的空间。

【讨论】:

【参考方案3】:

PCA 是一种方法。对于 TF-IDF,我还使用 Scikit Learn 的歧管包进行非线性降维。我觉得有帮助的一件事是根据 TF-IDF 分数标记我的分数。

这是一个示例(需要在开头插入您的 TF-IDF 实现):

from sklearn import manifold

# Insert your TF-IDF vectorizing here

##
# Do the dimension reduction
##
k = 10 # number of nearest neighbors to consider
d = 2 # dimensionality
pos = manifold.Isomap(k, d, eigen_solver='auto').fit_transform(.toarray())

##
# Get meaningful "cluster" labels
##
#Semantic labeling of cluster. Apply a label if the clusters max TF-IDF is in the 99% quantile of the whole corpus of TF-IDF scores
labels = vectorizer.get_feature_names() #text labels of features
clusterLabels = []
t99 = scipy.stats.mstats.mquantiles(X.data, [ 0.99])[0]
clusterLabels = []
for i in range(0,vectorized.shape[0]):
    row = vectorized.getrow(i)
    if row.max() >= t99:
        arrayIndex = numpy.where(row.data == row.max())[0][0]
        clusterLabels.append(labels[row.indices[arrayIndex]])
    else:
        clusterLabels.append('')
##
# Plot the dimension reduced data
##
pyplot.xlabel('reduced dimension-1')
pyplot.ylabel('reduced dimension-2')
for i in range(1, len(pos)):
    pyplot.scatter(pos[i][0], pos[i][1], c='cyan')
    pyplot.annotate(clusterLabels[i], pos[i], xytext=None, xycoords='data', textcoords='data', arrowprops=None)

pyplot.show()

【讨论】:

我刚刚注意到您的“来自可靠和/或官方来源”的警告。我现在将保留我的原始答案,但可能有时间来生成更学术的答案。【参考方案4】:

根据您的要求,您可以绘制 scipy.sparse.csr.csr_matrix

TfidfVectorizer.fit_transform() 会给你(文档 ID,术语号)tf-idf 分数。现在您可以按术语创建一个 numpy 矩阵作为 x 轴并将文档作为 y 轴,第二个选项是 plot(temm , tf-tdf score) 或者您可以使用 (term , document, frequency) 绘制 3-d在这里你也可以申请 PCA。

只需从 scipy.sparse.csr.csr_matrix 创建一个 numpy 矩阵并使用 matplotlib。

【讨论】:

您能否展示一些关于如何使用第一种和/或第二种方法的代码?

以上是关于我如何可视化用于 kmeans 聚类的 tf-idf 向量的数据点?的主要内容,如果未能解决你的问题,请参考以下文章

用于在 KMeans 聚类中选择适当数量的聚类的轮廓索引

matlab如何求kmean聚类中心点的坐标和各个中心包含的样本点数,要用到那些命令

Kmeans聚类定义KMeans聚类的步骤Kmeans聚类常见问题及改进Kmeans聚类的变形Kmeans聚类的优缺点

spark.mllib源码阅读-聚类算法1-KMeans

spark.mllib源码阅读-聚类算法1-KMeans

当我们只向它提供单个单词的 tfidf 向量时,kmeans 是如何知道如何对文档进行聚类的?