采用高维numpy阵列的点积

时间:2017-04-02 15:08:45

标签: python arrays numpy matrix dot-product

我试图在三个numpy数组之间采用点积。但是,我正在努力绕过这个问题。

问题如下:

我分别有两个(4)形状的numpy数组ab,以及一个形状为(4,4,3),c的numpy数组。

import numpy as np

a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
          [[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
          [[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
          [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])

我想以这样的方式计算点积,即我的结果是3元组。也就是说,首先使用ab,然后点击c,根据需要进行转置。换句话说,我想计算abc之间的点积,就像c的形状(4, 4)一样,但我想要一个3 -tuple结果。

我试过了:

重塑ac,然后计算点积:

a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))

tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp, c) 

理想情况下,我现在应该:

print(result.shape)
>> (1, 1, 3) 

但我收到了错误

  

ValueError:形状(1,4,3)和(4,1)未对齐:3(暗淡2)!= 4(暗淡0)

我也试过使用numpy的tensordot函数,但没有运气。

3 个答案:

答案 0 :(得分:1)

基本Properties规则是:A的最后一个轴,B的第二个到最后一个

dot(A,B)

In [965]: a.shape Out[965]: (4,) In [966]: b.shape Out[966]: (4, 4, 3) (和a)是1d。它的(4,)可以与c的第2(4)点对齐:

b

在输出中使用In [967]: np.dot(a,b).shape Out[967]: (4, 3) 会产生一个(3,)数组

c

使用等效的In [968]: np.dot(c, np.dot(a,b)) Out[968]: array([360, 360, 360])

,这种组合可能更清晰
einsum

但是如果我们希望In [971]: np.einsum('i,jik,j->k',a,b,c) Out[971]: array([360, 360, 360]) a的第一轴上行动呢?使用b这很容易做到:

einsum

要对In [972]: np.einsum('i,ijk,j->k',a,b,c) Out[972]: array([440, 440, 440]) 执行相同操作,我们只需切换dota

c

或转置In [973]: np.dot(a, np.dot(c,b)) Out[973]: array([440, 440, 440]) 的轴:

b

如果In [974]: np.dot(c, np.dot(a,b.transpose(1,0,2))) Out[974]: array([440, 440, 440]) a有不同的长度,这个换位问题会更清晰。例如A(2,)和(4,),(2,4,3)或(4,2,3)。

c

你有一个(1,4a)点缀着(4,4a,3)。结果是(1,4,3)。我添加了tmp = np.dot(a.T, b) # now has shape (1, 4, 3) 以确定何时组合轴。

要应用(4,1)a,我们必须进行相同的转置:

c
没有转置,

In [977]: np.dot(c[:,None].T, np.dot(a[:,None].T, b)) Out[977]: array([[[360, 360, 360]]]) In [978]: _.shape Out[978]: (1, 1, 3) 会做同样的事情。

  

我希望numpy会在最后一个轴上自动分配。也就是说,如果有意义的话,点积将在两个第一轴上运行。

鉴于我在开始时引用的np.dot(c[None,:], np.dot(a[None,:], b))规则,这没有意义。但是如果我们转换dot所以(3)轴是第一个,它可以“携带”,使用最后一个,第二个到最后一个。

b

答案 1 :(得分:0)

不是自动化但是完成工作:

np.einsum('i,ijk,j->k',a,b,c)
# array([440, 440, 440])

这会计算形状(3,)的d,使d_k = sum_{ij} a_i b_{ijk} c_j

答案 2 :(得分:0)

您将(1,4,3)矩阵乘以(4,1)矩阵,因此不可能,因为b中有3页(1,4)矩阵。如果你想用矩阵b的每一页乘以c,只需将每一页分别相乘。

a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
      [[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
      [[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
      [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])

a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))

tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp[:,:,0], c)
for i in range(1,3):
    result = np.dstack((result, np.dot(tmp[:,:,i], c)))
print np.shape(result)

所以你有大小(1,1,3)的结果