使用 Weka 在 Java 中进行文档聚类
Posted
技术标签:
【中文标题】使用 Weka 在 Java 中进行文档聚类【英文标题】:Document Clustering in Java using Weka 【发布时间】:2013-06-08 05:32:26 【问题描述】:我正在尝试将一组关于特定主题的 Java 新闻文章聚集在一起。我使用 Crawler4J 抓取了有关特定主题的新闻网站,推出了我自己的 TF/IDF 实现与语料库进行比较(有一些原因,我没有使用内置的 Weka 或其他 TF/IDF 实现,但它们可能已经出局了这个问题的范围)并应用了一些其他特定于域的逻辑,这让我为每个文档留下了一袋单词+权重(我将其存储在值介于 0 和 1 之间的 Map 中)。我想通过查看单词权重来对类似主题的文章进行聚类,因此我开始使用 Weka 的 EM 和 SimpleKMeans 聚类器。问题是我得到的结果非常不起眼,我正试图弄清楚我是否可以做任何事情来更好地调整集群。
例如,在一个包含约 300 篇文章的玩具数据集中,如果我将单词修剪到每个文档中的前 20 个,然后使用完整的单词集作为特征,我最终会得到约 2k 的独特特征。我将每篇文章用作训练实例,并尝试一些不同的参数来调整 SimpleKMeans 集群器(例如 ~20-30 个集群,最大迭代 100 次)。当我一目了然地查看数据时,我发现很多文章的关键字似乎非常密切相关,所以我期望高质量的结果和包含约 5-10 篇文章的集群。不幸的是,结果通常是一个集群有超过一半的文章,一堆集群每个有 1 篇文章,还有一些散乱者有 2-5 篇左右的文章。
这些结果是预期的,还是有办法获得更高质量的结果?请注意,我还研究了 LingPipe 和其他提供集群功能的框架,并尝试滚动我自己的 EM 实现(取得了适度但不是很大的成功)。提前感谢您的帮助!
【问题讨论】:
在将 tf-idf 向量输入 k-means 之前,您是否对其进行了标准化?这通常会有所帮助(使用 L2,又名欧几里得,归一化)。语言模型加权也可能比 tf-idf 效果更好。 谢谢,我将不得不研究标准化,因为我不明白它的作用。看起来 Weka 提供了一个可能有用的 Normalize 向量? 【参考方案1】:有几个技巧可以使 k-means 适用于文本:
-
去掉只出现在少数文档(具有低 df)中的术语。这些人为地扩大了向量空间中的距离。
标准化向量。这有点帮助,因为它消除了文档之间的长度差异。正如@Anony-Mousse 所指出的,它还使文档向量具有相似的差异。
在进行实际聚类之前,使用LSA(也就是截断的SVD)执行降维。这很有帮助。 (请务必同时标准化 LSA 结果。)
对规范化为何起作用的简短说明:假设您有三个文档 d₁, d₂, d₃,以及很小的词汇表 cat, dog, tax。术语文档矩阵(原始计数或 tf-idf,无关紧要)看起来像
| cat | dog | tax
d₁ | 100 | 100 | 0
d₂ | 10 | 10 | 0
d₃ | 0 | 0 | 100
现在我们要做 2-means。我们可以合理地期望找到一个宠物集群 d₁, d₂ 和一个金融单例集群 d₃。然而,这对之间的距离是
D(d₁, d₂) = 127.28
D(d₁, d₃) = 173.21
D(d₂, d₃) = 101.00
因此,像 k-means 这样的基于密度的方法将倾向于将 d₂ 与 d₃ 分组。通过对向量进行归一化,您可以有效地将 d₁ 和 d₂ 映射到同一个向量 [0.71, 0.71, 0],因此 D(d₁, d₂) = 0 并且它们将始终位于同一个簇中。
(k-应用于归一化向量的均值有时称为“球形”k-均值,因为单位向量位于以原点为中心的超球面上。)
【讨论】:
非常感谢这些信息。我已经正常化了,我的关键字的 tfidf 值在 0 和 1 之间浮动。不过,我的功能选择非常愚蠢,正如我在解释中提到的,我愚蠢的初始实现是考虑任何排名前 30 的术语记录一个特征并将其用于聚类。今晚我将尝试 LSA,示例非常少,因此任何在 Java 代码中使用 LSA 的指针都会非常有帮助。根据@Anony-Mousse 的问题,您是否确信 K-Means 将非常适合良好的特征选择,或者我应该尝试其他聚类器吗? 我玩了#1/3(修剪低频,使用LSA降低维度),结果稍微好一些。 44% 的文章仍然属于一个集群,但有 7 个集群有 5 篇以上的文章,这似乎更适合数据。如何将后 LSA 实例映射到我的原始实例?我是否依赖索引并假设订单被保留? @Tyson:没有理由不保留订单(除非您的实现确实有问题)。【参考方案2】:如果您有词袋和它们的权重,那么您应该首先计算它们之间的一些相似性度量。例如 Jacquard Similarity、Cosine Similarity....然后有了这个基础,您可以使用 K-Means 或其他聚类算法对您的文章进行聚类。
如果您知道新闻文章只能是固定类型,如体育、娱乐、历史、政治等,那么我建议您使用分类算法而不是聚类算法,这将增加您获得良好且令人印象深刻的结果的可能性。
如果真的想使用聚类算法,可以选择一些可以产生动态聚类的扩展算法(最近邻、遗传算法、质量阈值、最小生成树...)。
【讨论】:
【参考方案3】:k-means 和 EM 模型均由它们的均值向量聚类,相似度基于欧几里得。马氏距离。
问题在于平均值对于稀疏数据可能不合理。最好的体现是手段比文档稀疏。此外,甚至可能出现这些手段变得比实际文档更相似的情况。
所以恕我直言,您只是对数据使用了不合适的聚类算法。有时它可能工作正常,但有时它会失败,因为该方法是为每个轴上相同方差的密集数据设计的。
【讨论】:
感谢您的回复,尽管我承认我并不理解所有这些(并分享 larsmans 的问题)。您能否建议我应该尝试的不同聚类算法(和/或准备/过滤数据的方法)?以上是关于使用 Weka 在 Java 中进行文档聚类的主要内容,如果未能解决你的问题,请参考以下文章