使用
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
總計在所有軸上。
或'np.einsum':'diffs = img [:,None] - self_means; out = np.einsum('ij,ij,ij-> j',gamma,diffs,diffs)/ N_k'。可能會更快。 – Divakar
事實證明,img實際上是(N,1)的形狀。這段代碼足以讓我走向正確的方向。謝謝 – Shaun