【问题标题】:Nearest neighbour vector matching without replacement无替换的最近邻向量匹配
【发布时间】:2018-08-11 09:44:40
【问题描述】:

我想在 R 中执行以下操作:对于向量 X 中的每个元素,我想要向量 Y 中的最近邻,这样每个 X-Y 匹配之间的绝对差之和最小化。向量 Y 至少和向量 X 一样长。

问题是:我想在不替换的情况下执行此操作。例如,给定:

X= c(3, 6)
Y= c(1, 2, 4, 10),

我想获得Z= c(2, 4),因为匹配 3 到 2 和 6 到 4 比匹配 3 到 4 和 6 到 10 创建的总距离更小。

*这是我的第一个堆栈问题,因此对于我在提问时所犯的任何错误,请提前道歉。

更新:为了使用@merv 更具说明性的示例和术语,我正在寻找匹配的全局最优值,而不是局部最优值(第一个/贪婪匹配)。例如,如果X= c(3,7)Y= c(1,4,12),我想获得Z= c(1, 4),它的曼哈顿距离为5。我不想要第一个/贪婪匹配,这将是Z= c(4, 12)——这将获得通过找到最接近 3 的匹配项,然后找到最接近 7 的匹配项。

【问题讨论】:

  • 试试Y[findInterval(X, Y)]
  • @akrun 解决方案很好,但你也可以:Y[sapply(X, function(x) which.min(abs(Y - x)))]
  • 谢谢你们;然而,虽然这些建议适用于我给出的具体示例,但它们不适用于以下情况:X= c(10, 12)Y= c(1, 11, 14)。 @akrun 的建议给了c(1, 11),而@PoGibas 的建议给了c(11, 11)。答案应该是c(11, 14),因为 10 应该匹配 11,而 12 应该匹配 14。
  • 为什么12 匹配14,而不匹配11
  • 更新了问题以解决@merv 的查询

标签: r nearest-neighbor


【解决方案1】:

蛮力

如果您可以假设对此的大多数输入都会很小,那么最简单的方法是扩展搜索空间的所有可能组合。

uniqueNearestNeighbor <- function (X, Y) {
  zs <- combn(Y, length(X))
  dists <- apply(zs, 2, function (z) sum(abs(X - z)))
  return(zs[,which.min(dists)])
}

请注意,这假设您的向量都已排序。

> uniqueNearestNeighbor(c(3, 7), c(1, 4, 12))
[1] 1 4

如果您的搜索空间很大 (Y),但输入维度较低 (X),您可以修剪搜索空间以帮助限制组合的数量。例如,您可以安全地排除 Y 中不至少是 X 中点的第 k 个最近邻的所有点,其中 kX的维度。

算法方法

如果您确实有很大的搜索空间并且修剪不足以缩小问题,或者如果您将重复计算它并且它成为一个明显的瓶颈,您将需要采用更复杂的方法。在我的脑海中,我认为the A* algorithm 似乎很适合这个问题。对于可接受的启发式函数,可以使用X 中每个点到Y 中最近邻点的距离之和。在每次迭代中,将X 中的一个点分配给它最近的邻居,然后沿着树向下移动该点并移除其受让人。如果X 中的给定x 有多个最近邻(例如,x = 2Y 包含 1 和 3),则必须在搜索空间中包含这两个选项。

这将达到一个全局最优值,由于可证明的性质,给定任何XY,对于所有全局最优值,X 中的至少一个x 被分配给它在@ 中的最近邻居987654342@。因此,所描述的树将包含所有可能的全局最优值,并且由于 A* 是广度优先搜索,因此可以保证找到其中一个。

如果您需要走这条路,也值得在cs.stackexchange.com 上询问,因为可能有更合适的算法。

【讨论】:

  • 感谢@merv 的周到回复。我也相信蛮力是要走的路:我使用了 optmatch 包的 pairmatch 功能,我怀疑它完全按照你在引擎盖下描述的那样做。
【解决方案2】:

这是一个优化问题。您需要的是使用匈牙利算法,它完全符合您的要求。

【讨论】:

    【解决方案3】:

    正如 Amol 所指出的,这正是 hungarian algorithm 的目标:在最小化全局成本的同时找到最佳配对。您需要做的就是指定一个 cost 矩阵,在这里我将其作为点之间的 L1/L2 距离。

    复制 OP 的第二个示例,使用 RcppHungarian,得到相同的解决方案 Z= c(1, 4)5 的相同最低成本:

    library(RcppHungarian)
    
    X= c(3,7)
    Y= c(1,4,12)
    D <- outer(X, Y, function(x, y) abs(x-y))
    
    out <- HungarianSolver(D)
    out
    #> $cost
    #> [1] 5
    #> 
    #> $pairs
    #>      [,1] [,2]
    #> [1,]    1    1
    #> [2,]    2    2
    Y[out$pairs[,2]]
    #> [1] 1 4
    

    reprex package (v2.0.1) 于 2021 年 11 月 23 日创建

    【讨论】:

      猜你喜欢
      • 2017-07-11
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 2019-06-15
      • 2018-03-04
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多