聚类文本文档并获取重复的***术语

Posted

技术标签:

【中文标题】聚类文本文档并获取重复的***术语【英文标题】:Clustering text documents and obtaining duplicate top terms 【发布时间】:2017-01-05 16:41:30 【问题描述】:

我发现this post 中的代码非常有用。 (我会对该帖子添加评论,但我需要 50 点声望。)

我在上面的帖子中使用了相同的代码,但添加了一个我一直用来调试我自己的集群代码的测试文档。由于某种原因,一个文档中的一个词出现在两个集群中。

代码是:

更新:我在下面的文档中添加了“独特的句子”。

documents = ["I ran yesterday.", 
                "The sun was hot.", 
                "I ran yesterday in the hot and humid sun.", 
                "Yesterday the sun was hot.",
                "Yesterday I ran in the hot sun.",
                "Unique sentence." ]

vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(documents)

#cluster 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 clusters    
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

我收到的输出是:

更新:我更新了下面的输出以反映上面的“独特句子”。

集群 0: 太阳 热的 昨天 跑了 湿 独特 句子 集群 1: 独特 句子 昨天 太阳 跑了 湿 热的

您会注意到,“潮湿”在两个集群中都作为最重要的术语出现,即使它仅出现在上述文档的 1 行中。我希望一个独特的词,例如在这种情况下的“潮湿”,将成为其中一个集群中的最高词。

谢谢!

【问题讨论】:

【参考方案1】:

不一定。您正在使用的代码创建语料库的词袋(不包括停用词)的向量空间(我忽略了 tf-idf 权重。)。查看您的文档,您的向量空间大小为 5,带有一个单词数组(忽略顺序):

word_vec_space = [yesterday, ran, sun, hot, humid]

每个文档都分配有一个数字向量,用于判断它是否包含“word_vec_space”中的单词。

"I ran yesterday." -> [1,1,0,0,0]
"The sun was hot." -> [0,0,1,1,0]
...

在执行 k-mean 聚类时,您在向量空间中选择 k 个起点并让这些点四处移动以优化聚类。您最终得到的两个簇质心都包含'humid' 的非零值。这是因为包含'humid'的一个句子也有'sun''hot''yesterday'

【讨论】:

谢谢。关于:这是因为包含“潮湿”的一个句子也有“太阳”、“热”和“昨天”。我认为每个集群都有唯一的成员,在这种情况下是唯一的单词。看起来如果集群成员有共同的词可以属于超过 1 个集群。然而,由于我之前的示例“潮湿”句子有共享词(“太阳”、“热”和“昨天”),我对此进行了测试。我更新了示例以包含一个独特的句子。我还更新了示例输出。唯一句子中的单词也出现在两个集群中(即“唯一”和“句子”)。【参考方案2】:

TF*IDF 告诉您单词(在本例中为列)对于特定文档(在本例中为行)的代表性。代表我的意思是:一个词在一个文档中经常出现,但在其他文档中不经常出现。 TF*IDF 值越高,这个词就越能代表一个特定的文档。

现在让我们开始了解您实际使用的价值观。在 sklearn 的 kmeans 中,您使用返回变量 cluster_centers。这为您提供了每个词的每个集群的坐标,这是一个 TF*IDF 权重数组。需要注意的是,这些只是词频的某种抽象形式,不再与特定文档相关联。接下来,numpy.argsort() 为您提供对数组进行排序的索引,从最低 TF*IDF 值的索引开始。所以在那之后你用 [:, ::-1] 颠倒它的顺序。现在你有了最开始的那个聚类中心最有代表性的词的索引。

现在,让我们多谈谈 k-means。 k-means 随机初始化它的 k-cluster 中心。然后将每个文档分配给一个中心,然后重新计算聚类中心。重复此过程,直到满足最小化文档与其最近中心之间的平方距离之和的优化标准。这对您意味着,由于随机初始化,每个集群维度很可能没有 TF*IDF 值 0。此外,一旦满足优化标准,k-means 就会停止。因此,一个中心的 TF*IDF 值仅仅意味着分配给其他集群的文档的 TF*IDF 比其他集群中心更靠近这个中心。

另外一点是,使用 order_centroids[i, :10],每个集群中最有代表性的 10 个单词都会被打印出来,但是由于你总共只有 5 个单词,所有单词都会被打印出来无论哪种方式,只是顺序不同。

我希望这会有所帮助。顺便说一句,k-means 不能保证您找到全局最优值,并且可能会陷入局部最优值,这就是为什么它通常以不同的随机起点运行多次。

【讨论】:

【参考方案3】:

为什么集群会有不同的***术语?

考虑到集群工作(通常它不会 - 当心),您认为这些集群是坏的还是好的:

香蕉果实 苹果果实 苹果电脑 Windows 电脑 百叶窗

如果我能得到这样的集群,我会很高兴(事实上,我相信我看到了一个错误,因为这些结果太棒了。文本集群总是处于不工作的边缘)。

对于文本集群,主要是单词组合,而不仅仅是单个单词。苹果水果和苹果电脑不一样。

【讨论】:

感谢您的所有回复。基于 Kmeans 和 Kmeans++ 结果的其他视觉示例,我(天真地)期望集群文档是唯一的,就像这个一般示例 link 文档将由 k-means 唯一分配,但每个词都将在每个集群中具有一定的价值。在 LDA(一种更流行的文本技术)中,我相信每个文档都有一个主题分布,每个主题都有一个词分布。

以上是关于聚类文本文档并获取重复的***术语的主要内容,如果未能解决你的问题,请参考以下文章

文本文档聚类 - 非均匀聚类

Web 简单文件下载

比 tf/idf 和余弦相似度更好的文本文档聚类?

在 Python 中使用 h2o4gpu K-Means 对文本文档进行聚类

快速保存多行文本

使用 sklearn tf-idf 查找矢量化文本文档中的簇数