基于自定义距离矩阵的KNN近邻查询及R实现咨询
解决自定义距离矩阵的k近邻问题(R语言)
我明白你的问题了——你尝试用FNN包的knn()函数传入自定义距离矩阵,但结果还是基于欧氏距离计算的,这是因为你误解了该参数的实际作用。让我拆解问题并给出高效的解决方案:
为什么你的FNN代码没生效?
FNN包的knn()函数中,distance_matrix参数的作用是预计算训练样本之间的距离矩阵(用于加速训练集内部的近邻计算),而不是用来定义测试样本到训练样本的距离。所以你传入的矩阵并没有被用来计算测试样本c(3,3)到训练样本的距离,函数依然默认用欧氏距离计算了(3,3)到(1,1)、(2,2)的距离,导致结果不符合预期。
高效实现自定义距离矩阵的k近邻
既然你已经有了自定义的距离规则(或预计算好的距离矩阵),最直接且高效的方式是直接对距离矩阵进行行级操作,提取每个测试样本的k个最小距离对应的训练样本索引,再映射标签。
单测试样本场景(你的示例)
# 定义训练样本、标签和测试样本 train <- rbind(c(1,1), c(2,2)) y <- c("one", "two") test <- rbind(c(3,3)) # 自定义测试样本到每个训练样本的距离(按训练样本顺序排列) test_to_train_dist <- c(2, 3) # 设置k值 k <- 1 # 获取k近邻的索引(按距离升序排列,取前k个) nn_indices <- order(test_to_train_dist)[1:k] # 生成结果 pred_label <- y[nn_indices] # 当k=1时,概率为1;若k>1,可根据多数投票或距离权重调整 prob <- if(k == 1) 1 else sum(test_to_train_dist[nn_indices] == min(test_to_train_dist))/k result <- data.frame(test, pred = pred_label, prob = prob) print(result)
运行后会得到符合预期的结果:pred为"one",prob为1。
多测试样本+大数据场景
如果有大量测试样本,预计算好n_test × n_train的距离矩阵后,推荐使用matrixStats包的向量化函数(比apply()快得多)来批量处理每行的k近邻:
library(matrixStats) # 示例:2个测试样本,3个训练样本的自定义距离矩阵 # 行=测试样本,列=训练样本 distance_matrix <- matrix(c(2, 5, 3, 4, 1, 6), nrow=2, byrow=TRUE) train_labels <- c("one", "two", "three") test_data <- rbind(c(3,3), c(4,4)) k <- 2 # 获取每行前k个最小距离的训练样本索引 nn_indices <- rowOrder(distance_matrix, cols = 1:k) # 映射标签(每个测试样本对应k个近邻标签) nn_labels <- train_labels[nn_indices] # 构造结果(这里以第一个近邻作为预测标签,概率为1/k,可根据需求调整) result <- data.frame( test_data, pred = nn_labels[,1], top2_nn = apply(nn_labels, 1, paste, collapse = ", "), prob = 1/k ) print(result)
总结
- 不需要依赖FNN的
knn()函数来处理自定义距离矩阵,直接操作距离矩阵是最高效的方式。 - 大数据场景下,用
matrixStats的向量化函数替代循环或apply(),能大幅提升速度。 - 如果需要更复杂的加权投票或距离权重计算,可以基于提取的近邻索引和距离值进一步扩展逻辑。
内容的提问来源于stack exchange,提问作者spartan
相关产品推荐
相关产品推荐

