获取k倒数最近的邻居

时间:2019-06-10 09:15:49

标签: python python-3.x

有关我的问题的背景信息:

如果两个对象彼此相邻,则称为彼此的 k -倒数最近邻居。我只对不交集的对象感兴趣。例如,考虑两组数字 S = {0,1,2} T = {0.1,1.1,1.9} k = 2 。 对于组 S

    T 0
  • k 最近邻是 0.1,1.1
  • T 中 1 k 个最近邻居是 1.1,1.9
  • T 2
  • k 最近邻是 1.9,2.1

对于组 T

  • S 中 0.1
  • k 个最近邻居是 0,1
  • S 中 1.1 k 个最近邻居是 1、2
  • S 1.9 k 个最近邻居是 1、2

因此,成对的 k -倒数最近邻居是(0,0.1),(1,1.1),(1,1.9),(2,1.9)


{A,B,C,D,E} {W,X,Y,Z} 是某些对象的两个不相交的组。假设欧氏度量在这两个组之间有意义,并且我们有以下 5x4 距离矩阵:

distmat = np.array([[5,   1,   4, 7.5], 
                    [3,  10,   2,  11], 
                    [9, 2.5,   8,   3], 
                    [1,   3, 5.5,   5],
                    [4,   6, 3.5,   8]])

五行分别表示对象 A,B,C,D,E W,X,Y,Z 的距离。

问题:获得 A B k 倒数最近的邻居的有效方法是什么? >?

获取 k 最近的邻居是可以的,我使用np.argsort(distmat),然后检索索引小于 k 的对象。

这就是我尝试的对等部分。 wlog考虑对象 A 。对于 A 的每个 k 个最近邻居 N ,转置distmat并检查 N -th行。如果 A N k 最近邻,则它们是倒数;否则他们不是。一些粗略的代码:

for index_N, N in enumerate(knn_A): 
    knn_N = get_knn(distmat.T[index_N]
    if A in knn_N: 
        print("{} and {} are {}-reciprocals".format(A, N, k))

有什么改进建议吗?这很慢,因为我已经有许多嵌套的for循环,而且这两个组的大小可能很大。

1 个答案:

答案 0 :(得分:0)

由于您提供的代码中没有嵌套的for循环,因此您必须检查这是否更快。使用您的示例(由于行“ T中2的k最近邻为1.9,2.1。”这一行,我认为它的对等邻居是错误的。-其中2.1不在集合中,如果您的意思是1.1,则(2, 1.1)也是互惠的邻居。

import numpy as np 
import itertools 

# set k and make the example set
k = 2
s1 = [0, 1, 2]
s2 = [.1, 1.1, 1.9]

#create the distance matrix 
newarray = [ [ abs(s2j-s1i) for s2j in s2] for s1i in s1]
distmat = np.array( newarray )

#get the nearest neighbors for each set 
neighbors_si = np.argsort( distmat )
neighbors_sj = np.argsort( distmat.T )

#map element of each set to k nearest neighbors
neighbors_si = { i: neighbors_si[i][0:k] for i in range(len(neighbors_si)) }
neighbors_sj = { j: neighbors_sj[j][0:k] for j in range(len(neighbors_sj)) }

#for each combination of i and j determine if they are in each others neighbor list
for i, j in itertools.product( neighbors_si.keys(), neighbors_sj.keys() ):
    if j in neighbors_si[i] and i in neighbors_sj[j]:
        print( '{} and {} are {}-reciprocals'.format( s1[i], s2[j], k ))