【问题标题】:equivalent function to numpy.random.choice in C++C++ 中 numpy.random.choice 的等效函数
【发布时间】:2017-03-21 11:45:51
【问题描述】:

我需要你的帮助来解决以下问题:

c++/opencv中有没有相当于下面代码的函数:

np.random.choice(len(vec), samples, p=probabilities[:,0], replace=True)

提前致谢。

【问题讨论】:

标签: c++ opencv c++11 non-uniform-distribution


【解决方案1】:

好吧,让我们看看:numpy.random.choice(a, size=None, replace=True, p=None) (看我的评论,我猜你把函数的一些参数弄混了。)

对于输入 a,您使用的是样本数组。作为您想要len(vec) 的输出大小,您希望进行替换采样并具有自定义的非均匀分布。

首先使用随机分布生成索引数组,然后使用索引数组生成选定元素数组可能就足够了。

C++ 提供了生成非均匀分布数的帮助,即std::discrete_distribution

例子:

#include <random>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
    auto const samples = { 1, 2, 3, 4, 5, 6 }; // deducts to std::initializer_list<int>
    auto const probabilities = { 0.1, 0.2, 0.1, 0.5, 0.0, 1.0 }; // deducts to std::initializer_list<double>
    if (samples.size() < probabilities.size()) {
        std::cerr << "If there are more probabilities then samples, you will get out-of-bounds indices = UB!\n";
        return -1;
    }

    // generate non-uniform distribution (default result_type is int)
    std::discrete_distribution const distribution{probabilities};
    // note, for std::vector or std::array of probabilities, use
    // std::discrete_distribution distribution(cbegin(probabilities), cend(probabilities));

    int const outputSize = 10;

    std::vector<decltype(distribution)::result_type> indices;
    indices.reserve(outputSize); // reserve to prevent reallocation
    // use a generator lambda to draw random indices based on distribution
    std::generate_n(back_inserter(indices), outputSize,
        [distribution = std::move(distribution), // could also capture by reference (&) or construct in the capture list
         generator = std::default_random_engine{}  //pseudo random. Fixed seed! Always same output.
        ]() mutable { // mutable required for generator
            return distribution(generator);
        });

    std::cout << "Indices: ";
    for(auto const index : indices) std::cout << index << " ";
    std::cout << '\n';

    // just a trick to get the underlying type of samples. Works for std::initializer list, std::vector and std::array
    std::vector<decltype(samples)::value_type> output;
    output.reserve(outputSize); // reserve to prevent reallocation
    std::transform(cbegin(indices), cend(indices),
        back_inserter(output),
        [&samples](auto const index) {
            return *std::next(cbegin(samples), index);
            // note, for std::vector or std::array of samples, you can use
            // return samples[index];
        });

    std::cout << "Output samples: ";
    for(auto const sample : output) std::cout << sample << " ";
    std::cout << '\n';
}

On godbolt.org

编辑:link 似乎暗示std::default_random_engine 执行采样 替换。

【讨论】:

    【解决方案2】:

    您似乎希望从discrete random distribution 中取样

    该页面上的示例具有相当的示范性:

    // discrete_distribution
    #include <iostream>
    #include <random>
    
    int main()
    {
      const int nrolls = 10000; // number of experiments
      const int nstars = 100;   // maximum number of stars to distribute
    
      std::default_random_engine generator;
      std::discrete_distribution<int> distribution {2,2,1,1,2,2,1,1,2,2};
    
      int p[10]={};
    
      for (int i=0; i<nrolls; ++i) {
        int number = distribution(generator);
        ++p[number];
      }
    
      std::cout << "a discrete_distribution:" << std::endl;
      for (int i=0; i<10; ++i)
        std::cout << i << ": " << std::string(p[i]*nstars/nrolls,'*') << std::endl;
    
      return 0;
    }
    

    【讨论】:

    • 好的,我输入答案的时间太长了,也许我也应该从网站上复制示例代码,而不是尝试编写代表他的问题的代码;P
    • 我确实看到了解决方案,但我有概率!到时候还能用吗?
    【解决方案3】:

    我认为没有任何功能可以免费为您提供此功能。您可能需要自己编写。

    关于如何编写这样一个函数的一些提示:

    • 假设您有一个vector&lt;float&gt; 存储您的概率。首先在这个向量上使用std::partial_sum,得到元素的累积概率。
    • 然后,对于每个样本,生成一个介于 0 和 1 之间的随机浮点数。我们称之为random_value。迭代累积概率向量,直到找到大于random_value 的值。此时的索引是您的示例索引。在您的 samples 向量中获取此索引处的值,将其存储在某处并重复。

    【讨论】:

    • 他为什么要累积他的元素的概率?
    • @J.H.Bonarius 因为这样,他可以对 0 到 1 之间的数字进行采样,并通过与部分和比较得到正确的元素。与每个元素的单独概率进行比较是行不通的。当然,如果您使用的是std::discrete_distribution,则无需担心。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 2013-05-23
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    相关资源
    最近更新 更多