умножение матричной матрицы в Rcpp

77
6

Я пытаюсь ускорить некоторый R код с Rcpp который принимает вектор длины L (psi) и матрицу измерений (L, L) и выполняет некоторые элементарные операции. Есть ли более эффективный способ выполнять эти элементарные операции с Rcpp?

р:

 UpdateLambda <- function(psi,phi){
# updated full-day infection probabilites
psi.times.phi <- apply(phi,1,function(x) x*psi)
## return Lambda_{i,j} = 1 - \prod_{j} (1 - \psi_{i,j,t} \phi_{i,j})
apply(psi.times.phi,2,function(x) 1-prod(1-x))
}

каст:

#include <Rcpp.h>
#include <algorithm>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector UpdateLambdaC(NumericVector psi,
NumericMatrix phi
){

int n = psi.size();
NumericMatrix psi_times_phi(n,n);
NumericVector tmp(n,1.0);
NumericVector lambda(n);

for(int i=0; i<n;i++){
psi_times_phi(i,_) = psi*phi(i,_);
}

for(int i=0; i<n;i++){
// \pi_{j} (1- \lambda_{i,j,t})
for(int j=0; j<n;j++){
tmp[i] *= 1-psi_times_phi(i,j);
}
lambda[i] = 1-tmp[i];
}

return lambda;
}

спросил(а) 2021-01-25T17:59:59+03:00 4 месяца, 4 недели назад
1
Решение
63

Вы можете заменить apply циклы с помощью векторизованных альтернатив.

Первый из них эквивалентен:

t(phi)*psi

И второе:

1-exp(colSums(log(1-psi.times.phi)))

#test data
phi <- matrix(runif(1e6),1e3)
psi <- runif(1e3)

#new function
UpdateLambda2 <- function(psi,phi) 1-exp(colSums(log(1-t(phi)*psi)))

#sanity check
identical(UpdateLambda(psi,phi),UpdateLambda2(psi,phi))
[1] TRUE

#timings
library(rbenchmark)
benchmark(UpdateLambda(psi,phi),UpdateLambda2(psi,phi))
test replications elapsed relative user.self sys.self
1 UpdateLambda(psi, phi) 100 16.05 1.041 15.06 0.93
2 UpdateLambda2(psi, phi) 100 15.42 1.000 14.19 1.19

Похоже, что это не имеет большого значения, что очень удивительно, поскольку colSums обычно намного быстрее, чем apply. Я не уверен, что тестовые данные, которые я использовал, являются релевантными, так как на выходе есть все 1 из числа умножений числа меньше 1 во второй части. В любом случае, вы можете лучше работать в масштабе журнала, если хотите отметить детали таких небольших чисел.

ответил(а) 2021-01-25T17:59:59+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема