gpt4 book ai didi

r - 从距离矩阵创建 dist 对象的内存高效方法

转载 作者:行者123 更新时间:2023-12-04 14:16:20 24 4
gpt4 key购买 nike

我正在尝试创建 dist来自大距离矩阵的对象。我使用 stats::as.dist 内存不足.例如,我在当前机器上有大约 128 Gb 可用,但 as.dist处理 73,000 x 73,000 矩阵(约 42Gb)时内存不足。鉴于最后dist对象应该小于矩阵大小的一半(即它是下三角形,存储为向量)在我看来应该可以以更节省内存的方式进行此计算 - 只要我们小心创建大型中间对象,只需将输入的相关元素直接复制到输出。

查看 getS3method('as.dist', 'default') 的代码,我看到它使用 ans <- m[row(m) > col(m)] 进行计算这需要创建 rowcol与输入具有相同维度的矩阵。

我想我可以使用来自 here 的算法对此进行改进。生成下三角形的索引。这是我使用这种方法的尝试。

as.dist.new = function(dm, diag = FALSE, upper = FALSE) {
n = dim(dm)[1]
stopifnot(is.matrix(dm))
stopifnot(dim(dm)[2] == n)
k = 1:((n^2 - n)/2)
j <- floor(((2 * n + 1) - sqrt((2 * n - 1) ^ 2 - 8 * (k - 1))) / 2)
i <- j + k - (2 * n - j) * (j - 1) / 2
idx = cbind(i,j)
remove(i,j,k)
gc()
d = dm[idx]

class(d) <- "dist"
attr(d, "Size") <- n
attr(d, "call") <- match.call()
attr(d, "Diag") <- diag
attr(d, "Upper") <- upper
d
}

这适用于较小的矩阵。这是一个简单的例子:
N = 10
dm = matrix(runif(N*N), N, N)
diag(dm) = 0

x = as.dist(dm)
y = as.dist.new(dm)

然而,如果我们创建一个更大的距离矩阵,它会遇到与 as.dist 相同的内存问题。 .

例如。此版本在我的系统上崩溃:
N = 73000
dm = matrix(runif(N*N), N, N)
gc()
diag(dm) = 0
gc()

as.dist.new(dm)

有没有人建议如何更有效地执行此操作?欢迎使用 R 或 Rcpp 解决方案。 NB看着 this answer对于相关问题(从 2 列位置数据生成全距离矩阵),似乎可以使用 RcppArmadillo 来做到这一点。 ,但我没有使用它的经验。

最佳答案

嗯,遍历下三角的逻辑比较简单,
如果你用 C++ 来做,那么它也可以很快:

library(Rcpp)

sourceCpp(code='
// [[Rcpp::plugins(cpp11)]]

#include <cstddef> // size_t

#include <Rcpp.h>

using namespace Rcpp;

// [[Rcpp::export]]
NumericVector as_dist(const NumericMatrix& mat) {
std::size_t nrow = mat.nrow();
std::size_t ncol = mat.ncol();
std::size_t size = nrow * (nrow - 1) / 2;
NumericVector ans(size);

if (nrow > 1) {
std::size_t k = 0;
for (std::size_t j = 0; j < ncol; j++) {
for (std::size_t i = j + 1; i < nrow; i++) {
ans[k++] = mat(i,j);
}
}
}

ans.attr("class") = "dist";
ans.attr("Size") = nrow;
ans.attr("Diag") = false;
ans.attr("Upper") = false;
return ans;
}
')

as_dist(matrix(1:100, 10, 10))
1 2 3 4 5 6 7 8 9
2 2
3 3 13
4 4 14 24
5 5 15 25 35
6 6 16 26 36 46
7 7 17 27 37 47 57
8 8 18 28 38 48 58 68
9 9 19 29 39 49 59 69 79
10 10 20 30 40 50 60 70 80 90

关于r - 从距离矩阵创建 dist 对象的内存高效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59907035/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com