正态分布随机数生成算法

最近在学习基于蒙特卡罗的强化学习方法时遇到 生成服从正态分布的随机数的算法,因此做一个回顾和总结。

要编程得到服从均匀分布的伪随机数是容易的,C、Python、Java语言等都提供了相应的函数。

但是要想生成服从正态分布的随机数就没那么容易了,生成服从正态分布的随机数的基本思想是先得到服从均匀分布的随机数,再将服从均匀分布的随机数转变为服从正态分布。

实现均匀分布到正态分布转变的方法:

  • 利用分布函数的反函数

使用反函数,先随机抽出一个服从[0,1]均匀分布的数字u,然后

那z是正态分布的

import numpy as np  
from scipy.special import erfinv 
def inverfsampling(mu=0, sigma=1, size=1):  
    z = np.sqrt(2) * erfinv(2 * np.random.uniform(size=size) - 1)  
    return mu + z * sigma

  • Box Muller方法
Box Muller方法的推导过程较为复杂。但得到的结果却是很令人满意的。只要用两个相互独立的均匀分布就能得到正态分布用Box-Muller方法,随机抽出两个从均[0,1]匀分布的数字u和v。然后




均服从正态分布。


import numpy as np  

def boxmullersampling(mu=0, sigma=1, size=1):  
    u = np.random.uniform(size=size)  
    v = np.random.uniform(size=size)  
    z = np.sqrt(-2 * np.log(u)) * np.cos(2 * np.pi * v)  
    return mu + z * sigma  
  

  • 利用中心极限定理
利用林德伯格-莱维(Lindeberg—Levi)中心极限定理, 独立同分布的事件,具有相同的期望和方差,则事件服从中心极限定理。他表示了对于抽取样本,n足够大的时候,样本分布符合x~N(μ,σ^2)。
中心极限定理告诉我们,当样本量足够大时,样本均值的分布慢慢变成正态分布。
import numpy as np
import matplotlib.pylab as plb
from scipy import stats
import math

number=[30,100,300,1000,5000,30000]
y=[]
for i in range(len(number)):
    ave_uniform=[]
    for j in range(1000):
        data=np.random.uniform(-1,1,number[i])
        variance=(1.0/3.0)/(1.0*number[i])
        summer=sum(data)
        ave_uniform.append(summer/(1.0*number[i]))
        Range=np.arange(-0.5,0.5,0.001)
    plb.subplot(230+i+1)
    plb.plot(Range,stats.norm.pdf(Range,0,math.sqrt(variance)))
    plb.hist(ave_uniform,bins=100)
plb.show()
关于正态分布的理论证明,可参考课程:http://open.163.com/movie/2011/6/G/I/M82IC6GQU_M83JBFVGI.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值