You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于自定义距离矩阵的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:50:29