聚类:在一个大型集合中查找已关闭项目的组


Clustering: finding groups of close items within a large collection

我有一个项目数组(大约5000个项目,每个项目都是一个英文单词)和一个项目对之间的距离函数。我想在数组中找到一组项目,其中一组项目中的所有项目都满足距离标准(例如,每对项目的距离都小于2)。小组通常应该尽可能大,但没有正式的定义或硬性要求。

我的实现语言是PHP,但我正在寻找关于能够有效处理这一问题的算法的一般建议。

更新:我想我可以通过构建一个图来解决这个问题,其中顶点是项目,并且满足距离约束的项目之间有一条边。一旦我构建了图,我就可以运行像Bron–Kerbosch这样的算法来列出所有的最大集团。如果成功的话,我会更新,但在此期间,请随时添加您的想法。

这个函数是如何定义的?它是预先计算的吗?如果是这样,您可以迭代计算的函数表示,并根据您的标准检索成对的单词。如果没有,你就别无选择,只能计算所有成对单词之间的函数(这在你的图形方法中是必要的)。我会选择随机化+近似策略,而不是Bron-Kerbosch算法,比如

http://dimacs.rutgers.edu/Workshops/Challenge10/abstracts.html#ovelgonne

http://dl.acm.org/citation.cfm?id=1933306.1934471

它基于模块化最大化方法。模性是集群中传出边的数量与集群内边的数量之比。在您的情况下,您将查找比率为0的簇,并从中选择最大的一个。这个算法真的很快,适用于我使用过的大多数数据集。尽管基于模块化的方法可能对这个问题过于夸张,但IMHO我觉得这是一个思考这个问题的好方法+这个算法的实现是在线的(论文作者的C实现)。

我所理解的问题是:

"A-G"代表单词。"#"代表两个单词之间的距离。并且你需要找出距离<=2.

  A B C D E F G
A * # # # # # #
B   * # # # # #
C     * # # # #
D       * # # #
E         * # #
F           * #
G             *

基本上它需要两级循环,我们可以做的是减少比较时间,只比较上面矩阵中的"#"部分。以下是PHP中的代码:

$result = array();
while ( ($word = array_shift($arrWordList)) !== NULL ) {
    foreach ($arrWordList as $otherWord ) {
        if ( calc_dist($word, $otherWord) <= 2 ) {
            $result[] = array($word, $otherWord);
        }
    }
}

您可以使用$result继续执行某些操作。

考虑到您希望您的标准适用于组的所有成员,您需要一个允许重叠组的聚类算法。这是一个非常复杂的主题,所以我能做的最好的事情就是指导你阅读关于聚类算法的文献,特别是为重叠组设计的C-Means聚类。