gpt4 book ai didi

c++ - 加速 C/Rcpp 中 Dice 系数的计算

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:14:28 26 4
gpt4 key购买 nike

我需要计算一个相似性度量,称为 R 中二进制 vector 的大型矩阵 (600,000 x 500) 上的 Dice 系数。为了提高速度,我使用 C/Rcpp。该功能运行良好,但由于我不是背景计算机科学家,我想知道它是否可以运行得更快。此代码适合并行化,但我没有并行化 C 代码的经验。

Dice 系数是相似性/不相似性的简单度量(取决于您如何看待)。它旨在比较不对称二元 vector ,这意味着其中一个组合(通常为 0-0)并不重要,并且一致(1-1 对)比不一致(1-0 或 0-1 对)具有更大的权重。想象一下以下列联表:

   1    0
1 a b
0 c d

骰子系数为:(2*a)/(2*a +b + c)

这是我的 Rcpp 实现:

library(Rcpp)
cppFunction('
NumericMatrix dice(NumericMatrix binaryMat){
int nrows = binaryMat.nrow(), ncols = binaryMat.ncol();
NumericMatrix results(ncols, ncols);
for(int i=0; i < ncols-1; i++){ // columns fixed
for(int j=i+1; j < ncols; j++){ // columns moving
double a = 0;
double d = 0;
for (int l = 0; l < nrows; l++) {
if(binaryMat(l, i)>0){
if(binaryMat(l, j)>0){
a++;
}
}else{
if(binaryMat(l, j)<1){
d++;
}
}
}
// compute Dice coefficient
double abc = nrows - d;
double bc = abc - a;
results(j,i) = (2*a) / (2*a + bc);
}
}
return wrap(results);
}
')

这是一个运行示例:

x <- rbinom(1:200000, 1, 0.5)
X <- matrix(x, nrow = 200, ncol = 1000)
system.time(dice(X))
user system elapsed
0.814 0.000 0.814

最佳答案

Roland 提出的解决方案并不完全满足我的用例。因此,基于 arules 包的源代码,我实现了一个更快的版本。 arules 中的代码依赖于 Leisch (2005) 使用 R 中的 tcrossproduct() 函数的算法。

首先,我编写了 crossprod 的 Rcpp/RcppEigen 版本,速度提高了 2-3 倍。这基于 RcppEigen 插图中的示例代码。

library(Rcpp)
library(RcppEigen)
library(inline)
crossprodCpp <- '
using Eigen::Map;
using Eigen::MatrixXi;
using Eigen::Lower;

const Map<MatrixXi> A(as<Map<MatrixXi> >(AA));

const int m(A.rows()), n(A.cols());

MatrixXi AtA(MatrixXi(n, n).setZero().selfadjointView<Lower>().rankUpdate(A.adjoint()));

return wrap(AtA);
'

fcprd <- cxxfunction(signature(AA = "matrix"), crossprodCpp, "RcppEigen")

然后我写了一个小的 R 函数来计算 Dice 系数。

diceR <- function(X){
a <- fcprd(X)

nx <- ncol(X)
rsx <- colSums(X)

c <- matrix(rsx, nrow = nx, ncol = nx) - a
# b <- matrix(rsx, nrow = nx, ncol = nx, byrow = TRUE) - a
b <- t(c)

m <- (2 * a) / (2*a + b + c)
return(m)
}

这个新函数比旧函数快约 8 倍,比 arules 中的函数快约 3 倍。

m <- microbenchmark(dice(X), diceR(X), dissimilarity(t(X), method="dice"), times=100)
m
# Unit: milliseconds
# expr min lq median uq max neval
# dice(X) 791.34558 809.8396 812.19480 814.6735 910.1635 100
# diceR(X) 62.98642 76.5510 92.02528 159.2557 507.1662 100
# dissimilarity(t(X), method = "dice") 264.07997 342.0484 352.59870 357.4632 520.0492 100

关于c++ - 加速 C/Rcpp 中 Dice 系数的计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16938508/

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