浅析Python中的随机采样和概率分布


Posted in Python onDecember 06, 2021

 Python(包括其包Numpy)中包含了了许多概率算法,包括基础的随机采样以及许多经典的概率分布生成。我们这个系列介绍几个在机器学习中常用的概率函数。先来看最基础的功能——随机采样。

1. random.choice

如果我们只需要从序列里采一个样本(所有样本等概率被采),只需要使用random.choice即可:

import random
res1 = random.choice([0, 1, 2, 3, 4])
print(res1) # 3

2. random.choices(有放回)

当然,很多时候我们不只需要采一个数,而且我们需要设定序列中每一项被采的概率不同。此时我们可以采用random.random.choices函数, 该函数用于有放回的(即一个数据项可以被重复采多次)对一个序列进行采样。其函数原型如下:

random.choices(population, weights=None, *, cum_weights=None, k=1)

population: 欲采样的序列

weights: 每个样本被赋予的权重(又称相对权重),决定每个样本被采的概率,如[10, 0, 30, 60, 0]

cum_weights: 累积权重,相对权重[10, 0, 30, 60, 0]相当于累积权重[10, 10, 40, 100, 100]

我们从[0, 1, 2, 3, 4]中按照相对权重采样3个样本如下:

res2 = random.choices([0, 1, 2, 3, 4], weights=[10, 0, 30, 60, 0], k=3)
# 注意population不是关键字参数,在函数调用时不能写成population=[0,1,2,3,4]来传参
# 关于关键字参数和位置参数,可以参看我的博客《Python技法2:函数参数的进阶用法》https://www.cnblogs.com/orion-orion/p/15647408.html
print(res2) # [3, 3, 2]

从[0, 1, 2, 3, 4]中按照累积权重采样3和样本如下:

res3 = random.choices([0, 1, 2, 3, 4], cum_weights=[10, 10, 40, 100, 100], k=3)
print(res3) # [0, 3, 3]

注意,相对权重weights和累计权重cum_weights不能同时传入,否则会报TypeError异常'Cannot specify both weights and cumulative weights'

3. numpy.sample(无放回)

random.sample是无放回,如果我们需要无放回采样(即每一项只能采一次),那我们需要使用random.sample。需要注意的是,如果使用该函数,将无法定义样本权重。该函数原型如下:

random.sample(population, k, *, counts=None)¶

population: 欲采样的序列

k: 采样元素个数

counts: 用于population是可重复集合的情况,定义集合元素的重复次数。sample(['red', 'blue'], counts=[4, 2], k=5)等价于sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)

我们无放回地对序列[0, 1, 2, 3, 4]采样3次如下:

res3 = random.sample([0, 1, 2, 3, 4], k=3)
print(res3) # [3, 2, 1]

无放回地对可重复集合[0, 1, 1, 2, 2, 3, 3, 4]采样3次如下:

res4 = random.sample([0, 1, 2, 3, 4], k=3, counts=[1, 2, 2, 2, 1])
print(res4) # [3, 2, 2]

如果counts长度和population序列长度不一致,会抛出异常ValueError:"The number of counts does not match the population"

4.rng.choices 和 rng.sample

还有一种有放回采样实现方法是我在论文[1]的代码[2]中学习到的。即先定义一个随机数生成器,再调用随机数生成器的choices方法或sample方法,其使用方法和random.choice/random.sample函数相同。

rng_seed = 1234
rng = random.Random(rng_seed)
res5 = rng.choices(
     population=[0,1,2,3,4],
     weights=[0.1, 0, 0.3, 0.6, 0],
     k=3,
)
print(res5) # [3, 3, 0]

res6 = rng.sample(
     population=[0, 1, 2, 3, 4],
     k=3,
)
print(res6) # [4, 0, 2]

这两个函数在论文[1]的实现代码[2]中用来随机选择任务节点client:

def sample_clients(self):
        """
        sample a list of clients without repetition

        """
        rng_seed = (seed if (seed is not None and seed >= 0) else int(time.time()))
        self.rng = random.Random(rng_seed)

        if self.sample_with_replacement:
            self.sampled_clients = \
                self.rng.choices(
                    population=self.clients,
                    weights=self.clients_weights,
                    k=self.n_clients_per_round,
                )
        else:
            self.sampled_clients = self.rng.sample(self.clients, k=self.n_clients_per_round)

5. numpy.random.choices

从序列中按照权重分布采样也可以采用numpy.random.choice实现。其函数原型如下:

random.choice(a, size=None, replace=True, p=None)

a: 1-D array-like or int   如果是1-D array-like,那么样本会从其元素中抽取。如果是int,那么样本会从np.arange(a)中抽取;

size: int or tuple of ints, optional   为输出形状大小,如果给定形状为(m,n,k),那么m×n×k的样本会从中抽取。默认为None,即返回一个单一标量。

