尝试编写最近邻算法 - 欧几里得距离函数只计算测试集的一行的距离 - 为啥?

Posted

技术标签:

【中文标题】尝试编写最近邻算法 - 欧几里得距离函数只计算测试集的一行的距离 - 为啥?【英文标题】:Trying to code the nearest neighbours algorithm - euclidean distance function only calculates the distances for one row of the test set - why?尝试编写最近邻算法 - 欧几里得距离函数只计算测试集的一行的距离 - 为什么? 【发布时间】:2021-12-03 04:29:57 【问题描述】:

我正在尝试从头开始编写最近邻算法,但遇到了一个问题 - 我的算法只为训练集的一行/点提供最近邻的索引/分类。我浏览了代码的每一部分,并意识到问题出在我的欧几里得距离函数上。它只给出一行的结果。

这是我为欧几里得距离写的代码:

def euclidean_dist(r1, r2):
    dist = 0
    for j in range(0, len(r2)-1):
        dist = dist + (r2[j] - r1[j])**2
    return dist**0.5

在我的最近邻算法中,这是欧几里得距离函数的实现:

for i in range(len(x_test)):
        dist1 = []
        dist2 = []
        for j in range(len(x_train)):
            distances = euclidean_dist(x_test[i], x_train[j,:])
            dist1.append(distances)
            dist2.append(distances)
        dist1 = np.array(dist1)
        sorting(dist1) #separate sorting function to sort the distances from lowest to highest,
#the aim was to get one array, dist1, with the euclidean distances for each row sorted
#and one array with the unsorted euclidean distances, dist2, (to be able to search for index later in the code)

我在使用 iris 数据集并尝试使用它的这部分功能时注意到了这个问题。我将数据集分为测试和训练(X_testX_trainy_test)。

当使用数据集实现这一点时,我得到了dist2 的以下数组:

[0.3741657386773946,
 1.643167672515499,
 3.389690251335658,
 2.085665361461421,
 1.284523257866513,
 3.9572717874818752,
 0.9539392014169458,
 3.5805027579936315,
 0.7211102550927979,
      ...
0.8062257748298555,
 0.4242640687119287,
 0.5196152422706631]

它的长度是 112,与X_train 的长度相同,但这些只是X_test 集合的第一行或第一点的欧几里得距离。 dist1 数组是相同的,只是它是排序的。

为什么我没有得到测试集每一行/点的欧几里得距离?我以为我用 for 循环正确地迭代了,但显然有些地方不太对劲。任何建议或帮助将不胜感激。

【问题讨论】:

x_test 上的每次迭代,都会重置 dist1 和 dist2。因此,您只有最后一个。顺便说一句,你真的应该为这种计算切换做 numpy 数组。 我怎样才能做到每次迭代都不会重置 dist1 和 dist2?我将如何使用 numpy 数组来改进这一点? 【参考方案1】:

将 numpy 用于速度、内置距离和代码长度:

x_test_array = np.array(x_test)
x_train_array = np.array(x_train)
distance_matrix = np.linalg.norm(x_test[:,np.newaxis,:]-x_train[np.newaxis,:,:], axis=2)

矩阵中的单元格 i,j 对应于 x_train[i] 和 x_test[j] 之间的距离。 然后就可以进行排序了。

编辑:如何在没有 numpy 的情况下创建距离矩阵:

matrix = []
for i in range(len(x_test)):
    dist1 = []
    for j in range(len(x_train)):
        distances = euclidean_dist(x_test[i], x_train[j,:])
        dist1.append(distances)
    matrix.append(dist1)

【讨论】:

嗨 - 有没有办法使用我的欧几里得距离代码而不是 np.linalg.norm 来做到这一点,并且仍然创建一个矩阵?我认为我不应该在这项任务中使用它。除了这个 - 在您提供的 np.linalg.norm 代码中,为什么 x_test 不包含在其中? 那是错字对不起修复它。如果没有 numpu,您可以创建列表列表。在第一个 for 循环之前创建一个列表并将其称为矩阵。然后在 i 上的每个循环结束时,将 dist 附加到矩阵。 我尝试将原始代码中的列表附加到一个空列表中,但显然我没有正确实现它。还有另一种我不知道的附加方法吗?感谢您的帮助!

以上是关于尝试编写最近邻算法 - 欧几里得距离函数只计算测试集的一行的距离 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

基于欧几里得距离的 1-最近邻分类器如何对观察进行分类

K-近邻算法入门

《机器学习实战》之k-近邻算法(手写识别系统)

KNN分类器之NearestNeighbors详解及实践

欧几里得距离两个像素,每个像素属于不同的图像

K近邻算法