Python 通过numpy数组迭代有效地测试多个元素

Python 通过numpy数组迭代有效地测试多个元素,python,numpy,Python,Numpy,我有下面的代码,它遍历名为“m”的2dnumpy数组。它的工作速度非常慢。如何使用numpy函数转换此代码,以避免使用for循环 pairs = [] for i in range(size): for j in range(size): if(i >= j): continue if(m[i][j] + m[j][i] >= 0.75): pairs.append([i, j, m[i][j]

我有下面的代码,它遍历名为“m”的2dnumpy数组。它的工作速度非常慢。如何使用numpy函数转换此代码,以避免使用for循环

pairs = []
for i in range(size):
    for j in range(size):
        if(i >= j):
            continue
        if(m[i][j] + m[j][i] >= 0.75):
            pairs.append([i, j, m[i][j] + m[j][i]])

优化代码的一种方法是避免在(i>=j)时进行比较。要仅遍历数组的下三角形而不进行比较,必须使内部循环从最外层循环的
i
值开始。这样,就避免了
size x size
if
比较

import numpy as np
size = 5000
m = np.random.rand(size, size)
pairs = []


for i in range(size):
    for j in range(i , size):

        if(m[i][j] + m[j][i] >= 0.75):
            pairs.append([i, j, m[i][j] + m[j][i]])

可以使用NumPy使用矢量化方法。这个想法是:

  • 首先初始化一个矩阵
    m
    ,然后创建
    m+m.T
    ,它相当于
    m[i][j]+m[j][i]
    ,其中
    m.T
    是矩阵转置,称之为
    summ
  • (summ)
    返回矩阵的上三角部分(这相当于在代码中使用
    continue
    忽略下三角部分)。这避免了在代码中出现(i>=j):的显式
    。这里必须使用
    k=1
    排除对角线元素。默认情况下,
    k=0
    ,其中也包括对角线元素
  • 然后,使用求和
    m+m.T
    大于等于0.75的点的索引
  • 然后将这些索引和相应的值存储在列表中,以供以后处理/打印之用

可验证示例(使用小3x3随机数据集)

进一步的性能改进

我刚刚找到了一种更快的方法来生成最终的
列表,避免了显式for循环

pairs = list(zip(index[:, 0], index[:, 1], summ[index[:,0], index[:,1]]))

这个数组的维数是多少?大约5000x5000最好先定义第一个大小,然后在
m=np.random.rand(size,size)
中使用它。建议您将
np.random.seed(0)
添加到顶部,然后重新运行以给出可重复的结果。将我的程序执行时间从55秒减少到1.5秒。非常感谢@注:我稍微编辑了一下以包含
k=1
,因为您不需要对角线elements@nota:要获得更高的速度,请使用
zip检查我的编辑
pairs = list(zip(index[:, 0], index[:, 1], summ[index[:,0], index[:,1]]))