如何得到服从正态分布的样本
之前介绍了计算机如何产生随机数,同时也整理了常用的概率分布。现在我们来考虑这样的问题,如何得到服从正态分布的样本?,在计算机如何产生随机数中我们用线性同余发生器生成了随机数,这些随机数实际上就是服从的均匀分布,意味在范围内,每个样本被抽取概率是一样的。
对于正态分布的样本来说,每个样本被抽取的概率是不同的。根据正态分布的曲线我们知道,在平均值附近的点被抽取的概率是最大的,越往两边走,被抽取的样本的概率越低,于是形成了钟形曲线。
采样
采样的方式具有较强的通用性,一般用于比较复杂的概率分布。常用的采样方法有接受-拒绝采样,大名鼎鼎的马尔可夫蒙特卡洛采样(MCMC采样),其典型的代表是Metropolis-Hasting采样,Gibbs采样。这里我们先挖个坑留着,后续继续介绍。因为对于正态分布的采样虽然也能用这些采样的方法,但是效率不是最高的。用复杂的模型处理简单的问题,不太合理哈。
中心极限定理生成
中心极限定理描述的是多个独立的随机变量求和近似服从正态分布。之前我们得到了均匀分布,可以尝试独立地从均匀分布中采样多个变量,求和以后可以得到近似服从正态分布的样本。中心极限定理有多种描述方式,下面仅介绍其中一种。
独立同分布中心极限定理,,为独立同分布的随机变量序列,均值为方差均存在。
意味着近似服从标准正态分布,随机变量的个数越多,越近似服从正态分布。高尔顿板就是典型的中心极限定理的应用,每个小球独立的服从二项分布,小球每次碰到杆随机的选择一次方向,最终的结果近似服从正态分布。
接下来用程序来生成正态分布的样本
import numpy as np
from matplotlib import pyplot as plt
mu = 0.5 # 期望
s = 1 / 12 # 方差
sample_size = 10000 # 样本数
n = 1000 # 随机变量个数
total = np.sum(np.random.random((n, sample_size)), axis=0) # 随机变量求和
normal_dist = (total - n * mu) / np.sqrt(s * n) # 近似服从正态分布
plt.figure(0)
plt.hist(normal_dist, bins=np.linspace(-4, 4, 100), facecolor='green')
plt.show()
可以看到时其实就是均匀分布,随着逐渐增大,直方图轮廓越来越接近正态分布了。但是这样生成正态分布样本的效率是很低的,因为我们需要生成大量的随机变量,每个随机变量也要采样大量的样本,才能得到正态分布的样本。
逆变换法生成
我们已经有了均匀分布的样本,考虑建立映射把均匀分布的样本投影到正态分布。这样就实现了从正态分布采样了,这种方法称为Box–Muller变换,在实际中应用很多,例如Python的源码random
模块生成正态分布的随机数就是用的这个方法。
逆变换定理:设为连续型随机变量,取值于区间(可包括和端点), 的概率密度在上取正值, 的分布函数为则
假定服从均值为0,方差为1的高斯分布,且相互独立,它们的概率密度如下。
然后根据极坐标变换则概率密度变成:
然后分别得到的累积分布函数
根据逆变换定理
上面,带入到即可得到服从正态分布的样本
接下来验证一下生成样本的效果。
import numpy as np
from matplotlib import pyplot as plt
def get_normal_dist(sample_size):
u1 = np.random.uniform(size=sample_size)
u2 = np.random.uniform(size=sample_size)
return np.sqrt(-2 * np.log(u1)) * np.cos(2 * np.pi * u2)
plt.hist(get_normal_dist(10000),
bins=np.linspace(-4, 4, 100),
facecolor='green')
plt.show()
总结
本文主要介绍生成正态分布样本的方法,通用的采样方法,利用中心极限定理生成,逆变换法生成,其中重点介绍了后两种方法,并且给出了程序模拟。我做公众号的目的也是为了介绍数学编程,其实编程很大程度上就是数学的应用,把书本上的公式用在实际中,是不是能感受到数学与编程的魅力。
参考
https://cosx.org/2015/06/generating-normal-distr-variates