カスタム距離に与えられたポイントをクラスター化したいのですが、奇妙なことに、scipyとsklearnのどちらのクラスター化メソッドも距離関数を指定できないようです。
たとえば、sklearn.cluster.AgglomerativeClustering
、私ができる唯一のことは、アフィニティマトリックスを入力することです(これは非常にメモリを大量に消費します)。このまさに行列を構築するために、sklearn.neighbors.kneighbors_graph
ですが、2点間の距離関数を指定する方法がわかりません。誰かが私を啓発できますか?
すべてのscipy階層クラスタリングルーチンは、ポイントのペアを指定する2つの1Dベクトルを受け入れ、スカラーを返すカスタム距離関数を受け入れます。たとえば、 fclusterdata
を使用します。
import numpy as np
from scipy.cluster.hierarchy import fclusterdata
# a custom function that just computes Euclidean distance
def mydist(p1, p2):
diff = p1 - p2
return np.vdot(diff, diff) ** 0.5
X = np.random.randn(100, 2)
fclust1 = fclusterdata(X, 1.0, metric=mydist)
fclust2 = fclusterdata(X, 1.0, metric='euclidean')
print(np.allclose(fclust1, fclust2))
# True
metric=
kwargの有効な入力は scipy.spatial.distance.pdist
の場合と同じです。
sklearnには、事前に計算された距離行列を使用できるDBSCANがあります(M_ijがiとjの間の距離である三角行列を使用)。しかし、これはあなたが探しているクラスタリングのタイプではないかもしれません。
さらに、他の誰かが述べたように、scipy.cluster.hierarchy.fclusterdataは事前に計算された距離メトリックも許可します。 this reply で指定されたコードのスニペットがあり、距離のNxN行列をfclusterdataが簡単に読み取れる形式に変換するコードを提供します。
import scipy.spatial.distance as ssd
# convert the redundant n*n square matrix form into a condensed nC2 array
distArray = ssd.squareform(distMatrix) # distArray[{n choose 2}-{n-i choose 2} + (j-i-1)] is the distance between points i and j
階層的クラスタリングの場合、 scipy.cluster.hierarchy.fclusterdata を使用すると、リストに含まれる任意の距離メトリックを使用できます here を介してmetric=
キーワード引数(必要なリンケージメソッドで機能する場合)。