• 问题
  • 解决方案之一
  • 解决方案之二集合实现
  • 解决方案之三集合实现的优化
  • 解决方案之四

随机数的妙用:上回书说到的关于用蒙特卡洛方法进行一些数值计算(比如pi的逼近、特殊几何图像面积(存在解析解)的计算),都还是随机数较为间接的应用(也就是我所说的,将随机数转换为一种均匀分布的概率表现),这节我们考察随机数更为直接的应用,那就是随机采样。

问题

生成随机整数的有序子集。程序的输入包括两个整数mnm < n,输出是[0, n)范围内的有序随机整数列表。从概率的角度要求,得到的每个选择都是等概率。

这里我们还可以对比matlab的随机采样的高层工具箱函数。randperm()randsample。(对matlab不感兴趣的可以略过此节)

  • randperm函数形式较为简单
p = randperm(n);        # 对n的全排列(permutation)
p = randperm(n, k);     # 返回全排列的k个值(不允许重复)

小应用(实现对原始数据的按行重新排列)

X = randn(n, m);
Y = X(randperm(size(X, 1)), :);
  • randsample函数重载较多,功能也相对强大
y = randsample(n,k)
y = randsample(population,k)
y = randsample(n,k,replacement)
y = randsample(population,k,replacement)
  • 重载1用法同randperm
  • 重载2或者写作y = randsample(ARRAY, k),从数组中随机选出k个不同的数
  • replacement是一个bool变量,为1的时候,允许重复,反之不允许,默认不允许。

实现类似的数据重新按行排列的语句:

X = randn(n, m);
Y = X(randsample(1:size(X, :), size(X, 1), 0), :)

X是一个向量时:

X = randn(n, 1);
Y = randsample(X, length(X), 0);

解决方案之一

我们以考察0, 1, 2, ..., n-1整数序列为例,逐个考察每个整数的随机选择情况,不妨先取m = 2, n = 5,则第一个整数0被选中的概率为:

if (rand() % n < 2)

我们却不能按照此形式继续考察1, 2, ...

  • 如果0被选中,则紧接着1被选中的概率为
if (rand()% (n-1) < (m-1))
//if (rand() % (5-1) < (2-1))
// 也即是在余下的(n-1)个数中,仅有(m-1)次被选中的机会
  • 如果0不被选中,则紧接着1被选中的概率为:
if (rand()%(n-1) < m)   // 这里的深层含义是:以条件判断表达概率
// if (rand()%(5-1) < 2)
// 也即是在余下的(n-1)个数中,仍有m次被选中的机会

也即是,如果要从\n\n个余下的整数中选中其中的\m\m个,我们以\fracmn\fracmn选择下一个数

实现如下:

