具有多个维度阵列的外部产品

时间:2017-07-28 08:46:22

标签: python arrays numpy

我有d个形状(2, s, t, ...)的numpy数组,我希望将它们彼此相乘,以使输出的形状为(2, ..., 2, s, t, ...) {{1} } d s。例如,使用2

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] 不存在(这也是一个用例),这是经典的外部产品。

我考虑过meshgrid,但无法让它发挥作用。

任何提示?

3 个答案:

答案 0 :(得分: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 :(得分:2)

看起来这个小einsum宝石会解决你的问题:

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

对于n = 3的情况,不应该很难为n-d情况生成字符串。虽然我认为刚发布的另一个einsum答案可能与典型应用程序一样高效。

至于从一串长度为ndim的轴字符生成einsum字符串:

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

认为应该做..

答案 2 :(得分:0)

以下方法使用d-1 1维外部产品计算d-outer产品,并适用于所有情况。

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