乘以特定维矩阵

时间:2014-03-26 17:02:05

标签: python numpy matrix

说我有矩阵A和B.

A是三维数组/张量(?)。

[1,2,3,4]
[5,6,7,8]
[1,2,3,4]
[5,6,7,8]

在第三维度上有4个不同的2d矩阵,如上面的那个。

B是一个矩阵。

[1,2,3,4]

B中还有4个,每个都是相同的。

如何将B中的每个向量(?)与A中的每个2d矩阵相乘。

[1,2,3,4]*[1,2,3,4]*[1;2;3;4]
          [5,6,7,8]
          [1,2,3,4]
          [5,6,7,8]

上述类型乘法中有四个可以得到四个4x1向量。 我用numpy尝试过:

y = numpy.arange(4).reshape(1,4)
z = numpy.arange(64).reshape(4,4,4)
y.dot(z).dot(numpy.transpose(y))
------
Output:
array([[[ 420],
        [ 996],
        [1572],
        [2148]]])

它可以按照我的意愿运作。但是我不知道numpy是如何广播的,我想知道它是为了学习目的,还有其他用于处理不同库中的矩阵的包处理不同的广播。我试图以不同的方式来平铺B以获得相同的结果,但没有任何作用。如果我没有清楚地解释任何内容,请告诉我。

也宁愿从numpy获得4x1而不是3d返回。

3 个答案:

答案 0 :(得分:2)

您可能需要查看np.einsum。举个例子:

>>> mat = np.arange(80).reshape(4, 4, 5)
>>> vec = np.arange(12).reshape(3, 4)
>>> np.einsum('ij,jkl,ik->il', vec, mat, vec)
array([[ 2100,  2136,  2172,  2208,  2244],
       [20900, 21384, 21868, 22352, 22836],
       [58900, 60344, 61788, 63232, 64676]])

如果我没有得到错误的索引,我有5个形状为4x4的矩阵,以及3个长度为4的向量,并且计算每个向量的每个矩阵的3x5二次形式。

答案 1 :(得分:0)

请注意np.dot对{x 3}}的不同维度数组的行为有所不同:

  

对于二维数组,它相当于矩阵乘法,

     

对于1-D阵列到向量的内积(没有复数   共轭)。

     

对于N维,它是最后一个的和积   a的轴和b的倒数第二个

在您的示例z中有3个维度。

此外,还有here

您在示例中使用的是数组。 Numpy矩阵仅为2D,并且使用*运算符实现矩阵乘法。 (对于数组,这个perfroms元素按元素乘法)

答案 2 :(得分:0)

为了保持尺寸直,我将使用变量。通常在测试中我喜欢在每个维度中使用不同的大小(例如z=...reshape(3,4,5)),因此错误会突然出现在我身上。

k,j,l = 4
y = numpy.arange(4).reshape(1,j)
z = numpy.arange(64).reshape(k,j,l)

y.dot(z)会将y的最后一个昏暗与zj)的倒数第二个结合起来(参见其文档)。结果将是(1,k,l)

np.einsum有助于确认这一点:

print y.dot(z)
print np.einsum('ij,kjl',y,z) # note the repeated j

都产生

array([[[ 56,  62,  68,  74],
        [152, 158, 164, 170],
        [248, 254, 260, 266],
        [344, 350, 356, 362]]])

y.T(转置)是(j,1)。因此,第二个点将(1,k,l)(j,1),最后一个暗淡(l)与第一个j组合在一起,从而产生(1,k,1),即您的3d数组:

array([[[ 420],
        [ 996],
        [1572],
        [2148]]])

np.einsum('ijl,lm', np.einsum('ij,kjl',y,z), y.T) # note the repeated l

这个einsum可以组合成一个调用(使用相同的索引):

np.einsum('ij,kjl,ml',y,z,y)

不涉及广播。也就是说,没有添加或扩展维度。您只需要在通过dot时系统地跟踪维度。

要获得较小的尺寸结果,您需要挤出1或重塑结果。如果您从1d y开始,则会获得1d结果

y1=y.squeeze()
np.einsum('j,kjl,l',y1,z,y1)
y1.dot(z).dot(y1.T)
# array([ 420,  996, 1572, 2148])