#include <iostream>
using namespace std;
void randsample(unsigned n, unsigned m)
{unsigned select = m;unsigned remaining = n;unsigned i;for (i = 0; i < n; ++i){// 每一次循环,比如第i次循环,考察的是它被选中的概率// 考察到第i次时,可见之前已经历了共i次的判断(从0开始计数)// 也就是在余下的(n-i)个值中找到i出现的概率if (rand() % remaining < select){cout << i << " ";    // 表示i被选中--select;}--remaining;}cout << endl;
}

我们还可以继续简化这个函数,并使用一个数组存放这些随机采样值:

#include <iostream>
using namespace std;
void randsample(unsigned n, unsigned m, unsigned arr[])
{unsigned idx = 0;for (unsigned i = 0; i < n; ++i){if (rand() % (n-i) < m){arr[idx++] = i;--m;}}
}

我们也可递归化(忽然想到一个话题,就是递归和数学归纳法的关系,这个问题的讨论留待以后了)这个实现。

void randsample(unsigned n, unsigned m)
{if (n <= m)return ;if (rand() % n < m){cout << n - 1 << " ";randsample(n-1, m-1);}elserandsample(n-1, m);
}

解决方案之二(集合实现)

我们利用集合自身的性质(即不允许重复),以及C++STLset类模板的性质(自动被排序,因标准的STL setRB-tree为底层机制)来实现随机采样值的生成。

#include <set>
using namespace std;
//typedef set<unsigned> SampleSet;
void randsample(unsigned n, unsigned m)
{set<unsigned> s;while (s.size() < m)s.insert(rand()%n);    // 集合的性质保证了最终得到的数据没有重复set<unsigned>::const_iterator = it;for (it == s.begin(); it != s.end(); ++it)cout << *it <<  " ";cout << endl;
}

解决方案之三(集合实现的优化)

我们来分析解决方案二可能存在的问题就是当m非常接近n时,进行

s.insert(rand()%n);         // 会存在大量无意义的值的添加操作

如何保证m的时间复杂度呢?

void randsample(unsigned n, unsigned m)
{set<unsigned> s;for (unsigned i = n-m; i < n; ++i){unsigned t = rand()%(i+1);if (s.find(t) == s.end())// t <= is.insert(t);else// i >= i,这样每次循环,循环m次都有一个随机值的产生,只不过是否等概率,就要打个问号了s.insert(i);}
}

解决方案之四

生成随机整数的有序子集的另一种方法是首先把0, 1, ..., n-1的数组顺序打乱,这称为shuffle,也是一种排列,permutation

这里首先介绍一个randint(unsigned l, unsigned u)函数,

unsigned randint(unsigned l, unsigned u)
{return l + rand() % (u-l+1);// rand() % (u-l+1) -> [0, u-l]// [0, u-l] -> [l, u]// 也即是实现了[l, u]闭区间的随机整数采样
}
void genshuffle(unsigned n, unsigned m)
{unsigned* x = (unsigned*)malloc(sizeof(unsigned)*n);for (unsigned i = 0; i < n; ++i)x[i] = i;for (unsigned i = 0; i < m; ++i){unsigned j = randint(i, n-1);unsigned t = x[i]; x[i] = x[j]; x[j] = t; // swap(x[i], x[j]);}sort(x, x+m); // 如果不进行排序,genshuffle的功能就类似于randperm(n, m)for (unsigned i = 0; i < m; ++i)cout << x[i] <<  " ";cout << endl;
}

x[0, ...,i-1]记录已选中的元素集合,x[i, ..., n-1]表示未选中的元素集合。以这种机制避免了对新元素是否已经选中的判断。

从随机数生成到随机采样的C++实现相关推荐

  1. Python-pcl 随机采样一致性算法

    RANSAC 随机采样一致性算法 RANSAC是一种随机参数估计算法.RANSAC从样本中随机抽选出一个样本子集,使用最小方差估计算法对这个子集计算模型参数,然后计算所有样本与该模型的偏差,在使用一个 ...

  2. 随机采样池化--S3Pool: Pooling with Stochastic Spatial Sampling

    S3Pool: Pooling with Stochastic Spatial Sampling CVPR2017 https://github.com/Shuangfei/s3pool 本文将常规池 ...

  3. 机器学习中的数据不平衡问题----通过随机采样比例大的类别使得训练集中大类的个数与小类相当,或者模型中加入惩罚项...

    机器学习中的数据不平衡问题 摘自:http://wap.sciencenet.cn/blogview.aspx?id=377102 最近碰到一个问题,其中的阳性数据比阴性数据少很多,这样的数据集在进行 ...

  4. ML之FE:数据随机抽样之利用pandas的sample函数对超大样本的数据集进行随机采样,并另存为csv文件

    ML之FE:数据随机抽样之利用pandas的sample函数对超大样本的数据集进行随机采样,并另存为csv文件 目录 数据随机抽样之利用pandas的sample函数对超大样本的数据集进行随机采样,并 ...

  5. 5.7 随机采样最小二乘法

    5.7 随机采样最小二乘法 如果万一出现差错,又难以检测出,则强影响点影响很大,此时可以采用一种随机方法,尽量避免差错带来的影响. 随机最小二乘法不采用所有测量数据,而是随机抽取部分测量数据,根据这些 ...

  6. 最小二乘法以及RANSAC(随机采样一致性)思想及实现

    线性回归–最小二乘法(Least Square Method) 线性回归: 什么是线性回归? 举个例子,某商品的利润在售价为2元.5元.10元时分别为4元.10元.20元, 我们很容易得出商品的利润与 ...

  7. 【python】随机采样的两种方法

    python中需要在一定区间内进行采样,或是对生成的数据进行采样,可以利用随机模块random.sample()函数或者numpy.random.choice()函数实现. 1.随机采样 如果需要对某 ...

  8. 设置随机种子之后,网络训练结果仍然不同的解决方法(针对随机采样的数据集)torch设置随机种子,num_worker对数据采样的影响。

    网络训练结果无法复现 设置随机种子 应该为torch, numpy,以及Python设置随机种子,并提高torch卷积精度. def set_seed(seed):random.seed(seed)n ...

  9. 一种推理优化新思路,对特征图进行[随机采样-插值]

    分享一篇ECCV 2020 的论文:Spatially Adaptive Inference with Stochastic Feature Sampling and Interpolation 论文 ...

最新文章

  1. 20131003国庆作业例4-4,4-5,4-6.
  2. CG CTF CRYPTO easy!
  3. [转][C/C++]函数名字修饰(Decorated Name)方式
  4. java手机飞行模式_用了这么多年手机才知道,飞行模式还藏着这6个功能!太好用了...
  5. 计算机网络基础文档,计算机网络基础-20210608152532.pdf-原创力文档
  6. simulink学习笔记(2)
  7. 错过就找不到了 Java API文档 免费下载!!!
  8. new 操作符干了什么?
  9. WinRAR 曝 19 年前重大漏洞,可完全控制电脑!| 附解决方法
  10. IO流-设置输出字符编码格式
  11. jQuery当当网项目实现
  12. 经典中的经典算法:动态规划(详细解释,从入门到实践,逐步讲解)
  13. CentOS官方免费下载地址,包含CentOS7和CentOS8
  14. ubuntu18安装Domoticz(内网穿透)和home assistant(docker安装)
  15. 闲庭信步聊前端 - 见微知著微前端
  16. XSuperNEST套料引擎
  17. AUTOCAD——偏移命令、移动命令
  18. java如何判断回文数
  19. 跃居超导和离子阱的量子计算黑马,可编程可扩展的光量子硬件
  20. 局域网SDN技术硬核内幕 - 前传 突破多核的瓶颈——虚拟化

热门文章

  1. oracle数据库文件默认的安装位置,Oracle 10g数据库默认安装应该注意的问题
  2. Sklearn——Sklearn的介绍与安装
  3. OpenCV精进之路(十一):感兴趣区域ROI和logo添加技术
  4. jsp java代码取session_jsp中的session在java文件中取到
  5. SQL SERVER中的二种获得自增长ID的方法
  6. django缓存优化(二)
  7. MySQL教程(十二)—— 数据的导入与导出
  8. servlet监听器Listener(理论+例子)
  9. Yahoo的14条准则
  10. HDU2999 Stone Game, Why are you always there?【SG函数】