2016-12-04 111 views
0

我有一個我認爲需要直觀距離函數的聚類問題。每個實例都有一個x,y座標,但也有一組描述它的屬性(每個實例的編號不同)。理想情況下,可以將pythonobjects(類的實例)傳遞給它,並根據其內容任意比較它們。在Python中使用自定義距離函數的聚類算法

我想將距離表示爲x,y值之間的歐氏距離的加權總和以及像測量其他屬性的集合重疊一樣的jaccard索引。例如:

dist = (euclidean(x1, y1, x2, y2) * 0.6) + (1-jaccard(attrs1, attrs2) * 0.4) 

我發現的大多數聚類算法和實現都將實例特徵轉換爲數字。例如,在sklearn中使用dbscan,爲了完成我的距離函數,我需要以某種方式將數字轉換回原始表示。

如果可以使用可以任意方式比較實例的距離函數進行聚類,那將是非常好的。例如,設想一個歐幾里得距離函數,如果它們與另一個非空間特徵相匹配,則該函數會將對象評估爲更近。

def dist(ins1, ins2): 
    euc = euclidean(ins1.x, ins1.y, ins2.x, ins2.y) 
    if ins1.feature1 == ins2.feature1: 
      euc = euc * 0.9 
    return euc   

有沒有適合此方法的方法?如果羣集數量不必事先設置(但這對我來說並不重要),這也會很好。

回答

2

實際上,幾乎所有的聚類算法(除了爲k-均值,這需要數來計算意味着,很明顯),可以用任意的距離的函數使用。

在sklearn中,大多數算法接受metric="precomputed"距離矩陣而不是原始輸入數據。請仔細檢查文檔。例如DBSCAN

如果度量是「預先計算」,則X被假定爲距離矩陣並且必須是平方的。

你失去的是通過索引加速某些算法的能力。計算距離矩陣爲O(n^2),所以你的算法不可能比這更快。在sklearn中,您需要修改sklearn Cython代碼以添加新的距離函數(不幸的是,使用pyfunc會產生非常糟糕的性能)。 Java工具,如ELKI can be extended with little overhead,因爲Java的即時編譯器對此進行了優化。如果你的距離是度量那麼許多索引可以用於例如加速。 DBSCAN。

+0

謝謝!我完全忘了「預計算」模式。幸運的是O(n^2)的複雜性對我來說很好。 – user1478842