说我有矩阵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返回。
答案 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
的最后一个昏暗与z
(j
)的倒数第二个结合起来(参见其文档)。结果将是(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])