16

目前我正在使用内置函数 dist 来计算我在 R 中的距离矩阵。

dist(featureVector,method="manhattan")

这是当前应用程序的瓶颈,因此想法是并行化此任务(从概念上讲这应该是可能的)

搜索谷歌和这个论坛没有成功。

有人有想法吗?

4

6 回答 6

19

R 包amap为聚类和主成分分析提供了强大的并行化功能。在这些函数中,Dist方法提供了您正在寻找的东西:以并行方式计算并返回距离矩阵。

Dist(x, method = "euclidean", nbproc = 8)

上面的代码用 8 个线程计算欧几里得距离。

于 2014-09-10T14:08:01.047 回答
4

这是您可以走的一条路线的结构。它并不比仅仅使用dist()函数更快,而是花费了很多倍的时间。它确实是并行处理的,但即使计算时间减少到零,启动函数并将变量导出到集群的时间也可能比仅仅使用dist()

library(parallel)

vec.array <- matrix(rnorm(2000 * 100), nrow = 2000, ncol = 100)

TaxiDistFun <- function(one.vec, whole.matrix) {
    diff.matrix <- t(t(whole.matrix) - one.vec)
    this.row <- apply(diff.matrix, 1, function(x) sum(abs(x)))
    return(this.row)
}

cl <- makeCluster(detectCores())
clusterExport(cl, list("vec.array", "TaxiDistFun"))

system.time(dist.array <- parRapply(cl, vec.array,
                        function(x) TaxiDistFun(x, vec.array)))

stopCluster(cl)

dim(dist.array) <- c(2000, 2000)
于 2013-08-01T22:00:31.423 回答
3

您还可以使用parallelDistparDist包的功能,该包专为并行距离矩阵计算而构建。优点是该软件包可在 Mac OS、Windows 和 Linux 上使用,并且已经支持 39 种不同的距离测量(请参阅parDist)。

曼哈顿距离的性能比较(系统规格:Mac OS;Intel Core i7,4 核 @ 2.5 GHz 并启用超线程):

library(parallelDist)
library(amap)
library(wordspace)
library(microbenchmark)

set.seed(123)
x <- matrix(rnorm(2000 * 100), nrow = 2000, ncol = 100)

microbenchmark(parDist(x, method = "manhattan"),
               Dist(x, method = "manhattan", nbproc = 8),
               dist.matrix(x, method = "manhattan"),
               times = 10)

Unit: milliseconds
                                      expr      min       lq     mean   median       uq      max neval
          parDist(x, method = "manhattan") 210.9478 214.3557 225.5894 221.3705 237.9829 247.0844    10
 Dist(x, method = "manhattan", nbproc = 8) 749.9397 755.7351 797.6349 812.6109 824.4075 844.1090    10
      dist.matrix(x, method = "manhattan") 256.0831 263.3273 279.0864 275.1882 296.3256 311.3821    10

使用更大的矩阵:

x <- matrix(rnorm(10000 * 100), nrow = 10000, ncol = 100)
microbenchmark(parDist(x, method = "manhattan"),
+                Dist(x, method = "manhattan", nbproc = 8),
+                dist.matrix(x, method = "manhattan"),
+                times = 10)
Unit: seconds
                                      expr       min        lq      mean    median        uq       max neval
          parDist(x, method = "manhattan")  6.298234  6.388501  6.737168  6.894203  6.947981  7.221661    10
 Dist(x, method = "manhattan", nbproc = 8) 22.722947 24.113681 24.326157 24.477034 24.658145 25.301353    10
      dist.matrix(x, method = "manhattan")  7.156861  7.505229  7.544352  7.567980  7.655624  7.800530    10

进一步的性能比较可以在parallelDist's vignette中找到。

于 2017-06-28T22:20:56.887 回答
2

我是一个 Windows 用户,正在寻找一种有效的方法来计算距离矩阵以在层次聚类中使用它(例如,使用“stats”包中的函数 hclust)。函数Dist 在 Windows 中不能并行工作,所以我不得不寻找不同的东西,我找到了包含该函数的 Stefan Evert 的“wordspace”包。dist.matrix你可以试试这段代码:

X <- data.frame(replicate(1000,sample(0:1,5000,rep=TRUE)))
system.time(d <- dist(X, method = "manhattan"))
system.time(d2 <- as.dist( dist.matrix(as.matrix(X), method="manhattan") ))

如您所见,计算具有 1000 个二进制特征和 5000 个实例的数据帧的距离矩阵要快得多dist.matrix

这些是我的笔记本电脑(i7-6500U)中的结果:

> system.time(d <- dist(X, method = "manhattan"))
   user  system elapsed 
 151.79    0.04  152.59 
> system.time(d2 <- as.dist( dist.matrix(as.matrix(X), method="manhattan") ))
   user  system elapsed 
  19.19    0.22   19.56 

这解决了我的问题。在这里您可以查看我找到它的原始线程: http ://r.789695.n4.nabble.com/Efficient-distance-calculation-on-big-matrix-td4633598.html

它不能并行解决它,但在很多情况下就足够了。

于 2016-10-04T15:19:57.050 回答
1

我也在使用较大的距离矩阵并试图加快计算速度。上面的 Will Benson 说“启动函数并将变量导出到集群的时间可能比仅仅使用更长”时,他可能是正确的。

但是,我认为这适用于小到中等大小的距离矩阵。请参阅下面的示例,其中使用了具有 10 个处理器Dist的包amapdist 、包statsrdistfields中的函数,这些函数调用了 Fortran 函数。第一个示例创建一个 400 x 400 距离矩阵。第二个创建一个 3103 x 3103 距离矩阵。

require(sp)
require(fields)
require(amap)
data(meuse.grid)
meuse.gridA <- meuse.grid[1:400, 1:2]
meuse.gridB <- meuse.grid[, 1:2]

# small distance matrix
a <- Sys.time()
invisible(dist(meuse.gridA, diag = TRUE, upper = TRUE))
Sys.time() - a
Time difference of 0.002138376 secs
a <- Sys.time()
invisible(Dist(meuse.gridA, nbproc = 10, diag = TRUE, upper = TRUE))
Sys.time() - a
Time difference of 0.005409241 secs
a <- Sys.time()
invisible(rdist(meuse.gridA))
Sys.time() - a
Time difference of 0.02312016 secs

# large distance matrix
a <- Sys.time()
invisible(dist(meuse.gridB, diag = TRUE, upper = TRUE))
Sys.time() - a
Time difference of 0.09845328 secs
a <- Sys.time()
invisible(Dist(meuse.gridB, nbproc = 10, diag = TRUE, upper = TRUE))
Sys.time() - a
Time difference of 0.05900002 secs
a <- Sys.time()
invisible(rdist(meuse.gridB))
Sys.time() - a
Time difference of 0.8928168 secs

请注意,与距离矩阵较大 (3103 x 3103) 时Dist相比,计算时间如何从 0.09845328 秒减少到 0.05900002 秒。dist因此,我建议您使用amapDist包中的函数,前提是您有多个可用处理器。

于 2014-11-23T12:58:52.153 回答
0

我发现 parallelDist 比 dist 快几个数量级,并且在我的 Mac 上的 Microsoft R Open 3.4.0 下在此过程中消耗的虚拟内存要少得多。一个警告虽然 - 我没有运气在 R 3.3.3 上编译它。它没有将 R 的版本列为依赖项,但我怀疑它是。

于 2017-08-25T23:03:46.460 回答