【发布时间】:2020-08-03 15:31:19
【问题描述】:
我写了下面的函数来采样而不用替换。它返回一个vector<int>,表示在一些点中选取的样本。作为输入,我有一个vector<double>,其中包含所需样本大小的概率和一个整数。对于函数,我使用离散分布:
http://www.cplusplus.com/reference/random/discrete_distribution/discrete_distribution/
vector<int> samplingwoutreplacement(vector<double> probs, int samplesize) {
random_device rd;
mt19937 generator(rd());
vector<int> sample;
sample.reserve(samplesize);
for (int i = 0; i < samplesize; i++) {
discrete_distribution<int> distribution(probs.begin(), probs.end());
int currentpick = distribution(generator);
if (currentpick >= probs.size()) {
cout << endl << "error: range overstepped; current pick is: " << currentpick << endl;
cout << "probs.size = " << probs.size() << endl;
for (int j = 0; j < probs.size(); j++) {
cout << probs[j] << endl;
}
}
probs[currentpick] = 0;
sample.push_back(currentpick);
}
return sample;
}
在我的应用程序中,我多次使用这种采样,经过多次迭代后,离散分布返回的整数大于包含概率的向量的大小。 (更准确地说,我的向量大小为 178,我得到的返回值为 178,但应该得到介于 0 和 177 之间的整数。)这是怎么发生的?
【问题讨论】:
-
rd和generator应该是static。distribution应该在循环之外。rd甚至不需要,真的。你可以去mt19937 generator(random_device{}()); -
我没有收到那个错误。我尝试了 10M 的样本大小。进行我上面建议的调整后,我的程序也运行得更快了。
-
我想重复选择数字,但消除重复的可能性。因此,我将所选数字的概率设置为 0,并使用更新的概率初始化分布。所以,在我看来,分发不应该在循环之外。
-
对,明白了。在那部分上涂上光泽。将分布移回仍然不会触发错误。
-
更明确地说:pastebin 链接中的权重总和为 INFINITY (6.46e307 + 1.29e308 > 1.9e308 > DBL_MAX),这很容易在库中测试一个未充分测试的极端情况实施。
标签: c++ language-lawyer distribution sampling