Distanza di Wasserstein a coppie su 2 array

Oct 07 2020

Cerco di confrontare le formazioni sportive e quindi ho bisogno di confrontare come distribuzioni simili di coordinate di punti (x, y) sono per raggrupparle alla fine. Sto lavorando con un array 3D della seguente forma:

import scipy.spatial.distance as distance
from scipy.optimize import linear_sum_assignment
from sklearn.metrics import pairwise_distances
import numpy as np

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]]])

Ho implementato la seguente metrica personalizzata per la distanza di Wasserstein (la l e k è solo per il diverso ridimensionamento dei dati per confrontare formazioni di diversa densità):

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

La mia domanda è: come implementare il confronto a coppie tramite sklearn, finora sono arrivato a:

def pairwise_wasserstein(points):
    """
    Helper function to perform the pairwise distance function of all points within 'points' parameter

    """
    # return pairwise_distances(points, metric=wasserstein_distance_function)
    # print(points)
    return pairwise_distances(points, metric=wasserstein_distance_function)

che mi lancia o a

ValueError: setting an array element with a sequence.

o un

ValueError: Found array with dim 3. check_pairwise_arrays expected <= 2.

errore. Capisco che abbia a che fare con i miei dati che sono un array np 3D, ma per semplici confronti, ad es.

wasserstein_distance_function(data[0], data[1])

restituisce un valore valido. Qualche indizio su come farlo funzionare per un array per forse 1000 formazioni per trovare distanze a coppie che posso inserire in un algoritmo di AgglomerativeClustering? Molte grazie!

Risposte

2 KimTang Oct 08 2020 at 10:47

Il problema è che il tuo wasserstein_distance_function()richiede che l'input sia 2D, ma pairwise_wasserstein()richiede anche l'input 2D. E poiché pairwise_wasserstein()divide il tuo input per calcolarlo a coppie, dividerà i dati 2D in dati unidimensionali, che non funzioneranno più con i tuoi wasserstein_distance_function(). E quando fornisci dati 3D a pairwise_wasserstein(), genera un errore perché non può funzionare con quello.

Suggerirei di scrivere solo il tuo metodo di supporto, che itera tutti i punti dati a coppie e calcola la distanza di Wasserstein per te.

Suggerimento per una possibile soluzione:

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]))

Esempio di input con 4 punti dati:

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]]])

Output di esempio:

First index:  0 , Second index:  1 , Distance:  100.80000000000005
First index:  0 , Second index:  2 , Distance:  76.4
First index:  0 , Second index:  3 , Distance:  96.32000000000002
First index:  1 , Second index:  2 , Distance:  215.00000000000003
First index:  1 , Second index:  3 , Distance:  55.68000000000002
First index:  2 , Second index:  3 , Distance:  186.88