通过(a x c x d)矩阵乘以(a x a)方阵

时间:2014-12-23 03:46:01

标签: python numpy matrix

所以假设我有一个(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)

2 个答案:

答案 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 sumnp.einsum()功能,使用丰富的下标标签框架,允许broadcasting维度并控制输出:

np.einsum('ijk,i...->ijk', X, coeffs)

下标字符串:

  • 逗号,将第一个操作数的下标标签(左侧)与第二个操作数的下标标签分隔开来。
  • ->符号后面的下标标签给出了输出的尺寸。
  • 省略号...允许将coeffs向量广播到X矩阵的额外2维(...实际上是可选的,用于更明确的广播规范)

需要一点点习惯,但有许多矩阵向量操作,如tracediaginner/outer productelement-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页面