Вектору присваивается стандартное отклонение матрицы столбцов, изменяется его значение (RcppArmadillo) - PullRequest
0 голосов
/ 26 января 2019

Я работаю над пакетом RcppArma и центрирую и стандартизирую матрицу проектирования для алгоритма повышения, это код, сокращенный:

// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
List centering(arma::mat & X) {

   int p = X.n_cols;

   rowvec meanx(p);
   rowvec sigmax(p);

    meanx=mean(X,0);
    sigmax=stddev(X,0);

    for(int j=0;j<p;j++)
    {
      X.col(j)=X.col(j)-meanx(j);
      X.col(j)=X.col(j)/sigmax(j);
    }

  return List::create(Named("sigma") = sigmax, Named("X") = X);
}

Центрирование работает нормально, но после центрирования вектор «sigmax» имеет все значения, равные «1», поэтому вектор каким-то образом обновился до нового стандартного отклонения центрированной матрицы X, не переназначаясь. Мне нужны исходные значения для обратного преобразования коэффициентов. Почему он это делает? Как я могу избежать этого?

Я проверил функцию в R со следующим кодом:

set.seed(42)    
X <- replicate(10, rnorm(100, 5, 3))
res <- centering(X)
res <- centering(X)

Проблема появляется, когда я звоню во второй раз. Первый раз работает.

1 Ответ

0 голосов
/ 26 января 2019

Проще говоря: не используйте ссылку (&) рядом с параметром X в определении функции. Это активирует использование RcppArmadillo расширенного конструктора для arma::mat, который повторно использует объектную память R (c.f. include/RcppArmadilloWrap.h)

Итак, чтобы решить эту проблему, перейдите по ссылке:

List centering_reuse_memory(arma::mat & X) {
                                    # ^ reference/reuse
  # Routine given in OP
}

Кому:

List centering_new_memory(arma::mat X) {
                                 # ^ Direct copy

  # Routine given in OP
}

Понимание обмена ...

Давайте посмотрим, как меняется объект.

# Create the original object
set.seed(42)    
X <- replicate(3, rnorm(5, 5, 3))

# Create a duplicate object not sharing memory with X
set.seed(42)    
X_clone <- replicate(3, rnorm(5, 5, 3))

# View object
X
#         [,1]      [,2]       [,3]
# [1,] 9.112875  4.681626  8.9146090
# [2,] 3.305905  9.534566 11.8599362
# [3,] 6.089385  4.716023  0.8334179
# [4,] 6.898588 11.055271  4.1636337
# [5,] 6.212805  4.811858  4.6000360

# Check equality
all.equal(X, X_clone)
# [1] TRUE

Теперь запустим функцию с параметром arma::mat & X

.
res <- centering_reuse_memory(X)

# Verify results are the same.
all.equal(X, X_clone)
# [1] "Mean relative difference: 8.387859"

# Check X manually to see what changed... 
X
#             [,1]       [,2]       [,3]
# [1,]  1.34167459 -0.7368308  0.6566715
# [2,] -1.45185917  0.8327104  1.3376293
# [3,] -0.11282266 -0.7257062 -1.2116948
# [4,]  0.27645691  1.3245379 -0.4417510
# [5,] -0.05344967 -0.6947113 -0.3408550

Почему есть разница? Итак, используя ссылки, изменения в функции C ++ распространяются обратно на переменную X, находящуюся в R , которая соответствует объекту, хранящемуся в res$X.

# Verify R's X matches the saved C++ routine X modification
all.equal(X, res$X)
# [1] TRUE
...