[英]equivalent function to numpy.random.choice in C++
I need your help to solve the following problem:我需要您的帮助来解决以下问题:
Is there a function in c++/opencv which is equivalent to the following code: c++/opencv中是否有等价于以下代码的函数:
np.random.choice(len(vec), samples, p=probabilities[:,0], replace=True)
Thanks in advance.提前致谢。
Well, lets look at: numpy.random.choice(a, size=None, replace=True, p=None)
( see my comment, I guess you mixed up some of the function's parameters. )好吧,让我们看看: numpy.random.choice(a, size=None, replace=True, p=None)
(看我的评论,我猜你混淆了一些函数的参数。 )
For the input a
you are using an array of samples.对于输入a
您使用的是一组样本。 As an output size you want len(vec)
, you want sampling with replacement and have a custom non-uniform distribution.作为您想要的输出大小len(vec)
,您需要带替换采样并具有自定义的非均匀分布。
It is probably sufficient to first generate an array of indices using a random distribution and then using the array of indices to generate an array of selected elements.首先使用随机分布生成索引数组,然后使用索引数组生成所选元素的数组可能就足够了。
C++ offers help in generating non-uniform distributed numbers, being the std::discrete_distribution
C++ 提供了生成非均匀分布数的帮助,即std::discrete_distribution
Example:例子:
#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';
}
edit: link seems to suggest that std::default_random_engine
performs sampling with replacement.编辑:链接似乎表明std::default_random_engine
执行带替换采样。
seems you are looking to sample from a discrete random distribution似乎您正在寻找从离散随机分布中采样
the example on that page is fairly demonstrative:该页面上的示例相当具有示范性:
// 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;
}
I don't think there is a function that gives you this for free.我认为没有一个功能可以免费为您提供此功能。 You may have to write it yourself.您可能需要自己编写。
Some hints as to how to write such a function:关于如何编写这样一个函数的一些提示:
vector<float>
storing your probabilities.假设您有一个vector<float>
存储您的概率。 First use std::partial_sum
on this vector to get the accumulated probabilities of the elements.首先在这个向量上使用std::partial_sum
来获得元素的累积概率。random_value
.然后,对于每个样本,生成一个介于 0 和 1 之间的随机浮点数。我们称之为random_value
。 Iterate over your vector of accumulated probabilities until you find a value bigger than random_value
.迭代累积概率向量,直到找到大于random_value
的值。 The index at this point is your sample index.此时的索引是您的示例索引。 Take the value at this index in your samples
vector, store it somewhere and repeat.在您的samples
向量中获取此索引处的值,将其存储在某处并重复。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.