【问题标题】:Obtaining k-reciprocal nearest neighbours获得k-倒数最近邻
【发布时间】:2019-06-10 09:15:49
【问题描述】:

我的问题的背景信息:

如果两个对象在彼此的k-最近邻中,则它们称为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行。如果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 循环,而且这两个组的大小可能很大。

【问题讨论】:

  • 当你有两组对象时,你能澄清一下倒数最近邻是如何工作的吗?第一个例子只使用一组数字,而问题实际上使用了两个不相交的集合。
  • 糟糕,我不是很清楚。在背景信息部分,将集合与自身的副本进行比较以产生 4x4 距离矩阵。副本的价值应该相同,但身份不同。抱歉,我只能在明天编辑帖子。
  • 我不熟悉这个问题。 scipy 不是已经为此实现了功能吗?参见例如scikit-learn.org/stable/modules/generated/…
  • 我在scikit中看到的(叫做NearestNeighbours)是逐行处理数组的,但我需要的是元素更明智,所以我觉得它不适合。这不是一个成熟的问题,我只是在一篇论文中看到了这个概念,并且也有兴趣这样做

标签: python python-3.x


【解决方案1】:

您必须检查这是否更快,因为我在您提供的代码中没有看到任何嵌套的 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 ))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 2014-04-12
    • 1970-01-01
    • 2018-04-08
    • 2014-05-14
    • 2018-05-09
    • 2011-12-06
    相关资源
    最近更新 更多