2016-06-07 17 views
5

Supponiamo di avere le seguenti 2 allineamenti:Sum la differenza al quadrato tra 2 allineamenti NumPy

import numpy as np 
a=np.asarray([[1,2,4], 
     [3,1,2]]) 
b=np.asarray([[2,1,1], 
     [3,2,3], 
     [4,1,2], 
     [2,2,1],]) 

Per ogni a_row riga in una, desidero ottenere la somma di differenza al quadrato tra a_row e ogni riga b . La matrice risultante sarebbe un array 2 per 4. Il risultato atteso sarebbe il seguente:

array([[ 11., 5., 14., 10.], 
     [ 2., 2., 1., 3.]]) 

ho già implementato una soluzione che utilizza ciclo:

c=np.zeros((2,4)) 
for e in range(a.shape[0]): 
    c[e,:] = np.sum(np.square(b-a[e,:]),axis=1) 
print c 

cosa ho bisogno è una soluzione completamente vettorizzati, vale a dire non è richiesto alcun ciclo.

+0

Sembra come un naturale per lambda e chiusure. – duffymo

risposta

3

Qui è un approccio Numpythonic, semplicemente modificando la forma della b per essere in grado di sottrarre direttamente il a da esso:

>>> np.square(b[:,None] - a).sum(axis=2).T 
array([[11, 5, 14, 10], 
     [ 2, 2, 1, 3]]) 
+0

Ciao Kasravand, grazie per la tua risposta. Funziona con l'array campione ma ho un errore di memoria nei miei script reali. Nei miei script, la forma dell'array a è (500,3072) e la forma di b è (5000,3072). Immagino sia probabilmente perché questo metodo richiede molto la memoria? Non ho ricevuto l'errore usando il metodo loop menzionato nella mia domanda. – Allen

+0

@Allen Suggerisco 2 vie, in un primo momento se non si ha a che fare con grandi numeri è possibile convertire il proprio array [tipo] (http://docs.scipy.org/doc/numpy-1.10.1/user/basics. types.html) ad un tipo più semplice come 'int8', se non è possibile è possibile dividere l'array in array più corti e fare l'operazione separatamente, quindi concatenare il risultato. Ecco una buona risposta http://stackoverflow.com/questions/31268998/how-to-merge-two-large-numpy-arrays-if-slicing-doesnt-resolve-memory-error – Kasramvd

3

Se si ha accesso a SciPy, allora si potrebbe fare:

import scipy 
from scipy.spatial.distance import cdist 

import numpy as np 

a=np.asarray([[1,2,4], 
     [3,1,2]]) 
b=np.asarray([[2,1,1], 
     [3,2,3], 
     [4,1,2], 
     [2,2,1],]) 

x = cdist(a,b)**2 
# print x 
# array([[ 11., 5., 14., 10.], 
#  [ 2., 2., 1., 3.]]) 

Questa utilizza la funzione cdist che è vettorializzare e veloce. È possibile ottenere un po 'più di velocità usando numba o cython, ma in pratica dipende dalla dimensione degli array.

+0

Grazie Josh. Ho provato e funziona bene. Tuttavia, in questo caso, ho bisogno di una soluzione completamente vettoriale. Ad esempio, non è possibile utilizzare la funzione Scipy. – Allen

Problemi correlati