2013-12-19 39 views
7

一般問題NumPy的:多重外積

假設我有形狀(nrow,ncols,3)ndarrayv。我想計算形狀爲(nrow,ncols,3,3)的ndarray outer_array,其中包含形狀爲(3)的載體的所有外部產物,其索引爲(nrow,ncol)。當然,這是numpy.einsum存在的那種問題。 現在,我已經試過是:

outer_array = numpy.einsum("xyi,xyj->xyij",v,v.conjugate()) 

現在,我不知道,這將工作:儘管outer_array具有預期的形狀,外產品矩陣的元素不對應到我所期待的。

我認爲這是由於在einsum表達標籤的選擇:產品應該在xy來概括,因爲指數的反覆,但因爲我重用他們在輸出表達式,結果的總和是以某種方式廣播。

在另一方面,如果我寫:

outer_array = numpy.einsum("xyi,uvj->...ij",v,v.conjugate()) 

numpy的將計算外積的所有可能組合的每對(x,y)(u,v),導致形狀(ncols,nrow,ncols,nrow,3,3)的陣列,其中該對角線(u,v) = (x,y)將包含所需的輸出。

的確切的問題

如何選擇在einsum符號前兩個指標,以獲得一個數組,其中每個索引x,y在我與自身載體v的外積而不必訴諸到第二個表達式?

編輯 顯然,這種形式似乎太工作:

outer_array = numpy.einsum("...i,...j->...ij",v,v.conjugate()) 

我只能佩服numpy的廣播是多麼有用!

+4

你能發表一個輸出的例子「不對應你所期待的」嗎?你的第一種方法似乎是正確的做法。 – Jaime

+0

你確實是對的。意外結果的問題是由於另一個問題。我仍然想知道我的代碼如何管理工作,因爲索引'x'和'y'在條件中被重複並重新出現在輸出中。有人可以解釋嗎? – Bafe

+0

這可能是相關的:http://stackoverflow.com/q/17138393/1461210 –

回答

4

'xyi,xyj->xyij'工作的關鍵是在輸出字符串中重複了xy

讓我們用一個簡單的數組:

x = np.arange(6).reshape(3,2) 
np.einsum.einsum('ij->j',x) 
# array([6, 9]) # sums on the 1st dimension of `x` 

現在對於外產品。這x

In [20]: x[:,:,None]*x[:,None,:] # shape (3,2,2) 
Out[20]: 
array([[[ 0, 0], 
     [ 0, 1]], 

     [[ 4, 6], 
     [ 6, 9]], 

     [[16, 20], 
     [20, 25]]]) 

這是numpy的廣播(即添加尺寸和擴大它們)

爲例

"...i,...j->...ij",...作爲一個現有的,但匿名維度的佔位符運作更多。

等效與einsum是:

np.einsum('ij,ik->ijk',x,x) 

(我要真正做到這一點並不在過去的2名維對稱計算)。

我已經制定了一個純Python工作相似的einsum。重點在於解析參數字符串,以及它如何爲iter對象創建輸入。它在github上提供:https://github.com/hpaulj/numpy-einsum/blob/master/einsum_py.py歡迎您隨時隨地玩。它有一個debug標誌來顯示中間步驟。

用我einsum與調試輸出:

In [23]: einsum_py.myeinsum('ij,ik->ijk',x,x,debug=True) 
# ... some parsing information 
[('ij', [105, 106], 'NONE'), ('ik', [105, 107], 'NONE')] 
('ijk', [105, 106, 107], 'NONE') 
iter labels: [105, 106, 107],'ijk' 

op_axes [[0, 1, -1], [0, -1, 1], [0, 1, 2]] 

op_axes是在創建iter使用的密鑰參數,該對象在輸入和輸出端陣列的軸線迭代。它遍歷所有數組的第一個軸。 1st操作和輸出的第2軸爲1,第2操作的第2軸爲newaxis(-1)。

隨着ellipsis

In [24]: einsum_py.myeinsum('...j,...k->...jk',x,x,debug=True) 
... 
iter labels: [0, 106, 107],'0jk' 
op_axes [[0, 1, -1], [0, -1, 1], [0, 1, 2]] 

這產生相同的op_axes,因此相同的計算。

+0

非常感謝。另一個非常簡單的問題是:在輸出字符串中重複「XY」的確切效果是什麼?是否抑制了這些指數的總和? – Bafe

+0

http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#reduction-iteration - 每當可寫操作數的元素少於整個迭代空間時,該操作數正在減少。「In換句話說,這是缺少觸發求和的'xy'。 – hpaulj