knn算法中计算距离而不是欧几里得距离的替代有效方法

Posted

技术标签:

【中文标题】knn算法中计算距离而不是欧几里得距离的替代有效方法【英文标题】:alternate efficient way to compute distance instead of eucledian distance in knn algorithm 【发布时间】:2017-10-09 20:44:36 【问题描述】:

我已经实现了 knn 算法,这是我计算欧几里得距离的函数。

def euc_dist(self, train, test):
    return math.sqrt(((train[0] - test[0]) ** 2) + ((test[1] - train[1]) ** 2))

#
def euc_distance(self, test):
    eu_dist = []
    for i in range(len(test)):
        distance = [self.euc_dist(self.X_train[j], test[i]) for j in range(len(self.X_train))]
        eu_dist.insert(i, distance)


    return eu_dist

有没有更有效的方法来计算距离??

【问题讨论】:

您有一些示例输入/输出数据吗? 是的,但是训练数据集有 1400 行,测试数据集有 600 行。 【参考方案1】:

(1) Python 循环非常慢。学习使用数组计算,例如numpy:

import numpy as np

x = np.array(...)
y = np.array(...)
distances = np.sqrt(np.sum((x-y)**2)) 

批处理计算可以实现高效的矢量化甚至并行实现。

(2) 如果您不需要绝对距离值(例如,您只比较它们的大小或平均值或以某种方式对结果进行归一化),则省略平方根运算,它非常慢。省略是可能的,因为 sqrt 是一个单调函数(即省略它会保留总顺序)。

squared_distances = np.sum((x-y)**2)

(3) 除了欧几里得之外,可能还有对您的特定问题有意义的距离定义。您可以尝试找到更简单更快的定义,例如一个简单的减法或绝对误差。

error = x-y
absolute_error = np.abs(x-y)

(4) 在所有情况下,尝试和测量(配置文件)。在处理运行时性能优化时不要依赖直觉。

附:上面的代码 sn-ps 并没有准确地映射到您的代码(故意)。学习如何适应它们取决于您。提示:二维数组;)

【讨论】:

【参考方案2】:

如果仅用于比较,您可以使用平方距离(只需删除 math.sqrt - 操作缓慢)。

可能的优化 - 如果 Python 操作 ((train[0] - test[0]) ** 2 使用指数幂,则值得将其更改为简单的乘法

def squared_euc_dist(self, train, test):
    x = train[0] - test[0]
    y = train[1] - test[1]
    return x * x + y * y

【讨论】:

是的,乘法平方的速度大约是使用 ** 的两倍。如果 OP 需要距离而不是平方距离,那么 math.hypot 值得一看。 OTOH,他们可能应该使用 Numpy。 在这种情况下,平方和 sqrt 都没有解释器中的循环和内存访问开销那么重要。 @Drop 当然可以!这就是我提到 Numpy 的原因。 ;)

以上是关于knn算法中计算距离而不是欧几里得距离的替代有效方法的主要内容,如果未能解决你的问题,请参考以下文章

[ CS231n ] 图像分类

算法KNNSVM算法详解!

KNN分类器之NearestNeighbors详解及实践

邻居数 KNN 算法

有效计算单元阵列之间的欧几里得距离

欧几里得距离(python3,sklearn):有效地计算最近的对及其对应的距离