如何在RcppArmadillo中复制随机抽样?

4
这里有一个C ++函数,用于绘制具有零均值和标准偏差为sN个独立正态分布随机数。
// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]] 
List rnorm_cpp(double s, int N){

    arma::colvec epsilon = s * arma::randn(N);
    return List::create(Named("e") = epsilon);

}

这里有一个(几乎相同的)R版本

rnormR <- function(s, N){

  epsilon <- rnorm(N, mean = 0, sd = s)
  return(list(e = epsilon))

}    

在引用了rnorm_cpprnormR之后,我运行了以下代码:

set.seed(1234)
fooR <- rnormR(s = 5, N = 10)

set.seed(1234)
barR <- rnormR(s = 5, N = 10)

set.seed(1234)
fooCpp <- rnorm_cpp(s = 5, N = 10)

set.seed(1234)
barCpp <- rnorm_cpp(s = 5, N = 10)

最后,我运行了identical命令,并得到了以下结果:

> identical(fooR, barR)
[1] TRUE
> identical(barR, fooCpp)
[1] FALSE
> identical(fooCpp, barCpp)
[1] FALSE

我原以为这三个变量的结果都将是TRUE,但事实并非如此。如何实现:(1)使得多次调用rnorm_cpp时生成相同的随机数;(2)让rnormRrnorm_cpp产生相同的随机数?


你难道不需要假设 Rcpp 的 RNG 与 R 的相同吗?这是一个可疑的命题。 - IRTFM
1
因为这是真的 :) 这一直是 Rcpp 的一个特性 - 但在这里他正在调用 Armadillo 的 RNG,而这个假设确实是可疑的,正如我刚刚详细说明的那样。 - Dirk Eddelbuettel
1个回答

8
函数 arma::randn() 与 R RNGs 没有关联,因此调用 set.seed() 不会对其产生影响。
在 Rcpp 中,我们利用了精细的 R API,这使得我们可以从 R 和 C++ 访问相同的 RNGs。通过在 RNGScope 实例中小心谨慎地使用(这些实例会自动插入),RNG 状态始终在 R 和 C++ 之间正确。
但是,你不能假设任何其他第三方 RNG(在这里是 Arma)也已经自动对齐。此外,在这种特殊情况下,Conrad 的 Armadillo 文档很清楚:

要更改种子,请使用 std::srand() 函数。

为了说明问题(嗨,@DWin),这里是一个完整的 R 和 C++ 示例:
R> set.seed(42); rnorm(5)           ## Five N(0,1) draws in R
[1]  1.3710 -0.5647  0.3631  0.6329  0.4043
R> cppFunction('NumericVector foo(int n) { return rnorm(n); }')
R> set.seed(42); foo(5)             ## Five N(0,1) draws from C++ fun.
[1]  1.3710 -0.5647  0.3631  0.6329  0.4043
R> 

我们通过相同的随机数生成器种子和实际调用R提供的相同随机数生成器,使用R和C++得到了相同的数字。


对,这很有道理。所以,如果我从这里实现第一个示例:http://gallery.rcpp.org/articles/timing-normal-rngs/,我就能按预期设置种子? - inhuretnakht
使用 Rcpp 变量的 rnorm(),然后将其赋值给 arma 向量。 - Dirk Eddelbuettel
@DirkEddelbuettel,我从您在这里的回答中所理解的是,在Arma和R之间找不到种子号码的映射方式?如果您想要验证您在Arma中编写的函数与R中的函数是否相同,那么您会怎么做呢?非常感谢。 - Sam
这是一个具有统计答案的统计问题。您有两个不同的生成器,并且需要对结果进行分布比较。否则,您可以避免这个问题并在C++代码中使用R RNG。这是Rcpp的默认设置。 - Dirk Eddelbuettel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接