可视化随机采样的最佳方式c++

visual best way of random sampling c++

本文关键字:方式 c++ 最佳 随机 采样 可视化      更新时间:2023-10-16

我有一个长度为100万(0到100万)的数据向量a。从A,我想创建包含A索引的向量B(其长度仅为A的10%)。这些索引是从A中随机抽取的样本索引。我尝试过使用srand()和random_shuffle,这是为非常大的向量提取样本的好方法吗?有人能推荐我吗?

  std::vector <int> samplingIndex;
   for (int i = 0; i < 1000000; ++i) { samplingIndex.push_back(i); } 
   std::srand(50); 
   std::random_shuffle(samplingIndex.begin(), samplingIndex.end());

之后,我从samplingIndex中提取前10%的指数来制作B.

您可以使用Fisher–Yates shuffle,然后避免构建庞大的数组a:

类似于:

// Fisher–Yates_shuffle
std::vector<int> FisherYatesShuffle(std::size_t size,
                                    std::size_t max_size,
                                    std::mt19937& gen)
{
    assert(size <= max_size);
    std::vector<int> res(size);
    for (std::size_t i = 0; i != max_size; ++i) {
        std::uniform_int_distribution<> dis(0, i);
        std::size_t j = dis(gen);
        if (j < res.size()) {
            if (i < res.size()) {
                res[i] = res[j];
            }
            res[j] = i;
        }
    }
    return res;
}

实例

看起来很合理。一个调整是,你可以用这个替换for循环,以避免向量的重复重新分配:

std::vector <int> samplingIndex(1000000);
std::iota(samplingIndex.begin(), samplingIndex.end(), 0);

如果你的提取百分比远小于10%,那么在[0,len(A))中生成随机数是值得的,直到你得到len(B)的不同值。

您的代码是使用旧的C++编写的。我认为你应该在新的C++11/14中仔细观察随机性。

http://en.cppreference.com/w/cpp/algorithm/random_shuffle

如果您的输入来自AWGN源(或接近AWGN源),您可以每10个样本中选择一个样本,并在O(N)时间内完成工作(您想要10%的随机样本,对吗?)

否则,从一个巨大的向量中提取10%的随机样本的一种非常有效的方法是在每次选择索引时随机存储地提取样本。继续随机挑选项目,如果索引已经被提取,则重复。是的,这是一种概率方法,但您可以在最佳和平均场景中实现O(N)复杂性。最糟糕的情况是,你一次又一次地选择相同的索引,但这意味着一个非常非常糟糕的PRNG实现:你可以假设最坏的情况是一个非常不可能的场景(只需像哈希函数中那样保持足够低的几率)

您也可以使用链表并"短路"所选样本(将PRNG输出空间减少到N-1),但这需要额外的内存来存储链表。