【问题标题】:Fast way to calculate sum over the outer products of 2-d array, with the shape of (2, 5) in numpy计算二维数组外积和的快速方法,numpy中的形状为(2, 5)
【发布时间】:2018-10-08 12:56:18
【问题描述】:

我有一个 numpy 二维数组,形状为 (2, 5)(可能是更多维度 (m,n))

A=array([[2.64859009e-02, 2.17771938e-02, 2.38019379e+00, 7.35715883e-01,6.89917290e-01],
      [6.89917290e-01, 5.67262659e-01, 6.20004150e+01, 1.91642758e+01,1.79712923e+01]]

我想生成两个 5 x 5 矩阵,这是数组 A 本身中每个数组的外积。

第一个矩阵应该是[2.64859009e-02, 2.17771938e-02, 2.38019379e+00, 7.35715883e-01,6.89917290e-01][2.64859009e-02, 2.17771938e-02, 2.38019379e+00, 7.35715883e-01,6.89917290e-01]的外积,第二个矩阵应该是[6.89917290e-01, 5.67262659e-01, 6.20004150e+01, 1.91642758e+01,1.79712923e+01][6.89917290e-01, 5.67262659e-01, 6.20004150e+01, 1.91642758e+01,1.79712923e+01]的外积。

计算之后,我想对两个 5 x 5 矩阵的每个元素求和,最终输出为一个 5 x 5 矩阵。

A[0] outer* A[0] + A[1] outer* A[1]

在 numpy 中有没有快速的方法?

【问题讨论】:

  • 两个 5*5 矩阵怎么算。 A[0] 和 A[1] 的外积将为您提供一个 5*5 矩阵。除非,我把问题理解错了。
  • 您好,我刚刚编辑了这个问题以使其更清楚,它是A[0]A[0]A[1]A[1] 的外积
  • 另一种描述A 的方式是二维数组,形状为(2,5)。你看过np.outer吗?

标签: python python-3.x numpy


【解决方案1】:

让我们做一个更简单的测试数组:

In [254]: A = np.arange(10).reshape(2,5)
In [255]: A
Out[255]: 
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
In [256]: A.shape
Out[256]: (2, 5)

鉴于您描述问题的方式,np.outer 应该很容易应用:

In [257]: np.outer(A[0],A[0])+np.outer(A[1],A[1])
Out[257]: 
array([[25, 30, 35, 40, 45],
       [30, 37, 44, 51, 58],
       [35, 44, 53, 62, 71],
       [40, 51, 62, 73, 84],
       [45, 58, 71, 84, 97]])

np.outer 仅适用于 1d 数组,而不适用于整个 2d A。但是我们可以使用broadcasting 做同样的outer。结果将是一个 (2,5,5) 数组,然后我们可以在第一个轴上求和:

In [260]: (A[:,:,None]*A[:,None,:]).sum(axis=0)
Out[260]: 
array([[25, 30, 35, 40, 45],
       [30, 37, 44, 51, 58],
       [35, 44, 53, 62, 71],
       [40, 51, 62, 73, 84],
       [45, 58, 71, 84, 97]])

np.einsum 也是描述此类操作的一种方便方式(如果您习惯于处理轴索引):

In [261]: np.einsum('ij,ik->jk',A,A)
Out[261]: 
array([[25, 30, 35, 40, 45],
       [30, 37, 44, 51, 58],
       [35, 44, 53, 62, 71],
       [40, 51, 62, 73, 84],
       [45, 58, 71, 84, 97]])

但是 einsum 看起来确实像 dot 产品,产品的总和。我们只需要转置第一个数组:

np.einsum('ji,ik->jk', A.T,A)   

np.dot:

In [262]: np.dot(A.T,A)
Out[262]: 
array([[25, 30, 35, 40, 45],
       [30, 37, 44, 51, 58],
       [35, 44, 53, 62, 71],
       [40, 51, 62, 73, 84],
       [45, 58, 71, 84, 97]])

【讨论】:

  • 太棒了!从中学习:)
【解决方案2】:

您可以使用here 中的np.outer 方法。

A=np.array([[2.64859009e-02, 2.17771938e-02, 2.38019379e+00, 7.35715883e-01,6.89917290e-01],[6.89917290e-01, 5.67262659e-01, 6.20004150e+01, 1.91642758e+01,1.79712923e+01]]) b = np.outer(A[0],A[0]) c = np.outer(A[1],A[1])

b+c 的简单总和应该足以完成最后一步。

【讨论】:

  • 如果我仍然想将它们保存到数组中怎么办?
  • bc 是 numpy 数组。如果你想要一个数组。您可以随时根据需要堆叠它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2016-12-20
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
相关资源
最近更新 更多