所以假设我有一个(c x d)
矩阵列表。就像说我有a
个。我对每个矩阵都有a
个系数。
在NumPy中是否有一种快速方法可以在保持张量数据结构的同时,将每个矩阵标量乘以其系数,或者我是否需要在for循环中手动执行,即X = np.array([np.multiply(coefs[i], X[i]) for i in range(len(coefs))])
即。 X.shape = (3, 4, 5)
,coefs.shape = (3)
。
答案 0 :(得分:2)
X = np.array([[[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]],
[[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]],
[[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]]])
coeffs = np.array([2,4,6])
您需要将轴添加到coeffs
,以便它以您想要的维度进行广播。
>>> X * coeffs[:, np.newaxis, np.newaxis]
array([[[2, 2, 2, 2, 2],
[2, 2, 2, 2, 2],
[2, 2, 2, 2, 2],
[2, 2, 2, 2, 2]],
[[4, 4, 4, 4, 4],
[4, 4, 4, 4, 4],
[4, 4, 4, 4, 4],
[4, 4, 4, 4, 4]],
[[6, 6, 6, 6, 6],
[6, 6, 6, 6, 6],
[6, 6, 6, 6, 6],
[6, 6, 6, 6, 6]]])
>>>
np.newaxis
允许coeffs
的值与X
的第一维对齐,然后在剩余维度上为broadcast。
答案 1 :(得分:0)
<强>解决方案:强>
这是走pythonic方式的经典问题。以下1-liner使用强大的einstein sum
,np.einsum()功能,使用丰富的下标标签框架,允许broadcasting维度并控制输出:
np.einsum('ijk,i...->ijk', X, coeffs)
下标字符串:
,
将第一个操作数的下标标签(左侧)与第二个操作数的下标标签分隔开来。 ->
符号后面的下标标签给出了输出的尺寸。 ...
允许将coeffs
向量广播到X
矩阵的额外2维(...
实际上是可选的,用于更明确的广播规范) 需要一点点习惯,但有许多矩阵向量操作,如trace
,diag
,inner/outer product
,element-wise multiplication
等,都归于此强大的配方。
用文字说明:
因此字符串基本上表示采用X
矩阵的所有维度,并将其与coeffs
向量相乘(在X
的额外维度上广播)并生成输出矩阵的尺寸与X
相同。
<强>输出:强>
>>> np.einsum( 'ijk,i->ijk', np.ones((2,2,2)), np.array([2,4]))
array([[[ 2., 2.],
[ 2., 2.]],
[[ 4., 4.],
[ 4., 4.]]])
在2D情况下,沿任一轴的元素:
>>> np.einsum( 'ij,i->ij', np.ones((2,2)), np.array([2,4]))
array([[ 2., 2.],
[ 4., 4.]])
>>> np.einsum( 'ij,j->ij', np.ones((2,2)), np.array([2,4]))
array([[ 2., 4.],
[ 2., 4.]])
<强>替代:强>
当然,您可以使用np.newaxis
参数和简单乘法手动在额外维度上广播向量:
X * coeff[:, np.newaxis, np.newaxis]
<强>定时:强>
使用ipython line magic function %timeit
我们实际上可以看到einsum
对于大型数据集来说可能要贵一点:
>>> %timeit np.einsum('ijk,i...->ijk',np.ones((10,100,100)),np.ones(10))
1000 loops, best of 3: 209 µs per loop
>>> %timeit np.ones((10,100,100))*np.ones(10)[:,np.newaxis, np.newaxis]
1000 loops, best of 3: 129 µs per loop
然后权衡是einstein sum
提供的多功能性。
P.S。如果您是一位沉迷于它提供的丰富索引框架的Matlab用户,您可能有兴趣查看此Numpy-Matlab comparison页面