随机抽样的元组向量与C ++中的权重

时间:2017-10-26 14:08:38

标签: c++ vector random tuples

我想知道是否有人可以提供帮助。

我正在寻找一种相当简单且理想的快速方法,从带有权重的元组向量中进行采样。

e.g。说我有一个元组的向量,每个都包含一个值和相应的权重/概率:

vector<tuple<int, double>> foo = { {1,0.04},{2,0.8},{ 3,0.01 },{ 4,0.03 },{ 
5,0.1 },{ 6,0.9 } };

我想通过foo并根据权重随机抽样,所以我最终得到一个向量(一个新的向量或替换foo中的元素),在这种情况下,有问题的大多数将是2和6.例如

 vector<tuple<int, double>> bar = { {2,0.8},{2,0.8},{ 6,0.9},{ 6,0.9 },{ 
6,0.9 },{ 6,0.9 } };

我确信使用像std :: discrete_distribution这样的东西很简单,虽然我还没弄清楚究竟是怎么做的。

编辑: 感谢您的帮助到目前为止,我可能已经使用了一些不良的术语&#34;重新采样&#34;。

本质上我想要的是采用元组的向量&#34; foo&#34;如上所述,并产生一个新的矢量&#34; bar&#34;它与foo的大小相同,由foo的元组组成,但元组是根据元组中的概率加权随机选择的。 - 希望这是有道理的。

2 个答案:

答案 0 :(得分:2)

这样的东西?

// Example program
#include <iostream>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::discrete_distribution<> d({0.04, 0.8, 0.01, 0.03, 0.1, 0.9});
    std::map<int, int> m;
    for(int n=0; n<100000; ++n) {
        ++m[d(gen)];
    }
    for(auto p : m) {
        std::cout << p.first+1 << " generated " << p.second << " times\n";
    } 
 }

1 generated 2089 times
2 generated 42472 times
3 generated 544 times
4 generated 1631 times
5 generated 5473 times
6 generated 47791 times

答案 1 :(得分:1)

std::discrete_distribution可行。以下使用权重来置换对的向量。它倾向于收敛到2或6,正如人们所期望的那样。

#include <random>
#include <vector>
#include <tuple>
#include <iostream>

std::ostream& operator<<(std::ostream& os,const std::vector<std::tuple<int, double>>& v)
{
    for(auto&& i : v)
        std::cout << "{" << std::get<0>(i) << ", " << std::get<1>(i) << "}\t";
    return os;
}

auto permute(std::vector<std::tuple<int, double>>& foo)
{
    std::vector<std::tuple<int, double>> temp;              // return value
    std::vector<double> v;                                  // weights
    for(auto&& i : foo)
        v.push_back(std::get<1>(i));                        // get weights
    std::discrete_distribution<int> dd{v.begin(), v.end()}; // create distribution
    static std::random_device rd;
    for(size_t i{}; i < foo.size(); ++i)
        temp.push_back(foo[dd(rd)]);                        // build return vector by selecting from foo according to weights
    return temp;
}

int main()
{
    std::vector<std::tuple<int, double>> foo = {{1, 0.04}, {2, 0.8}, {3, 0.01}, {4, 0.03}, {5, 0.1}, {6, 0.9}};
    std::cout << foo << '\n';
    for(size_t i{}; i < 10; ++i) {
        foo = permute(foo);
        std::cout << foo << '\n';
    }
}

示例输出:

{1, 0.04}       {2, 0.8}        {3, 0.01}       {4, 0.03}       {5, 0.1}        {6, 0.9}
{2, 0.8}        {5, 0.1}        {6, 0.9}        {2, 0.8}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {2, 0.8}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {2, 0.8}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {2, 0.8}
{6, 0.9}        {6, 0.9}        {2, 0.8}        {6, 0.9}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {2, 0.8}        {6, 0.9}        {2, 0.8}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {2, 0.8}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}
{6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}        {6, 0.9}