5

假设我有两个 3 维矩阵,就像这样(取自这个 matlab 示例http://www.mathworks.com/help/matlab/ref/dot.html):

A = cat(3,[1 1;1 1],[2 3;4 5],[6 7;8 9])
B = cat(3,[2 2;2 2],[10 11;12 13],[14 15; 16 17])

如果我想沿第三维取成对点积,我可以在 matlab 中这样做:

C = dot(A,B,3)

这将给出结果:

C =
  106   140
  178   220

什么是 numpy 中的等效操作,最好是矢量化选项,以避免必须在整个数组中编写双 for 循环。我似乎无法理解应该做什么np.tensordotnp.inner应该做什么,但它们可能是选项。

4

3 回答 3

4
In [169]:

A = np.dstack([[[1, 1],[1 ,1]],[[2 ,3],[4, 5]],[[6, 7],[8, 9]]])
B = np.dstack([[[2, 2],[2, 2]],[[10, 11],[12, 13]],[[14, 15], [16, 17]]])
c=np.tensordot(A, B.T,1)
np.vstack([np.diag(c[:,i,i]) for i in range(A.shape[0])]).T
Out[169]:
array([[106, 140],
       [178, 220]])

但令人惊讶的是它是最慢的:

In [170]:

%%timeit
c=np.tensordot(A, B.T,1)
np.vstack([np.diag(c[:,i,i]) for i in range(A.shape[0])]).T
10000 loops, best of 3: 95.2 µs per loop
In [171]:

%timeit np.einsum('i...,i...',a,b)
100000 loops, best of 3: 6.93 µs per loop
In [172]:

%timeit inner1d(A,B)
100000 loops, best of 3: 4.51 µs per loop
于 2014-06-05T17:48:01.007 回答
2

这是一个解决方案:

A = dstack([[[1, 1],[1 ,1]],[[2 ,3],[4, 5]],[[6, 7],[8, 9]]])
B = dstack([[[2, 2],[2, 2]],[[10, 11],[12, 13]],[[14, 15], [16, 17]]])

C = einsum('...k,...k',A,B)

基本上dstack沿第三个轴(docs)连接,然后使用 einsumnumpy 提供的强大的爱因斯坦求和工具(docs

于 2014-06-05T17:52:13.270 回答
2

使用 np.einsum:

In [9]: B = np.array([[[2, 2],[2, 2]],[[10, 11],[12, 13]],[[14, 15],[16, 17]]])

In [10]: A = np.array([[[1, 1],[1, 1]],[[2, 3],[4, 5]],[[6, 7],[8, 9]]]) 

In [11]: np.einsum('i...,i...',A,B)
Out[11]:
array([[106, 140],
       [178, 220]])

或者这是另一个有趣的:

In [37]: from numpy.core.umath_tests import inner1d

In [38]: inner1d(A,B)
Out[38]:
array([[106, 140],
       [178, 220]])

根据@flebool 的评论进行编辑inner1d,适用于 (2,2,3) 和 (3,2,2) 形状的数组:

In [41]: A = dstack([[[1, 1],[1 ,1]],[[2 ,3],[4, 5]],[[6, 7],[8, 9]]])

In [42]: B = dstack([[[2, 2],[2, 2]],[[10, 11],[12, 13]],[[14, 15], [16, 17]]])

In [43]: inner1d(A,B)
Out[43]:
array([[106, 140],
       [178, 220]])
于 2014-06-05T17:53:33.910 回答