【问题标题】:(Speed Challenge) Any faster way to compute distance matrix in terms of generic Hamming distance?(速度挑战)根据通用汉明距离计算距离矩阵的任何更快的方法?
【发布时间】:2020-04-26 23:56:06
【问题描述】:

我正在寻找一种更有效的方法来获取Hamming distance 方面的距离矩阵。

背景

我知道包 e1071 中有一个函数 hamming.distance() 来计算距离矩阵,但我怀疑在涉及具有多行的大矩阵时它可能会非常慢,因为它应用了嵌套的 for 循环进行计算.

到目前为止,我在下面的代码中有一个更快的方法(请参阅methodB)。但是,它只适用于二进制域,即{0,1}^n。但是,当遇到包含两个以上元素的域时,它不可用,即{0,1,2,...,K-1}^n。从这个意义上说,methodB 不适用于通用汉明距离。

目标

我的目标是找到一种具有以下特点的方法:

  • 仅由基础 R 中的函数组成(不使用 Rcpp 重写函数以加快速度)
  • 对于特殊情况k=2,比我的方法更快methodB()
  • 可以泛化为任何正整数k
  • 优于 hamming.distance() 来自包 e1071 的速度

我的代码

library(e1071)
# vector length, i.e., number of matrix
n <- 7
# number of elements to consist of domain {0,1,...,k-1}^n
k <- 2
# matrix for computing hamming distances by rows
m <- as.matrix(do.call(expand.grid,replicate(n,list(0:k-1))))

# applying `hamming.distance()` from package "e1071", which is generic so it is available for any positive integer `k`
methodA <- function(M) hamming.distance(M)
# my customized method from base R function `dist()`, which is not available for cases `k >= 2`
methodB <- function(M) as.matrix(round(dist(M,upper = T,diag = T)**2))

基准给出了

microbenchmark::microbenchmark(
  methodA(m),
  methodB(m),
  unit = "relative",
  check = "equivalent",
  times = 50
)

Unit: relative
       expr      min       lq   mean   median       uq      max neval
 methodA(m) 33.45844 33.81716 33.963 34.30313 34.92493 14.92111    50
 methodB(m)  1.00000  1.00000  1.000  1.00000  1.00000  1.00000    50

提前欣赏!

【问题讨论】:

标签: r algorithm performance matrix hamming-distance


【解决方案1】:

我发现这个博客有四篇关于计算汉明矩阵的文章。我不想为此而声名狼藉,但也许可以看看它。 https://johanndejong.wordpress.com/2015/10/02/faster-hamming-distance-in-r-2/

hamming <- function(X) {
  D <- (1 - X) %*% t(X)
  D + t(D)
}

> microbenchmark::microbenchmark(
+   methodB(m),
+   hamming(m),
+   unit = "relative",
+   times = 50
+ )
Unit: relative
       expr    min       lq     mean   median       uq      max neval
 methodB(m) 1.0000 1.000000 1.000000 1.000000 1.000000 1.000000    50
 hamming(m) 1.2502 1.299844 1.436486 1.301461 1.302033 4.607748    50

PS:我没有足够的声望来发表评论。

【讨论】:

    【解决方案2】:
    methodM <- function(x) {
      xt <- t(x)
      sapply(1:nrow(x), function(y) colSums(xt != xt[, y]))
    }
    microbenchmark::microbenchmark(
      methodB(m), methodM(m),
      unit = "relative", check = "equivalent", times = 50
    )
    # Unit: relative
    #       expr  min       lq     mean   median       uq      max neval cld
    # methodB(m) 1.00 1.000000 1.000000 1.000000 1.000000 1.000000    50  a 
    # methodM(m) 1.25 1.224827 1.359573 1.219507 1.292463 4.550159    50   b
    

    【讨论】:

    • 感谢您的回答!是的,您的方法很快,可以扩展到k&gt;2 的情况。对于特殊情况k = 2,您有什么比我的methodB() 更快的想法吗?
    • @ThomasIsCoding 它并不快可能是因为不使用低级优化函数dist。这也计算所有距离,理想情况下我们希望使用更好的算法来计算仅上(下)三角形部分的值。
    • 是的,我明白了,也许我们已经是使用base R的速度限制了
    【解决方案3】:

    您是否尝试过使用Rcpp?我有一个非常相似的问题!请在此处查看答案:https://stackoverflow.com/a/60067825/3237589

    【讨论】:

    • 谢谢,但我想使用基本 R(而不是 Rcpp),正如我的帖子中所述
    猜你喜欢
    • 2020-04-27
    • 1970-01-01
    • 2014-09-25
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多