replace: boolean, optional   表示采样是又放回的还是无放回的。若replace=True,则为又放回采样(一个值可以被采多次),否则是无放回的(一个值只能被采一次)。

p: 1-D array-like, optional   表示a中每一项被采的概率。如果没有给定,则我们假定a中各项被采的概率服从均匀分布(即每一项被采的概率相同)。

从[0,1,2,3,4,5]中重复/不重复采样3次如下:

import numpy as np
res1 = np.random.choice(5, 3, replace=True)
print(res1) # [1 1 4]

res2 = np.random.choice(5, 3, replace=False)
print(res2) # [2 1 4]

同样是[0,1,2,3,4,5]中重复/不重复采样3次,现在来看我们为每个样本设定不同概率的情况:

res3 = np.random.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0])
print(res3)  # [2 3 3]

res4 = np.random.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0])
print(res4) # [3 2 0]

参考文献

https://github.com/omarfoq/FedEM

https://www.python.org/

https://numpy.org/

到此这篇关于浅析Python中的随机采样和概率分布的文章就介绍到这了,更多相关Python内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python通过解析网页实现看报程序的方法
Aug 04 Python
详解在Python中处理异常的教程
May 24 Python
Python类的用法实例浅析
May 27 Python
Python使用sftp实现上传和下载功能(实例代码)
Mar 14 Python
Python和Java进行DES加密和解密的实例
Jan 09 Python
浅谈python中get pass用法
Mar 19 Python
Python语法分析之字符串格式化
Jun 13 Python
python lambda表达式(匿名函数)写法解析
Sep 16 Python
Python 装饰器原理、定义与用法详解
Dec 07 Python
Python 使用threading+Queue实现线程池示例
Dec 21 Python
聊聊python中的循环遍历
Sep 07 Python
python使用隐式循环快速求和的实现示例
Sep 11 Python
python程序的组织结构详解
Python中异常处理用法
Nov 27 #Python
python中的3种定义类方法
Nov 27 #Python
5道关于python基础 while循环练习题
Nov 27 #Python
Python中的pprint模块
Nov 27 #Python
python 多态 协议 鸭子类型详解
Nov 27 #Python
Python机器学习实战之k-近邻算法的实现
You might like
用php获取本周,上周,本月,上月,本季度日期的代码
2009/08/05 PHP
使用php测试硬盘写入速度示例
2014/01/27 PHP
php中http与https跨域共享session的解决方法
2014/12/20 PHP
PHP中把错误日志保存在系统日志中(Windows系统)
2015/06/23 PHP
php算法实例分享
2015/07/14 PHP
php生成二维码图片方法汇总
2016/12/17 PHP
PHP实现二维数组按照指定的字段进行排序算法示例
2019/04/23 PHP
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
基于jquery & json的省市区联动代码
2012/06/26 Javascript
input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
2013/04/02 Javascript
YUI模块开发原理详解
2013/11/18 Javascript
angularjs中的e2e测试实例
2014/12/06 Javascript
Js使用WScript.Shell对象执行.bat文件和cmd命令
2014/12/18 Javascript
zTree插件下拉树使用入门教程
2016/04/11 Javascript
jQuery获取当前点击的对象元素(实现代码)
2016/05/19 Javascript
微信小程序canvas写字板效果及实例
2017/06/15 Javascript
微信小程序如何修改本地缓存key中单个数据的详解
2019/04/26 Javascript
vue中在vuex的actions中请求数据实例
2019/11/08 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
[54:10]完美世界DOTA2联赛PWL S2 Magma vs FTD 第二场 11.29
2020/12/03 DOTA
python控制台英汉汉英电子词典
2020/04/23 Python
pygame 精灵的行走及二段跳的实现方法(必看篇)
2017/07/10 Python
Python实现的逻辑回归算法示例【附测试csv文件下载】
2018/12/28 Python
分析运行中的 Python 进程详细解析
2019/06/22 Python
pytorch进行上采样的种类实例
2020/02/18 Python
Mac中PyCharm配置Anaconda环境的方法
2020/03/04 Python
解决django的template中如果无法引用MEDIA_URL问题
2020/04/07 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
2021/03/03 Python
在HTML5 Canvas中放入图片和保存为图片的方法
2014/05/03 HTML / CSS
泰国的头号网上婴儿用品店:Motherhood.co.th
2019/04/09 全球购物
可持续未来的时尚基础:Alternative Apparel
2019/05/06 全球购物
《歌唱二小放牛郎》教学反思
2014/04/19 职场文书
2014年租房协议书范本
2014/10/30 职场文书
事业单位工作人员年度考核个人总结
2015/02/12 职场文书
雨雪天气温馨提示
2015/07/15 职场文书
微信小程序APP的事件绑定以及传递参数时的冒泡和捕获
2022/04/19 Javascript