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

标签 java algorithm math frameworks cluster-analysis

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

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

  • 如果跨维度 1 的集群之间的距离 < T1,跨维度 2 的距离 < T2,... 跨维度 n 的距离 < Tn,则集群两点 c1 和 c2。
  • 如果满足跨维度 1 的规则并且满足跨维度 2 的规则,则将它们聚类而不用担心其他维度...

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

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

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

谢谢 阿布舍克 S

最佳答案

你可以用 Weka 来做.

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

Weka 中其他可用的聚类器有:Cobweb、EM、FarthestFirst、FilteredClusterer、MakeDensityBasedClusterer、RandomizableClusterer、RandomizableDensityBasedClusterer、RandomizableSingleClustererEnhancer、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

关于java - 从头开始实现自定义凝聚算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10773958/

相关文章:

algorithm - mongodb:如何找到具有指定顺序的给定记录索引?

math - F#:多项式乘法

math - 如何找到给定行中的最小数字?

java - java中删除数组中的元素

java - Hibernate - 通过更新父对象创建子对象,但需要生成子对象的 key

algorithm - 动态算法查找数组中 "accessible"数字的乘积的最大和

algorithm - 如何在 O(n) 时间内找到最小正连续子序列?

java - Java 中是否可以在没有反射的情况下进行运行时编译的类实例化和使用?

java - Junit 5 无法解析方法的参数

algorithm - 如何检查给定数字是否为 x^y 形式?