2016-04-03 97 views
1

我在嘗試向量化以下等式。我有它在非量化的形式工作Numpy矢量化錯誤

Variances

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

產生

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



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

這給了我錯誤的答案。答案有正確的形狀,但該值是遙遠

然而

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

作品。我是新來numpy的,所以我敢肯定,我犯了一個愚蠢的錯誤,但我無法找到它在這種情況下

感謝

回答

3

使用

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

,而不是

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) 

請注意img - self.means減去相應的值元素img已成形(N,)self.means的形狀爲(K,),因此如果N == K與另一個相減,則可能會產生ValueError,但如果N != K因形狀不兼容而可能會產生ValueError。由於您沒有收到錯誤,因此N必須等於K

由於您要計算二維數組值,因此首先通過添加新軸img形成一個形狀爲(N, 1)的二維數組:img[:, None]

然後取的 broadcasting所以 優點,即當你減去1D陣列self.means,它將廣播到2D 陣列兼容形狀(N, K)的。廣播默認添加新軸 左側。因此,形狀(K,)的陣列可以自動地廣播到形狀爲(N, K)的 陣列。 (這也解釋了爲什麼我們需要使用img[:, None]在右側明確添加一個新軸。)

現在(img[:, None] - self.means)將是形狀爲(N, K)的二維數組。


還要注意,調用np.sum時,因爲求和是在長度N的第一軸進行指定axis=0是很重要的。由於Python使用基於0的索引,因此第一個軸對應於axis=0

如果不指定軸,則默認情況下,np.sum總計在所有軸上。

+1

或'np.einsum':'diffs = img [:,None] - self_means; out = np.einsum('ij,ij,ij-> j',gamma,diffs,diffs)/ N_k'。可能會更快。 – Divakar

+0

事實證明,img實際上是(N,1)的形狀。這段代碼足以讓我走向正確的方向。謝謝 – Shaun