簡體   English   中英

從頭開始實施自定義凝聚算法

[英]Implementing a custom agglomerative algorithm from scratch

我知道凝聚聚類算法,它以每個數據點作為單個聚類開始然后將點組合成聚類的方式。

現在,我有一個n維空間和幾個數據點,每個維度都有值。 我想根據業務規則聚類兩個點/集群,如:

  • 如果跨越維度1的集群之間的距離<T1,則集群兩個點c1和c2,並且跨越維度2的距離<T2,......和跨越維度的距離n <Tn。
  • 如果滿足維度1的規則並且滿足維度2的規則,則集群它們而不必擔心其他維度...

....和類似的自定義規則。

另外,我有自己的方法來定義和測量任何特定維度中任意兩個聚類之間的距離。 維度可能只是字符串,我想定義自己的字符串距離度量。 在另一個維度中,它可以包含位置的名稱,並且沿着該維度的兩個點之間的距離是命名的位置之間的地理距離,對於其他維度也是如此。

是否有框架/軟件可以讓我實現這種定義自定義距離指標的方式,然后實施凝聚聚類? 當然,當在任何時間點都不滿足業務規則時,凝聚聚類停止,並且我們在最后的n維空間中形成聚類。

謝謝Abhishek S.

你可以用Weka來做。

您必須實現距離函數 ,並使用setDistanceFunction(DistanceFunction distanceFunction)方法將其傳遞給Hierarchical Clusterer

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業務規則時返回Double.positiveInfinity

ELKI是另一種選擇。 它具有比Weka(它主要用於分類)更多的聚類算法。 他們甚至有一個Wiki教程,解釋了如何實現自定義距離函數(然后你應該可以在層次聚類中使用): 距離函數教程

請注意,“業務規則”不是指定距離函數的常用方法...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM