2014-03-26 106 views
1

说我有矩阵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中的每个矢量(?),每个2D矩阵在A.

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

会有上述类型的乘法的4得到4个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以达到相同的效果,但没有任何效果。如果我没有解释清楚,请告诉我。

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

回答

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点矩阵形状的4×4,且长度为4的3个向量,并且正在计算与每个向量的每个矩阵的3×5二次型。

+0

这不会重现OP的双'dot',因为'dot'使用第2至第2个参数的最后一个维度。 – hpaulj

+0

但他的第二个参数是1D。我认为这与他所问的内容相符,这似乎是一种二次方式。无论如何,他应该能够通过摆弄指数来得到他想要的。 – Jaime

0

注意np.dot具有不同尺寸的阵列的行为不同,从here

对于2 d阵列它相当于矩阵乘法,

1-d阵列矢量的内积(没有复杂的 共轭)。

对于N维它结束的最后 轴线和第二到末尾B

的在您的例子z有3种尺寸的总和产物。

此外,还有一个important distinction between a numpy array and a numpy matrix

你在你的例子使用数组。 Numpy矩阵仅为2D,矩阵乘法运算符为*。 (对于数组,这个元素通过元素乘法运算)

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你得到一个一维结果

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