gpt4 book ai didi

c++ - 将 R 的种子从 Rcpp 更改为保证可重复性

转载 作者:太空狗 更新时间:2023-10-29 20:21:34 24 4
gpt4 key购买 nike

我正在尝试在 rcpp 中编写一个函数 r(d, n)。该函数从正态分布 N(0, d) 中随机抽取 n 次。这个函数应该被很好地定义,因此只要 d 和 n 不改变它们的值,函数就应该返回相同的绘制。

如果 d 被限制为整数,这将不是问题,在这种情况下我可以设置种子并完成工作

// set seed
// [[Rcpp::export]]
void set_seed(unsigned int seed) {
Rcpp::Environment base_env("package:base");
Rcpp::Function set_seed_r = base_env["set.seed"];
set_seed_r(seed);
}

// function r(d, n)
// [[Rcpp::export]]
vec randdraw(int d, int n){
set_seed(d);
vec out = randn(n);
return out;
}

但显然我不想将 d 限制为整数。理想情况下 d 应该是双倍的。有什么想法吗?谢谢!

最佳答案

我认为正在发生的问题是您正在尝试分散 Armadillo 提供的 randn,它仅限于标准常态,例如N(0,1),使其匹配 N(0, d)。有两种方法可以解决这个问题,因为它是标准常态。

选项 1:使用统计属性

第一种方法只涉及将样本乘以 d 的平方根,例如sqrt(d)*sample。这是可能的,因为方差和期望的随机变量属性给出 sqrt(d)*N(0, 1) ~ N(0, sqrt(d)^2) ~ N(0, d)。

这里要注意的一件更重要的事情是 set_seed() 函数将在 Armadillo 配置为 RcppArmadillo hooks into R's RNG library 后起作用。访问 ::Rf_runif 函数以生成随机值。唯一需要注意的是,由于 Section 6.3 of Writing R Extensions 中详述的 R/C++ 交互限制,您不能使用 arma::arma_rng::set_seed() 设置种子。 .如果你确实使用它,那么 you would get warned with :

When called from R, the RNG seed has to be set at the R level via set.seed()

在第一个检测到的调用上。

话虽如此,这里是一个简短的代码示例,其中我们乘以 sqrt(d)

代码:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// set seed
// [[Rcpp::export]]
void set_seed(double seed) {
Rcpp::Environment base_env("package:base");
Rcpp::Function set_seed_r = base_env["set.seed"];
set_seed_r(std::floor(std::fabs(seed)));
}

// function r(d, n)
// [[Rcpp::export]]
arma::vec randdraw(double d, int n){
set_seed(d); // Set a seed for R's RNG library
// Call Armadillo's RNG procedure that references R's RNG capabilities
// and change dispersion slightly.
arma::vec out = std::sqrt(std::fabs(d))*arma::randn(n);
return out;
}

输出:

> randdraw(3.5, 5L)
[,1]
[1,] -0.8671559
[2,] -1.9507540
[3,] 2.9025090
[4,] -1.2953745
[5,] 2.0799176

注意:由于 rnorm 过程与 arma::randn 生成不同,所以没有直接的等价物。

选项 2:依赖 R 的 RNG 函数

第二种明显更好的解决方案是显式依赖 R 的 RNG 函数。之前,由于 RcppArmadillo 的配置,我们隐式使用了 R 的 RNG 库。我倾向于使用这种方法,因为您已经假设在使用 the set_seed() function 时代码特定于 R (免责声明:我写了帖子)。如果您担心 dinteger 的限制,可以从 doubleint 进行轻微的强制转换与 std::floor(std::fabs(seed))。使用 Rcpp::r*()R::r*() 生成值后,将使用 an advanced ctor 创建 Armadillo vector 。重用现有的内存分配。

代码:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// set seed
// [[Rcpp::export]]
void set_seed(double seed) {
Rcpp::Environment base_env("package:base");
Rcpp::Function set_seed_r = base_env["set.seed"];
set_seed_r(std::floor(std::fabs(seed)));
}

// function r(d, n)
// [[Rcpp::export]]
arma::vec randdraw(double d, int n){
set_seed(d); // Set a seed for R's RNG library
Rcpp::NumericVector draws = Rcpp::rnorm(n, 0.0, d); // Hook into R's Library
// Use Armadillo's advanced CTOR to re-use memory and cast as an armadillo object.
arma::vec out = arma::vec(draws.begin(), n, false, true);
return out;
}

输出:

> randdraw(3.21,10)
[,1]
[1,] -3.08780627
[2,] -0.93900757
[3,] 0.83071017
[4,] -3.69834335
[5,] 0.62846287
[6,] 0.09669786
[7,] 0.27419092
[8,] 3.58431878
[9,] -3.91253230
[10,] 4.06825360
> set.seed(3)
> rnorm(10, 0, 3.21)
[1] -3.08780627 -0.93900757 0.83071017 -3.69834335 0.62846287 0.09669786 0.27419092 3.58431878 -3.91253230 4.06825360

关于c++ - 将 R 的种子从 Rcpp 更改为保证可重复性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43221681/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com