分配矩阵列标准偏差的向量正在改变其值(RcppArmadillo)
Vector assigned the standard deviation of matrix columns is changing its value (RcppArmadillo)
我正在研究一个 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)
第二次调用时出现问题。第一次成功。
简单地说:不要在函数定义中使用参数 X
旁边的引用 (&
)。这会激活 RcppArmadillo 对 an advanced constructor for arma::mat
that re-uses the R object memory (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
现在,运行参数pass为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++ 函数中的修改传播回驻留在 R 中的 X
变量,即 匹配 存储在 res$X
.
的对象
# Verify R's X matches the saved C++ routine X modification
all.equal(X, res$X)
# [1] TRUE
我正在研究一个 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)
第二次调用时出现问题。第一次成功。
简单地说:不要在函数定义中使用参数 X
旁边的引用 (&
)。这会激活 RcppArmadillo 对 an advanced constructor for arma::mat
that re-uses the R object memory (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
现在,运行参数pass为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++ 函数中的修改传播回驻留在 R 中的 X
变量,即 匹配 存储在 res$X
.
# Verify R's X matches the saved C++ routine X modification
all.equal(X, res$X)
# [1] TRUE