多维 numpy.outer 没有展平
Multidimensional numpy.outer without flatten
x 是 N × M 矩阵。
y是L向量的1。
我想return "outer product"在x和y之间,我们称它为z吧。
z[n,m,l] = x[n,m] * y[l]
我可能可以使用 einsum 来做到这一点。
np.einsum("ij,k->ijk", x[:, :, k], y[:, k])
或之后重塑。
np.outer(x[:, :, k], y).reshape((x.shape[0],x.shape[1],y.shape[0]))
但我正在考虑仅在 np.outer 中执行此操作,或者看起来更简单、内存效率更高。
有办法吗?
它是 numpy
"can't know unless you happen to know" 位之一:np.outer
扁平化多维输入而 np.multiply.outer
不:
m,n,l = 3,4,5
x = np.arange(m*n).reshape(m,n)
y = np.arange(l)
np.multiply.outer(x,y).shape
# (3, 4, 5)
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,1) * (1,1,l)
实现的 (n,m,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]
是最快的,但不是很多。
x 是 N × M 矩阵。
y是L向量的1。
我想return "outer product"在x和y之间,我们称它为z吧。
z[n,m,l] = x[n,m] * y[l]
我可能可以使用 einsum 来做到这一点。
np.einsum("ij,k->ijk", x[:, :, k], y[:, k])
或之后重塑。
np.outer(x[:, :, k], y).reshape((x.shape[0],x.shape[1],y.shape[0]))
但我正在考虑仅在 np.outer 中执行此操作,或者看起来更简单、内存效率更高。
有办法吗?
它是 numpy
"can't know unless you happen to know" 位之一:np.outer
扁平化多维输入而 np.multiply.outer
不:
m,n,l = 3,4,5
x = np.arange(m*n).reshape(m,n)
y = np.arange(l)
np.multiply.outer(x,y).shape
# (3, 4, 5)
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,1) * (1,1,l)
实现的 (n,m,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]
是最快的,但不是很多。