2014-10-26 125 views
0

我試圖做一個函數,如numpy.inner,但總結了第一個兩個數組的軸而不是最後一個軸。目前我使用tensordotrollaxis計算numpy.inner()在第一個(而不是最後一個)軸

def inner1(a, b): 
    return numpy.tensordot(numpy.rollaxis(a, 0, len(a.shape)), b, 1) 

但我想知道:有沒有更好的辦法?也許一個不需要我滾動軸?

我覺得einsum應該使這成爲可能,但我不知道如何在這裏使用它。
當我指定下標字符串時,似乎需要我對ab進行硬編碼,在此我無法真正做到,因爲對輸入的維度沒有特別的要求。

(注:我上午知道有到求和第一軸,而不是最後的性能影響,但我在這裏忽略它們)

回答

2

我想你想要的是np.tensordot(a, b, (0, 0))

+0

您確定這種方式有效嗎?這失敗了:'einsum('i ...,i ...-> ...',((1,2)),((1,3)))' – Mehrdad 2014-10-26 23:18:19

+0

這一切都取決於你想要什麼去做。在這種情況下,我認爲你想,'einsum('ij ...,ik ...-> jk ...',((1,2)),((1,3)))''。 – farenorth 2014-10-26 23:21:57

+0

我想你可能錯過了這個問題的要點?我無法控制輸入形狀。據我所知,他們可能是「(1,2,3,4)」和「(1,5,6,7)';重點是除了第一個維度之外的所有維度都應該是不相關的,所以當我不知道字符串應該是什麼時,我將如何使用'einsum'? – Mehrdad 2014-10-26 23:23:19

1

這不是爲tensordot液漂亮,但你可以從輸入ndim構建einsum字符串:

ll = 'abcdefghijklmnopqrstuvw' 
astr = ll[0]+ll[1:a.ndim]+','+ll[0]+ll[a.ndim:a.ndim+b.ndim-1] 
np.einsum(astr,a,b) 

np.einsum,您可以指定軸爲列表而不是字符串

np.einsum(a, [0]+range(1,a.ndim), b, [0]+range(a.ndim,a.ndim+b.ndim-1)) 

對於一對3d和2D陣列,這些產生:

np.einsum('abc,ad', a, b) 
np.einsum(a, [0,1,2], b, [0,3]) 

'...'在這裏不起作用,因爲這意味着重複軸(儘可能),因爲你想要唯一的軸(除了第一個軸)。

在編寫messier時,einsum解決方案比tensordot更快(對於小型測試陣列,速度要快3倍)。


einsum與另一種選擇是重塑陣列,減少了「剩餘」的尺寸降低到一個。這爲計算增加了一些時間,但並不是很多:

np.einsum('ij,ik',a.reshape(a.shape[0],-1), b.reshape(a.shape[0],-1)).reshape(a.shape[1:]+b.shape[1:]) 
+0

我其實自己試過這個,結果在我的情況下變慢了 - 但是讓我更加困擾的問題是,在一般情況下,字母表中沒有足夠的字母來完成這項工作。 :P – Mehrdad 2014-10-27 23:10:36

+0

我喜歡使用軸列表;我以前從未見過。很高興知道。謝謝! – farenorth 2014-10-28 00:58:32

+0

我添加了一個使用重塑的方法。 – hpaulj 2014-10-28 16:48:56

相關問題