我正在处理两个不同的数组(75x4),并在两个数组之间应用最短距离算法。
所以我想:
我怎么才能和numpy一起这么做呢?
本质上,我希望在每一行数组2上执行一行数组1之间的操作,找到最小值,并将其存储在一个新数组中。然后,对数组1的第2行执行同样的操作,对所有75行数组1执行类似的操作。
这是我正在使用的公式的代码。我得到的只是数组1(训练数据)和数组2(测试数据)之间的距离。但是我要寻找的是,对数组2的所有行进行迭代的一行数组1,将最小值存储在一个新数组中,然后对下一行数组1执行同样的操作,以此类推。
arr_attributedifference = (arr_trainingdata - arr_testingdata)**2
arr_distance = np.sqrt(arr_attributedifference.sum(axis=1))
发布于 2018-06-07 15:45:22
下面是两种方法,一种是使用einsum
,另一种是KDTree
einsum
从本质上做了我们也可以通过广播实现的事情,例如,np.einsum('ik,jk', A, B)
大致相当于(A[:, None, :] * B[None, :, :]).sum(axis=2)
。einsum的优点是它可以立即完成求和,因此避免了创建mxmxn中间数组。
KDTree
更复杂。我们必须预先投资来生成树,但是之后查询最近的邻居是非常有效的。
import numpy as np
from scipy.spatial import cKDTree as KDTree
def f_einsum(A, B):
B2AB = np.einsum('ij,ij->i', B, B) / 2 - np.einsum('ik,jk', A, B)
idx = B2AB.argmin(axis=1)
D = A-B[idx]
return np.sqrt(np.einsum('ij,ij->i', D, D)), idx
def f_KDTree(A, B):
T = KDTree(B)
return T.query(A, 1)
m, n = 75, 4
A, B = np.random.randn(2, m, n)
de, ie = f_einsum(A, B)
dt, it = f_KDTree(A, B)
assert np.all(ie == it) and np.allclose(de, dt)
from timeit import timeit
for m, n in [(75, 4), (500, 4)]:
A, B = np.random.randn(2, m, n)
print(m, n)
print('einsum:', timeit("f_einsum(A, B)", globals=globals(), number=1000))
print('KDTree:', timeit("f_KDTree(A, B)", globals=globals(), number=1000))
样本运行:
75 4
einsum: 0.067826496087946
KDTree: 0.12196151306852698
500 4
einsum: 3.1056990439537913
KDTree: 0.85108971898444
我们可以看到,在小问题规模时,直接方法(einsum)更快,而对于更大的问题规模,KDTree获胜。
https://stackoverflow.com/questions/50751135
复制相似问题