提问人:Adhithi S 提问时间:5/31/2023 最后编辑:Adhithi S 更新时间:5/31/2023 访问量:82
在 cpp 中使用 Seedsequence 复制随机数生成器的生成
Replicate the generation of random number generators using Seedsequence in cpp
问:
我正在将用 python 编写的 Gibb 采样器转换为 cpp。虽然代码工作正常,但存在可重复性问题。Python 代码能够为任何一组种子生成类似的输出,其中 cpp 代码结果在不同的运行中不一致。
以下代码片段用于在 Python 中为不同的迭代生成随机数:
ss=np.random.SeedSequence()
child_states = ss.spawn(n) #n is the number of iterations
for i in range(0,n):
inference(child_states[i]);
def inference(seed):
child_states = seed.spawn(len(Docs))
for i in range(len(Docs)):
seq(seed);
def seq(seed):
rng = np.random.default_rng(seed)
for i in range(0,V):
z=rng.multinomial(................)
以下是使用 pcg64 对象在 c++ 中尝试的代码片段:
void inference(){
pcg_extras::seed_seq_from<std::random_device> seedSource;
pcg64 rng(seedSource);
for(int i=0;i<m;i++)
gsl_rng_set(r, rng());
for(int j=0;j<V;j++)
gsl_ran_multinomial(..................)
}
有没有办法在 CPP 中实现相同的伪随机数生成步骤?
修改更新: 对于少量样品,我能够解决重现性问题。所以我尝试的是
std::vector<unsigned int> seed_values(10);
std::generate(seed_values.begin(), seed_values.end(),
std::ref(rd));
std::seed_seq seq(seed_values.begin(), seed_values.end());
生成一组 M 种子,并使用它来生成 M 个种子序列,如下所示
std::seed_seq seq{seed};
std::vector<std::uint64_t> seeds(m);
seq.generate(seeds.begin(), seeds.end());
这适用于少量样本,但当样本数量很大时,似乎两个样本被分配了相似的随机数。种子位数会不会成为问题,因为在 Python 中种子位数至少为 128 位,而在 cpp 中最多为 64 位。
答:
在 C++ 中,通常按如下方式初始化伪随机数生成器:
std::default_random_engine e((std::random_device())());
它产生一个随机数生成器,其中或多或少是随机选择的种子。
如果将其替换为固定种子,则无论编译程序运行多少次,都将收到相同的伪随机数序列;尝试例如
std::default_random_engine e(1012);
std::uniform_int_distribution<int> uid(0, 1000);
for(size_t i = 1; i <= 100; ++i)
{
std::cout << std::setw(3) << uid(e) << (i % 10 ? ' ' : '\n');
}
std::cout.flush();
如果解析命令行参数,则可以动态交换序列,同时仍可控制何时接收与其他程序运行相同的序列。
C++ 带有相当多的预实现算法和发行版,请参阅 cpPreference – 如果其中有与 python 使用的算法和发行版相同的算法和发行版,那么您甚至有可能在 python 和 C++ 中为相同的种子生成相同的序列,但不能保证,实现细节的差异也可能阻止它。
上面使用 C++ 标准随机库(我宁愿推荐它而不是一些第三方库),因为我不熟悉 PCG 库。如果你更喜欢继续后者:那个使用种子生成器,我不知道它会多久调用一次,尽管在我看来,只假设一次似乎是合理的。如果您现在将代码片段替换为自定义代码片段,则始终在其中返回相同的预定义种子(您可以调整静态变量以通过命令行参数控制它),那么您可以再次可靠地重现相同的序列(但您需要自己测试......std::random_device
operator()
评论
rd
std::random_device
std::seed_seq seq({12, 10, 51, 77, 54});
上一个:研究论文中的随机种子
下一个:如何从上下文设定数据库种子
评论
std::random_device