2017-07-28 97 views
2

陣列外積我有形狀(2, s, t, ...)d numpy的陣列,以及我想乘每個區域具有彼此,使得輸出與d2 S形(2, ..., 2, s, t, ...)。例如,對於d==3與多個維度

import numpy 

d = 3 
a = numpy.random.rand(d, 2, 7, 8) 

out = numpy.empty((2, 2, 2, 7, 8)) 
for i in range(2): 
    for j in range(2): 
     for k in range(2): 
      out[i, j, k] = a[0][i]*a[1][j]*a[2][k] 

如果s, t, ...不存在(其也是用例),這是經典的外積。

我想到了meshgrid,但無法完成它的工作。

任何提示?

回答

0

下面的方法計算d-外產物與d-1一維外部產品和工程在所有情況下。

def outern(a): 
    d = len(a) 

    # If the elements are more than one-dimensional, assert that the extra 
    # dimensions are all equal. 
    s0 = a[0].shape 
    for arr in a: 
     assert s0[1:] == arr.shape[1:] 

    out = a[0] 
    for k in range(1, d): 
     # Basically outer products. Checkout `numpy.outer`'s implementation for 
     # comparison. 
     out = numpy.multiply(
       # Insert a newaxis after k `:` 
       out[(slice(None),) * k + (numpy.newaxis,)], 
       # Insert a newaxis at the beginning 
       a[k][numpy.newaxis], 
       ) 
    return out 
2

我會用numpy.einsum

c = a[0] 
for i in range(d-1): #adds one dimension in each iteration 
    c = np.einsum('i...,...->i...', a[i+1],c) 

這給了幾乎相同的結果是你的,但軸以相反的順序:

c.swapaxes(0,2)==out #yields True 

您可以扭轉前幾軸或調整其餘的代碼,無論什麼對你更好。

1

看起來這有點einsum寶石會解決你的問題:

out = np.einsum('i...,j...,k...->ijk...', *a) 

那對於n = 3的情況下,不應該是很難,雖然產生了正d情況下琴絃。雖然我認爲剛纔發佈的其他艾森姆答案可能與典型應用程序一樣。

作爲從長度NDIM軸線字符的字符串生成einsum字符串:

einsum_statement = ','.join(f'{a}...' for a in ax) + f'->{ax}...' 

認爲應該做..

+0

您可以取代''用... xy''使它更普遍的工作。除此之外:任何想法如何將這個表達式概括爲任意'd'? –

+0

如果'a = numpy.random.rand(d)',此解決方案不起作用。我猜這個案子可以用'if'截獲。 –