我有两个 numpy 数组,X
and Y
,有形状(n,d)
and (m,d)
, 分别。假设我们要计算每行之间的欧几里得距离X
和每一行Y
并将结果存储在数组中Z
有形状(n,m)
。我对此有两个实现。第一个实现使用两个 for 循环,如下所示:
for i in range(n):
for j in range(m):
Z[i,j] = np.sqrt(np.sum(np.square(X[i] - Y[j])))
第二种实现仅通过矢量化使用一个循环:
for i in range(n):
Z[i] = np.sqrt(np.sum(np.square(X[i]-Y), axis=1))
当我在特定的机器上运行这些代码时X
and Y
数据显示,第一次实现耗时近30秒,第二次实现耗时近60秒。我预计第二个实现会更快,因为它使用矢量化。其运行缓慢的原因是什么?我知道我们可以通过完全矢量化代码来获得更快的实现,但我不明白为什么第二个代码(部分矢量化)比非矢量化版本慢。
这是完整的代码:
n,m,d = 5000,500,3000
X = np.random.rand(n,d)
Y = np.random.rand(m,d)
Z = np.zeros((n,m))
tic = time.time()
for i in range(n):
for j in range(m):
Z[i,j] = np.sqrt(np.sum(np.square(X[i] - Y[j])))
print('Elapsed time 1: ', time.time()-tic)
tic = time.time()
for i in range(n):
Z[i] = np.sqrt(np.sum(np.square(X[i]-Y), axis=1))
print('Elapsed time 2: ', time.time()-tic)
tic = time.time()
train_squared = np.square(X).sum(axis=1).reshape((1,n))
test_squared = np.square(Y).sum(axis=1).reshape((m,1))
test_train = -2*np.matmul(Y, X.T)
dists = np.sqrt(test_train + train_squared + test_squared)
print('Elapsed time 3: ', time.time()-tic)
这是输出:
Elapsed time 1: 35.659096002578735
Elapsed time 2: 65.57051086425781
Elapsed time 3: 0.3912069797515869