慢欧几里德距离

时间:2015-05-05 19:28:31

标签: python numpy knn

我正在使用下面的python代码计算欧几里德距离:

def getNeighbors(trainingSet, testInstance, k, labels):
    distances = []
    for x in range(len(trainingSet)):
        dist = math.sqrt(((testInstance[0] - trainingSet[x][0]) ** 2) +    ((testInstance[1] - trainingSet[x][1]) ** 2))
        distances.append([dist, labels[x]])
    distances = np.array(distances)   
    return distances

为了计算给定点与其他10个点的距离,这很好。但是当我用18563个其他点来计算一个点的距离时,计算机就会被挂起并且不会响应大约3个小时。

如何更快地计算 18563 积分?

1 个答案:

答案 0 :(得分:6)

你可以先通过转换为NumPy然后使用向量操作来加速它,而不是在循环中完成工作,然后转换为NumPy。像这样:

trainingArray = np.array(trainingSet)
distances = ((testInstance[0] - trainingArray[:, 0]) ** 2 +
             (testInstance[1] - trainingArray[:, 1]) ** 2).sqrt()

(这显然是未经测试的,因为没有足够的上下文来知道我必须猜测的那些变量实际上是什么,但它会接近那个。)

您可以采取其他措施来挤出一些额外的%-try,将** 2替换为自我乘法,将sqrt替换为** .5,或者(可能最好)替换np.hypot的全部内容。 (如果你不知道如何使用timeit - 或者更好的是,IPython和%timeit魔法 - 现在是学习的好时机。)

但最终,这只会给你一个大约一个数量级的常数倍增速度。也许需要15分钟而不是3个小时。那很好,但是......为什么一开始需要3个小时?你在这里做的事情应该是几秒钟,甚至更少。这里显然有一些更大的错误,比如当你认为你只召唤一次时,你可能会将这个功能调用N ** 2次。你真的需要解决这个问题。

当然,这仍然值得这样做。首先,逐元素操作比循环更简单,更易读,更难以出错。其次,即使你将整个程序减少到3.8秒,你也会很高兴将数量级加速到0.38秒,对吗?