2016-08-31 54 views
3

我有一個NumPy ndarray它是整形(32,1024),並保存32個信號測量,我想合併成一個1024個單元的長陣列,對於每個32都有不同的權重。我使用的是numpy.average,但我的權重很複雜,average根據拋出結果的總和來執行權重的歸一化。NumPy ndarray廣播形狀(X,)與(X,1)

看着平均代碼,我意識到我可以通過將權重乘以信號數組然後對第一個軸進行求和來完成同樣的任務。但是,當我嘗試乘以(32,1024)信號數組乘以我的(32)權重數組時,由於(32,)無法廣播到(32,1024),所以我得到一個尺寸不匹配。如果我重塑的權重陣列(32,1),然後一切正常,但是這導致相當醜陋的代碼:

avg = (weights.reshape((32, 1)) * data).sum(axis=0) 

任何人都可以解釋爲什麼與NumPy不會讓我的(32)陣列廣播到(32,1024)和/或建議執行加權平均的替代的更簡潔的方式?

+1

numpy可以擴展(32,)到'(1,32)'到'(1024,32)';但你必須授予它將'(32,)'擴展到'(32,1)'的權限。這避免了在其他情況下的含糊性,例如,將(32,)乘以(1024,)。更多關於這個在我最近的答案,http://stackoverflow.com/a/39238203/901925 – hpaulj

回答

4

關於爲什麼(32,)無法播放到(32, 1024)的問題,這是因爲形狀沒有正確對齊。爲了把它變成一個原理,我們有:

weights :   32 
data : 32 x 1024 

我們需要對齊只有軸,這是weights第一軸對準的data第一軸。所以,正如你發現的一種方法是reshape2D,這樣我們最終會得到一個單獨的維度作爲第二個軸。回到原理圖,我們將使用修改後的版本:

weights : 32 x 1 
data : 32 x 1024 

現在,我們可以執行這些元素操作。

我們可以明確地引入新中軸線與None/np.newaxis,從而取代reshaping,像這樣 -

(weights[:,None]*data).sum(0) 

讓我們來看看爲整潔的替代品!

一個整潔,或許直觀的方式將與np.einsum -

np.einsum('i,ij->j',weights,data) 

另一種方法是使用​​矩陣乘法,因爲我們失去了weights第一軸反對data第一軸,像這樣 -

weights.dot(data) 
+0

清楚和徹底的答案,謝謝。我不知道'np.einsum' - 雖然它確實是一個整潔的方法,但我不認爲這對於不熟悉語法的人來說顯而易見。 'np.dot'風格更接近於「合理的」,並且非常緊湊。 –

相關問題