【问题标题】:Find K nearest neighbors, starting from a distance matrix从距离矩阵开始找到 K 个最近的邻居
【发布时间】:2014-06-20 09:53:30
【问题描述】:

我正在寻找一个经过优化的函数,它接受一个n X n 距离矩阵并返回一个n X k 矩阵,其中包含第i 行中第i 个数据点的k 最近邻居的索引。

我发现了无数不同的 R 包,它们可以让你做 KNN,但它们似乎都在同一个函数中包含了距离计算和排序算法。特别是,对于大多数例程,主要参数是原始数据矩阵,而不是距离矩阵。就我而言,我在混合变量类型上使用了非标准距离,因此我需要将排序问题与距离计算分开。

这并不完全是一个令人生畏的问题——我显然可以在循环中使用order 函数来获得我想要的东西(请参阅下面的解决方案),但这远非最佳。例如,当k 很小(小于11)时,sort 函数和partial = 1:k 运行得更快,但不幸的是只返回排序值而不是所需的索引。

【问题讨论】:

  • library(class) 有一个knn 函数。也许检查一下。这是一个分类包。
  • 是的,我在看class::knn。像其他人一样,它采用原始数据并应用欧几里得距离。我没有看到直接给它一个距离矩阵的方法。
  • 看看herestraight_distance <- function(p,q){sqrt((p-q)^2)} 不确定是不是这样,但您可能会在该页面上找到一些东西。

标签: r sorting matrix distance knn


【解决方案1】:

为了记录(我不会将此标记为答案),这是一个快速而肮脏的解决方案。假设sd.dist 是特殊距离矩阵。假设k.for.nn 是最近邻的数量。

n = nrow(sd.dist)
knn.mat = matrix(0, ncol = k.for.nn, nrow = n)
knd.mat = knn.mat
for(i in 1:n){
  knn.mat[i,] = order(sd.dist[i,])[1:k.for.nn]
  knd.mat[i,] = sd.dist[i,knn.mat[i,]]
}

现在knn.mat 是矩阵,每行包含k 最近邻居的索引,为方便起见,knd.mat 存储了相应的距离。

【讨论】:

  • 这认为一个点的最近邻是该点本身,因为您没有在order 函数中删除该点。
【解决方案2】:

尝试使用FastKNN CRAN 包(尽管它没有很好的文档记录)。它提供了k.nearest.neighbors 函数,可以给出任意距离矩阵。下面是一个计算所需矩阵的示例。

# arbitrary data
train <- matrix(sample(c("a","b","c"),12,replace=TRUE), ncol=2) # n x 2
n = dim(train)[1]
distMatrix <- matrix(runif(n^2,0,1),ncol=n) # n x n

# matrix of neighbours
k=3
nn = matrix(0,n,k) # n x k
for (i in 1:n)
   nn[i,] = k.nearest.neighbors(i, distMatrix, k = k)

注意:您可以随时查看 Cran 软件包列表中的 Ctrl+F='knn' 相关功能: https://cran.r-project.org/web/packages/available_packages_by_name.html

【讨论】: