2016-04-03 8 views
1

Ich versuche, die folgende Gleichung zu vektorisieren. Ich habe es in nicht-vektorisierte Form arbeitenNumpy Vektorisierungsfehler

Variances

print(K) 
print(N) 
print(gamma.shape) 
print(means.shape) 
print(img.shape) 
print(N_k.shape) 

ergibt

2 
1000 
(1000, 2) 
(2,) 
(1000) 
(2,) 



self.variances = np.sum(gamma * (img - self.means) ** 2)/N_k 

Das gibt mir die falsche Antwort. Die Antwort hat die richtige Form, aber die Werte sind weg

jedoch

self.variances = [ np.sum([gamma[n][k] * (img[n] - self.means[k]) ** 2 for n in range(0, N)])/N_k[k] for k in range(0, K) ] 

funktioniert. Ich bin neu in numpy so bin ich sicher, dass ich einen dummen Fehler gemacht habe, aber ich bin nicht in der Lage es in diesem Fall

Antwort

3

Verwenden

self.variances = np.sum(gamma * (img[:, None] - self.means) ** 2, axis=0)/N_k 

statt

Dank zu finden
self.variances = np.sum(gamma * (img - self.means) ** 2)/N_k 

import numpy as np 

N, K = 10, 20 
gamma = np.random.random((N, K)) 
means = np.random.random(K) 
N_k = np.random.random(K) 
img = np.random.random(N) 

expected = np.array([ np.sum([gamma[n][k] * (img[n] - means[k]) ** 2 for n in range(0, N)])/N_k[k] for k in range(0, K) ]) 

result = np.sum(gamma * (img[:, None] - means) ** 2, axis=0)/N_k 

assert np.allclose(result, expected) 

Hinweis: img - self.means subtrahiert die entsprechenden Werte elementweise. img hat (N,) Form und self.means hat (K,) Form, so dass man von dem anderen subtrahiert ist möglich, wenn N == K, wirft jedoch einen Valueerror wenn N != K seitdem die Formen nicht kompatibel sind. Da Sie keinen Fehler erhalten haben, muss N gleich K sein.

Da Sie einen 2D-Array von Werten berechnet werden sollen, zunächst img einen 2D-Array von Form (N, 1) machen durch eine neue Achse und fügen hinzu: img[:, None].

Dann nehmen Sie Vorteil von broadcasting so , dass, wenn Sie das Array 1D subtrahieren self.means, es (N, K) zu einem 2D-Array kompatibler Form ausgestrahlt wird. Broadcasting fügt standardmäßig neue Achsen auf die linke hinzu. Somit kann das Array der Form (K,) automatisch zu einem Array der Form (N, K) übertragen werden. (Dies erklärt auch, warum wir img[:, None] verwenden mussten, um explizit eine neue Achse auf der rechten Seite hinzuzufügen.)

Jetzt wird (img[:, None] - self.means) ein 2D-Array der Form (N, K) sein.


Beachten Sie auch, dass es wichtig ist, axis=0 angeben, wenn np.sum Aufruf weil die Summierung über die erste Achse der Länge N erfolgt. Da Python 0-basierte Indexierung verwendet, entspricht die erste Achse axis=0.

Wenn Sie keine Achse angeben, wird standardmäßig np.sum über alle Achsen summiert.

+1

Oder mit 'np.einsum':' diffs = img [:, None] - self_means; out = np.einsum ('ij, ij, ij-> j', gamma, diffs, diffs)/N_k'. Könnte schneller sein. – Divakar

+0

Nun, es stellt sich heraus, dass Img tatsächlich (N, 1) in Form ist. Dieser Code war genug, um mich in die richtige Richtung zu bringen. Vielen Dank – Shaun