这可以通过使用
np.argpartition
来获取最大的
k
个元素的索引,然后使用
np.ix_
选择并设置来自
m1
和
m2
的所选元素的点积。因此,我们基本上需要分两个阶段来实现这个功能,接下来将讨论这两个阶段。
首先,获取对应于m1
和m2
中最大的k
个元素的索引,如下所示 -
m1_idx = np.argpartition(-m1,k,axis=0)[:k].ravel()
m2_idx = np.argpartition(-m2,k)[:,:k].ravel()
最后,设置输出数组。使用
np.ix_
将
m1
和
m2
索引分别沿行和列广播以选择要设置的输出数组中的元素。接下来,计算
m1
和
m2
中最高
k
个元素之间的点积,可以使用
m1_idx
和
m2_idx
进行索引从
m1
和
m2
中获取这些元素。
out = np.zeros((n,n))
out[np.ix_(m1_idx,m2_idx)] = np.dot(m1[m1_idx],m2[:,m2_idx])
让我们通过对另一个实现运行它来验证该实现,该实现显式设置较低的 n-k
元素为 0
在 m1
、m2
中,然后执行点积。以下是执行检查的示例运行 -
1)输入:
In [170]: m1
Out[170]:
array([[ 0.26980423],
[ 0.30698416],
[ 0.60391089],
[ 0.73246763],
[ 0.35276247]])
In [171]: m2
Out[171]: array([[ 0.30523552, 0.87411242, 0.01071218, 0.81835438, 0.21693231]])
In [172]: k = 2
2) 运行建议的实现:
In [173]:
...: m1_idx = np.argpartition(-m1,k,axis=0)[:k].ravel()
...: m2_idx = np.argpartition(-m2,k)[:,:k].ravel()
...: out = np.zeros((n,n))
...: out[np.ix_(m1_idx,m2_idx)] = np.dot(m1[m1_idx],m2[:,m2_idx])
...:
3)使用替代实现来获取输出:
In [174]: # Explicit setting of lower n-k elements to zeros for m1 and m2
...: m1[np.argpartition(-m1,k,axis=0)[k:]] = 0
...: m2[:,np.argpartition(-m2,k)[:,k:].ravel()] = 0
...:
In [175]: m1 # Verify m1 and m2 have lower n-k elements set to 0s
Out[175]:
array([[ 0. ],
[ 0. ],
[ 0.60391089],
[ 0.73246763],
[ 0. ]])
In [176]: m2
Out[176]: array([[ 0. , 0.87411242, 0. , 0.81835438, 0. ]])
In [177]: m1.dot(m2) # Use m1.dot(m2) to directly get output. This is expensive.
Out[177]:
array([[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.52788601, 0. , 0.49421312, 0. ],
[ 0. , 0.64025905, 0. , 0.59941809, 0. ],
[ 0. , 0. , 0. , 0. , 0. ]])
4) 验证我们提出的实现:
In [178]: out # Print output from proposed solution obtained earlier
Out[178]:
array([[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.52788601, 0. , 0.49421312, 0. ],
[ 0. , 0.64025905, 0. , 0.59941809, 0. ],
[ 0. , 0. , 0. , 0. , 0. ]])