outer 的代码是:
multiply(a.ravel()[:, newaxis], b.ravel()[newaxis, :], out)
正如其文档所说,它变平(即ravel)。如果数组已经是 1d,则该表达式可以写为
a[:,None] * b[None,:]
a[:,None] * b # broadcasting auto adds the None to b
我们可以将广播规则应用于您的 (n,m)*(1,l):
In [2]: x = np.arange(12).reshape(3,4); y = np.array([[1,2]])
In [3]: x.shape, y.shape
Out[3]: ((3, 4), (1, 2))
你想要一个 (n,m,l),这是 (n,m,1) * (1,1,l) 实现的。我们需要向x 添加一个尾随维度。 y 上的额外前导 1 是自动的:
In [4]: z = x[...,None]*y
In [5]: z.shape
Out[5]: (3, 4, 2)
In [6]: z
Out[6]:
array([[[ 0, 0],
[ 1, 2],
[ 2, 4],
[ 3, 6]],
[[ 4, 8],
[ 5, 10],
[ 6, 12],
[ 7, 14]],
[[ 8, 16],
[ 9, 18],
[10, 20],
[11, 22]]])
使用einsum:
In [8]: np.einsum('nm,kl->nml', x, y).shape
Out[8]: (3, 4, 2)
您批准的事实:
In [9]: np.multiply.outer(x,y).shape
Out[9]: (3, 4, 1, 2)
建议 y 不是真正的 (1,l) 而是 (l,)`。调整任何一个都很容易。
我认为这些之间的内存效率没有太大差异。在这个小例子中,In[4] 是最快的,但不是很多。