首页 > 解决方案 > Python避免双重for循环

问题描述

我试图找到一种方法来通过使用numpy来避免python中的双重for循环,但我不确定它是否可能。

我有两个 3D 矩阵,我使用 numpy 的 flatten() 将它们展平为两个 2D 矩阵,现在我需要对每一行、每一行进行计算。基本上每一行代表一个图像,我正在对两个向量进行一系列计算,并返回一个标量。

A [a, b, c, d]     A' [a, b, c, d]
B [e, f, g, h]     B' [e, f, g, h]
C [i, j, k, l]     C' [i, j, k, l]
D [m, n, o, p]     D' [m, n, o, p]

result
[AA' AB' AC' AD']
[BA' BB' BC' BD']
[CA' CB' CC' CD']
[DA' DB' DC' DD']

编辑:这是我的双重 for 循环

aMatrix = np.array([[5, 3, 2, 1, 4, 2],
        [7, 0, 3, 5, 7, 9],
        [9, 8, 0, 2, 4, 8],
        [3, 5, 2, 0, 1, 9],
        [7, 7, 4, 1, 7, 6],
        [5, 9, 8, 9, 6, 1]])

find_distance_of_two_sets(aMatrix, aMatrix)

def find_distance_of_two_sets(aMatrix, bMatrix):
    distance = np.zeros((6, 6))
    i = 0
    for a in aMatrix:
        j = 0
        for b in bMatrix:
            distance[i][j] = euclidean_distance(a, b)
            j += 1
        i += 1
outputFile = open('distanceMatrix', 'wb')
np.save(outputFile, distance)

def euclidean_distance(a, b):
    return np.sqrt(np.sum(np.square(np.subtract(a, b))))

如果您要打印结果,那将是

[[ 0.          9.38083152  9.05538514  8.18535277  7.         11.87434209]
 [ 9.38083152  0.          9.79795897 10.14889157  8.66025404 13.82027496]
 [ 9.05538514  9.79795897  0.          7.93725393  5.91607978 13.52774926]
 [ 8.18535277 10.14889157  7.93725393  0.          8.36660027 15.03329638]
 [ 7.          8.66025404  5.91607978  8.36660027  0.         10.67707825]
 [11.87434209 13.82027496 13.52774926 15.03329638 10.67707825  0.        ]]

标签: pythonnumpy

解决方案


广播第二个数组,利用向量化操作。

设置

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

d = (a - a[:, None])**2
np.sqrt(d.sum(-1)).round(2)

array([[ 0.  ,  9.38,  9.06,  8.19,  7.  , 11.87],
       [ 9.38,  0.  ,  9.8 , 10.15,  8.66, 13.82],
       [ 9.06,  9.8 ,  0.  ,  7.94,  5.92, 13.53],
       [ 8.19, 10.15,  7.94,  0.  ,  8.37, 15.03],
       [ 7.  ,  8.66,  5.92,  8.37,  0.  , 10.68],
       [11.87, 13.82, 13.53, 15.03, 10.68,  0.  ]])

表现

a = np.random.rand(100, 100)

%%timeit
d = (a - a[:, None])**2
np.sqrt(d.sum(-1)).round(2)

7.68 ms ± 75.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
distance = np.zeros((100, 100))
for i, el1 in enumerate(a):
     for j, el2 in enumerate(a):
         distance[i][j] = np.sqrt(np.sum(np.square(np.subtract(el1, el2))))

51.1 ms ± 1.97 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

推荐阅读