从头开始实现自定义凝聚算法

Posted

技术标签:

【中文标题】从头开始实现自定义凝聚算法【英文标题】:Implementing a custom agglomerative algorithm from scratch 【发布时间】:2012-06-02 04:33:14 【问题描述】:

我了解凝聚聚类算法,它从每个数据点开始作为单独的集群,然后将点组合成集群。

现在,我有一个 n 维空间和几个数据点,这些数据点在每个维度上都有值。我想根据以下业务规则对两个点/集群进行聚类:

如果集群之间跨维度 1 的距离 如果满足跨维度 1 的规则并且满足跨维度 2 的规则,则将它们聚类,而无需考虑其他维度...

....和类似的自定义规则。

此外,我有自己的方法来定义和测量任何特定维度中任何两个集群之间的距离。维度可能只包含字符串,我想定义自己的字符串距离度量。在另一个维度中,它可能包含位置的名称,并且沿该维度的两点之间的距离是所命名的位置之间的地理距离,其他维度也是如此。

是否有一个框架/软件可以让我实现这种定义自定义距离度量的方式,然后实现凝聚聚类?当然,当业务规则在任何时间点都不满足时,聚合聚类就停止了,最后我们在n维空间中形成了聚类。

谢谢 阿布舍克S

【问题讨论】:

我想使用 JAVA,如果有框架,最好使用框架或我 :-) 【参考方案1】:

你可以用Weka来做到这一点。

您必须实现Distance Function,并使用setDistanceFunction(DistanceFunction distanceFunction) 方法将其传递给Hierarchical Clusterer。

Weka 中其他可用的集群器有:Cobweb、EM、FarthestFirst、FilteredClusterer、MakeDensityBasedClusterer、RandomizableClusterer、RandomizableDensityBasedClusterer、RandomizableSingleClusterEnhancer、SimpleKMeans、SingleClustererEnhancer。

距离函数示例,来自 NormalizableDistance 类:

  /** Index in ranges for MIN. */
  public static final int R_MIN = 0;

  /** Index in ranges for MAX. */

  public static final int R_MAX = 1;

  /** Index in ranges for WIDTH. */
  public static final int R_WIDTH = 2;

  /** the instances used internally. */
  protected Instances m_Data = null;

  /** True if normalization is turned off (default false).*/
  protected boolean m_DontNormalize = false;

  /** The range of the attributes. */
  protected double[][] m_Ranges;

  /** The range of attributes to use for calculating the distance. */
  protected Range m_AttributeIndices = new Range("first-last");

  /** The boolean flags, whether an attribute will be used or not. */
  protected boolean[] m_ActiveIndices;

  /** Whether all the necessary preparations have been done. */
  protected boolean m_Validated;


public double distance(Instance first, Instance second, double cutOffValue, PerformanceStats stats) 
    double distance = 0;
    int firstI, secondI;
    int firstNumValues = first.numValues();
    int secondNumValues = second.numValues();
    int numAttributes = m_Data.numAttributes();
    int classIndex = m_Data.classIndex();

    validate();

    for (int p1 = 0, p2 = 0; p1 < firstNumValues || p2 < secondNumValues; ) 
      if (p1 >= firstNumValues)
        firstI = numAttributes;
      else
        firstI = first.index(p1); 

      if (p2 >= secondNumValues)
        secondI = numAttributes;
      else
        secondI = second.index(p2);

      if (firstI == classIndex) 
        p1++; 
        continue;
      
      if ((firstI < numAttributes) && !m_ActiveIndices[firstI]) 
        p1++; 
        continue;
      

      if (secondI == classIndex) 
        p2++; 
        continue;
      
      if ((secondI < numAttributes) && !m_ActiveIndices[secondI]) 
        p2++;
        continue;
      

      double diff;

      if (firstI == secondI) 
        diff = difference(firstI,
                  first.valueSparse(p1),
                  second.valueSparse(p2));
        p1++;
        p2++;
      
      else if (firstI > secondI) 
        diff = difference(secondI, 
                  0, second.valueSparse(p2));
        p2++;
      
      else 
        diff = difference(firstI, 
                  first.valueSparse(p1), 0);
        p1++;
      
      if (stats != null)
        stats.incrCoordCount();

      distance = updateDistance(distance, diff);
      if (distance > cutOffValue)
        return Double.POSITIVE_INFINITY;
    

    return distance;
  

表明您可以分别处理各个维度(在 Weka 中称为属性)。因此,您可以为每个维度/属性定义不同的距离。

关于避免将某些实例聚集在一起的业务规则。我认为你可以创建一个距离函数,当业务规则不满足时返回Double.positiveInfinity

【讨论】:

我们可以在不同的维度上分别设置距离函数吗?另外,只有当业务规则匹配时,我们是否可以编写业务规则来聚类两个点/集群? 我更新了我的答案。希望现在它能回答你所有的问题:) 非常感谢 Vitalij。你能解释一下代码吗?我无法了解少数变量(例如 m_Data、m_ActiveIndices)是什么,因为它们没有在方法中声明。有没有你知道的参考教程告诉我这些变量是什么? 我在示例中添加了变量声明和 cmets。最好的指南是weka.wikispaces.com/Use+WEKA+in+your+Java+code 谢谢!您现在是否可以从那里详细了解完整的 WEKA 架构?我想了解存在的各种类和包,然后相应地对其进行编程。【参考方案2】:

ELKI 是另一种选择。它比 Weka 拥有更多的聚类算法(主要用于分类)。他们甚至有一个 Wiki Tutorial 解释如何实现自定义距离函数(然后你应该能够在层次聚类中使用它): distance function tutorial.

请注意,“业务规则”并不是指定距离函数的一种非常常见的方式...

【讨论】:

我想为跨维度计算的距离指定业务规则。你知道有一个框架可以让我指定这些业务规则,然后只有在业务规则匹配的情况下,该框架才会对两个数据点/集群进行聚类? 匿名,你知道我在哪里可以学习如何使用 ELKI 编程吗?看起来很有趣。 你试过我贴的教程链接了吗?不,我永远不会触及商业规则。他们被称为“商业”垃圾是有原因的。 是的,我知道如何提及自定义距离度量,但是我想知道如何将该距离函数插入到更大的集群代码中。 试试图形用户界面。这个对我有用。我在那里配置聚类算法,并将我的类名作为距离函数。 GUI 是完成这一切的最简单方法,不必费心用 Java 完成。

以上是关于从头开始实现自定义凝聚算法的主要内容,如果未能解决你的问题,请参考以下文章

UIGestureRecognizer 从头开始​​制作 UISlider

如何实现自定义控件的目标动作机制?

自定义文本视图的自动布局支持

对齐自定义视图的问题

从头开始实施 dropout

动态自定义 django 管理列?