我有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
,但无法让它发挥作用。
任何提示?
答案 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