thanks to insightful comments on this thread: Pairwise Wasserstein distance on 2 arrays, I was able to come up with a custom function to find a distance metric between a set of 2 dimensional arrays (10 points, with x-, y-coordinates). My next step is to find a way to feed this information into an agglomerative clustering algorithm, such as the fcluster() method of the scipy.cluster.hierarchy module.
More specifically, I would like to use the following functions to find ideally a set of n clusters for a 3 dimensional array of data. I am not sure how to tweak the pairwise-wasserstein function to retrieve the distance matrix that fcluster needs to find the cluster assignments agglomeratively.
Thanks for any ideas in advance!
import numpy as np
from scipy.optimize import linear_sum_assignment
from scipy.cluster.hierarchy import dendrogram, linkage, ward
from scipy.cluster.hierarchy import fcluster
data = np.array([[[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]],
[[5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8]],
[[1, 15], [3, 2], [1, 2], [5, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]],
[[5, 1], [7, 8], [5, 6], [7, 1], [5, 6], [7, 8], [5, 1], [7, 8], [5, 6], [7, 8]]])
def wasserstein_distance_function(f1, f2):
min_cost = np.inf
f1 = f1.reshape((10, 2))
f2 = f2.reshape((10, 2))
for l in np.linspace(0.8, 1.2, 3):
for k in np.linspace(0.8, 1.2, 3):
cost = distance.cdist(l * f1, k * f2, 'sqeuclidean')
row_ind, col_ind = linear_sum_assignment(cost)
curr_cost = cost[row_ind, col_ind].sum()
if curr_cost < min_cost:
min_cost = curr_cost
return min_cost
def pairwise_wasserstein(points):
"""
Helper function to perform the pairwise distance function of all points within 'points' parameter
"""
for first_index in range(0,points.shape[0]):
for second_index in range(first_index+1,points.shape[0]):
print("First index: ", first_index, ", Second index: ", second_index, ", Distance: ",wasserstein_distance_function(points[first_index],points[second_index]))
def find_clusters_formation(data):
"""
Method to find the clusters for the points array
"""
dist_mat = pairwise_wasserstein(data)
Z = ward(dist_mat)
cluster = fcluster(Z, 3, criterion='maxclust')