#rcpp #markov
#rcpp #марков
Вопрос:
Я пытаюсь решить, имеет ли смысл внедрять оператор R %*% в RCpp, если мой набор данных огромен. НО у меня действительно возникли проблемы с получением реализации RCpp.
Вот мой пример R-кода
# remove everything in the global environment
rm(list = ls())
n_states = 4 # number of states
v_n <- c("H", "S1", "S2", "D") # the 4 states of the model:
n_t = 100 # number of transitions
# create transition matrix with random numbers. This transition matrix is constant.
m_P = matrix(runif(n_states*n_t), # insert n_states * n_t random numbers (can change this later)
nrow = n_states,
ncol = n_states,
dimnames = list(v_n, v_n))
# create markov trace, what proportion of population in each state at each period (won't make sense due to random numbers but that is fine)
m_TR <- matrix(NA,
nrow = n_t 1 ,
ncol = n_states,
dimnames = list(0:n_t, v_n)) # create Markov trace (n_t 1 because R doesn't understand Cycle 0)
# initialize Markov trace
m_TR[1, ] <- c(1, 0, 0, 0)
# run the loop
microbenchmark::microbenchmark( # function from microbenchmark library used to calculate how long this takes to run
for (t in 1:n_t){ # throughout the number of cycles
m_TR[t 1, ] <- m_TR[t, ] %*% m_P # estimate the Markov trace for cycle the next cycle (t 1)
}
) # end of micro-benchmark function
print(m_TR) # print the result.
И вот замена оператора %*%: (Который, похоже, вообще не работает правильно, хотя я не могу понять, почему.
library(Rcpp)
cppFunction(
'void estimate_markov(int n_t, NumericMatrix m_P, NumericMatrix m_TR )
{
// We want to reproduce this
// matrix_A[X 1,] <- matrix_A[X,] %*% matrix_B
// The %*% operation behaves as follows for a vector_V %*% matrix_M
// Here the Matrix M is populated with letters so that you can
// more easily see how the operation is performed
// So, a multiplication like this:
//
// V M
// {1} %*% {A D}
// {2} {B E}
// {3} {C F}
//
// Results in a vector:
// V_result
// {1*A 1*D}
// {2*B 2*E}
// {3*C 3*F}
//
// Now use values instead of letters for M (ex: A=1, B=2, .., F=6)
// V_result
// {1*1 1*4} {1 4} {5}
// {2*2 2*5} => {4 10} => {14}
// {3*3 3*6} {9 18} {27}
//
// Note that the RHS matrix may contain any number of columns,
// but *MUST* must contain the same number of rows as LHS vector
// Get dimensions of matricies , and sanity check
// number of elements in a vector from the LHS matrix must equal == number of row on the RHS
if( m_TR.cols() != m_P.rows())
throw std::range_error("Matrix mismatch, m_P.rows != m_TR.rows");
// we want to know these dimensions, and there is no reason to call these functons in a loop
// store the values once
int cnt_P_cols = m_P.cols();
int cnt_TR_cols = m_TR.cols();
//
for(int Index = 1; Index <= n_t; Index)
{
// iterate over the columns in m_TR
for(int col_iter = 0; col_iter < cnt_TR_cols; col_iter)
{
// an accumulator for the vector multiplication
double sum = 0;
// The new value comes from the previous row (Index-1)
double orig_TR = m_TR(col_iter, Index-1);
// iterate over the columns in m_P corresponding to this Index
for(int p_iter = 0; p_iter < cnt_P_cols; p_iter)
{
// accumulate the value of this TR scalar * the m_P vector
sum = orig_TR * m_P(p_iter, Index);
}
m_TR(col_iter, Index) = sum;
}
}
}'
)
Может кто-нибудь указать мне, где моя логика идет не так.
Комментарии:
1. Проверьте RcppEigen или RcppArmadillo . Вы пытаетесь изобрести велосипед.
2. Спасибо за ответ. Я посмотрел на RcppArmadillo, но в идеале я хотел бы иметь возможность выполнять такие функции самостоятельно. Потому что в конечном итоге у меня будут значительно более сложные задачи, связанные с Rcpp.
3. Вы не должны так легко отказываться от существующих инструментов. Настоящие эксперты, такие как доктор Сандерсон из Armadillo, потратили десятилетие на то, чтобы сделать эти вещи намного превосходными. Они отправляются в библиотеки LAPACK / BLAS для фактического умножения матриц. Теперь у вас есть десятилетний опыт в числовой математике. Теперь всегда можно улучшить ситуацию, но… это также становится все сложнее и сложнее.