AI智能
改变未来

Python中的随机采样和概率分布(二)

在上一篇博文《Python中的随机采样和概率分布(一)》(链接:https://www.cnblogs.com/orion-orion/p/15647408.html)中,我们介绍了Python中最简单的随机采样函数。接下来我们更进一步,来看看如何从一个概率分布中采样,我们以几个机器学习中最常用的概率分布为例。

1. 二项(binomial)/伯努利(Bernoulli)分布

1.1 概率质量函数(pmf)

\\[P(X = x;\\space n, \\space p)=\\left(\\begin{array}{c}n \\\\ x\\end{array}\\right) p^{x}(1-p)^{n-x}\\\\x=0,1,2,…n; \\space 0\\leqslant p \\leqslant 1\\]

当\\(n=1\\)时,则取到下列极限情况,是为参数为\\(p\\)的二项分布:

\\[P(X = x;\\space p)= p^{x}(1-p)^{1-x}\\\\x=0,1; \\space 0\\leqslant p \\leqslant 1\\]

二项分布\\(P(X = x;\\space n, \\space p)\\)可以表示进行独立重复试验\\(n\\)次,每次有两成功和失败可能结果(分别对应概率\\(p\\)和\\(1-p\\)),共成功\\(x\\)次的概率。

1.2 函数原型

random.binomial(n, p, size=None)

参数:

n

: int or array_like of ints   对应分布函数中的参数

n

,>=0,浮点数会被截断为整形。

p

: float or array_like of floats   对应分布函数参数\\(p\\), >=0并且<=1。

size

: int or tuple of ints, optional   如果给定形状为\\((m, n, k)\\),那么\\(m\\times n \\times k\\)个随机样本会56c从中抽取。默认为None,即返回一个一个标量随机样本。

返回:

out

: ndarray or scalar  从带参数的概率分布中采的随机样本,每个样本表示独立重复实验\\(n\\)次中成功的次数。

1.3 使用样例

设进行独立重复实验10次,每次成功概率为0.5,采样样本表示总共的成功次数(相当于扔10次硬币,正面朝上的次数)。总共采20个样本。

import numpy as npn, p = 10, .5s = np.random.binomial(n, p, 20)print(s) # [4 5 6 5 4 2 4 6 7 2 4 4 2 4 4 7 6 3 5 6]

可以粗略的看到,样本几乎都在5周围上下波动。
我们来看一个有趣的例子。一家公司钻了9口井,每口井成功的概率为0.1,所有井都失败了,发生这种情况的概率是多少?
我们总共采样2000次,来看下产生0结果的概率。

s = sum(np.random.binomial(9, 0.1, 20000) == 0)/20000.print(s) # 0.3823

可见,所有井失败的概率为0.3823,这个概率还是蛮大的。

2. 多项(multinomial)分布

2.1 概率质量函数(pmf)

\\[P(\\bm{56cX} = \\bm{x};\\space n, \\space \\bm{p})=\\frac{n !}{x_{1} ! \\cdots x_{k} !} p_{1}^{x_{1}} \\cdots p_{k}^{x_{k}}\\\\\\bm{x}=(x_1, x_2, …, x_k), x_i \\in \\{0, …, n\\}, \\space \\sum_{i}{x_i}=n; \\\\\\bm{p}=(p_1, p_2, …, p_k), 0\\leqslant p_i \\leqslant 1, \\space \\sum_{i}{p_i}=1\\]

当\\(k=2\\)时,则取到下列极限情况,是为参数为\\(n\\), \\(p\\)的二项分布:

\\[P(X = x;\\space n, \\space p)=\\frac{n !}{x !(n-x) !} p^{x}(1-p)^{n-x}\\\\x=0,1,2,…n; \\space 0\\leqslant p \\leqslant 1\\]

也就是说,多项分布式二项分布的推广:仍然是独立重复实验\\(n\\)次,但每次不只有成功和失败两种结果,而是\\(k\\)种可能的结果,每种结果的概率为\\(p_i\\)。多项分布是一个随机向量的分布,\\(\\bm{x}=(x_1, x_2, …, x_k)\\)意为第\\(i\\)种结果出现\\(x_i\\)次,\\(P(\\bm{X} = \\bm{x};\\space n, \\space p)\\)也就表示第\\(i\\)种结果出现\\(x_i\\)次的概率。

2.2 函数原型

random.multinomial(n, pvals, size=None)

参数:

n

: int   对应分布函数中的参数

n

pvals

: sequence of floats   对应分布函数参数\\(\\bm{p}\\), 其长度等于可能的结果数\\(k\\),并且有\\(0 \\leqslant p_i \\leqslant 1\\)。

size

: int or tuple of ints, optional   为输出形状大小,因为采出的每个样本是一个随机向量,默认最后一维会自动加上\\(k\\),如果给定形状为\\((m, n)\\),那么\\(m\\times n\\)个维度为\\(k\\)的随机向量会从中抽取。默认为None,即返回一个一个\\(k\\)维的随机向量。

返回:

out

: ndarray   从带参数的概率分布中采的随机向量,长度为可能的结果数\\(k\\),如果没有给定

size

,则shape为

(k,)

2.3 使用样例

设进行独立重复实验20次,每次情况的概率为1/6,采样出的随机向量表示每种情况出现次数(相当于扔20次六面骰子,点数为0, 1, 2, …, 5出现的次数)。总共采1个样本。

s = np.random.multinomial(20, [1/6.]*6, size=1)print(s) # [[4 2 2 3 5 4]]

当然,如果不指定size,它直接就会返回一个一维向量了

s = np.random.multinomial(20, [1/6.]*6)print(s) # [4 1 4 3 5 3]

如果像进行多次采样,改变

size

即可:

s = np.random.multinomial(20, [1/6.]*6, size=(2, 2))print(s)# [[[4 3 4 2 6 1]#   [5 2 1 6 3 3]]#  [[5 4 1 1 6 3]#   [2 5 2 5 4 2]]]

这个函数在论文

<sup>

[1]

</sup>

的实现代码

<sup>

[2]

</sup>

中用来设置每一个

client

分得的样本数:

for cluster_id in range(n_clusters):weights = np.random.dirichlet(alpha=alpha * np.ones(n_clients))clients_counts[cluster_id] = np.random.multinomial(clusters_sizes[cluster_id], weights)# 一共扔clusters_sizes[cluster_id]次筛子,该函数返回骰子落在某个client上各多少次,也就对应着该client应该分得的样本数

3.均匀(uniform)分布

103c

3.1 概率密度函数(pdf)

\\[p(x; \\space a, \\space b)=\\frac{1}{b-a}\\]

均匀分布可用于随机地从连续区间\\([a, b)\\)内进行采样。

3.2 函数原型

random.uniform(low=0.0, high=1.0, size=None)

参数:

low

: float or array_like of floats, optional   对应分布函数中的下界参数

a

,默认为0。

high

: float or array_like of floats   对应分布函数中的下界参数

b

,默认为1.0。

size

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

返回:

out

: ndarray or scalar   从带参数的均匀分布中采的随机样本

3.3 使用样例

s = np.random.uniform(-1,0,10)print(s)# [-0.9479594  -0.86158902 -0.63754099 -0.0883407  -0.92845644 -0.11148294#  -0.19826197 -0.77396765 -0.26809953 -0.74734785]

4. 狄利克雷(Dirichlet)分布

4.1 概率密度函数(pdf)

\\[P(\\bm{x}; \\bm{\\alpha}) \\propto \\prod_{i=1}^{k} x_{i}^{\\alpha_{i}-1} \\\\\\bm{x}=(x_1,x_2,…,x_k),\\quad x_i > 0 , \\quad \\sum_{i=1}^k x_i = 1\\\\\\bm{\\alpha} = (\\alpha_1,\\alpha_2,…, \\alpha_k). \\quad \\alpha_i > 0\\]

4.2 函数原型

random.dirichlet(alpha, size=None)

参数:

alpha

: sequence of floats, length k   对应分布函数中的参数向量 \\(\\alpha\\),长度为\\(k\\)。

size

: int or tuple of ints, optional   为输出形状大小,因为采出的每个样本是一个随机向量,默认最后一维会自动加上\\(k\\),如果给定形状为\\((m, n)\\),那么\\(m\\times n\\)个维度为\\(k\\)的随机向量会从中抽取。默认为None,即返回一个一个\\(k\\)维的随机向量。

返回:

out

: ndarray   采出的样本,大小为\\((size, k)\\)。

4.3 使用样例

设\\(\\bm{\\alpha}=(10, 5, 3)\\)(意味着\\(k=3\\)),\\(size=(2, 2)\\),则采出的样本为\\(2\\times 2\\)个维度为\\(k=3\\)的随机向量。

s = np.random.dirichlet((10, 5, 3), size=(2, 2))print(s)# [[[0.82327647 0.09820451 0.07851902]#   [0.50861077 0.4503409  0.04104833]]#  [[0.31843167 0.22436547 0.45720285]#   [0.40981943 0.40349597 0.1866846 ]]]

这个函数在论文[1]的实现代码[2]中用来生成符合狄利克雷分布的权重向量

for cluster_id in range(n_clusters):# 为每个client生成一个权重向量,文章中分布参数alpha每一维都相同weights = np.random.dirichlet(alpha=alpha * np.ones(n_clients))clients_counts[cluster_id] = np.random.multinomial(clusters_sizes[cluster_id], weights)

参考文献

  • [1] Marfoq O, Neglia G, Bellet A, et al. Federated multi-task learning under a mixture of distributions[J]. Advances in Neural Information Processing Systems, 2021, 34.
  • [2] https://github.com/omar191afoq/FedEM
  • [3] https://www.python.org/
  • [4] https://numpy.org/
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Python中的随机采样和概率分布(二)