Python编程产生非均匀随机数的几种方法代码分享


Posted in Python onDecember 13, 2017

1.反变换法

设需产生分布函数为F(x)的连续随机数X。若已有[0,1]区间均匀分布随机数R,则产生X的反变换公式为:

F(x)=r, 即x=F-1(r)

反函数存在条件:如果函数y=f(x)是定义域D上的单调函数,那么f(x)一定有反函数存在,且反函数一定是单调的。分布函数F(x)为是一个单调递增函数,所以其反函数存在。从直观意义上理解,因为r一一对应着x,而在[0,1]均匀分布随机数R≤r的概率P(R≤r)=r。 因此,连续随机数X≤x的概率P(X≤x)=P(R≤r)=r=F(x)

即X的分布函数为F(x)。

例子:下面的代码使用反变换法在区间[0, 6]上生成随机数,其概率密度近似为P(x)=e-x

import numpy as np
import matplotlib.pyplot as plt
# probability distribution we're trying to calculate
p = lambda x: np.exp(-x)
# CDF of p
CDF = lambda x: 1-np.exp(-x)
# invert the CDF
invCDF = lambda x: -np.log(1-x)
# domain limits
xmin = 0 # the lower limit of our domain
xmax = 6 # the upper limit of our domain
# range limits
rmin = CDF(xmin)
rmax = CDF(xmax)
N = 10000 # the total of samples we wish to generate
# generate uniform samples in our range then invert the CDF
# to get samples of our target distribution
R = np.random.uniform(rmin, rmax, N)
X = invCDF(R)
# get the histogram info
hinfo = np.histogram(X,100)
# plot the histogram
plt.hist(X,bins=100, label=u'Samples');
# plot our (normalized) function
xvals=np.linspace(xmin, xmax, 1000)
plt.plot(xvals, hinfo[0][0]*p(xvals), 'r', label=u'p(x)')
# turn on the legend
plt.legend()
plt.show()

Python编程产生非均匀随机数的几种方法代码分享

一般来说,直方图的外廓曲线接近于总体X的概率密度曲线。

2.舍选抽样法(Rejection Methold)

用反变换法生成随机数时,如果求不出F-1(x)的解析形式或者F(x)就没有解析形式,则可以用F-1(x)的近似公式代替。但是由于反函数计算量较大,有时也是很不适宜的。另一种方法是由Von Neumann提出的舍选抽样法。下图中曲线w(x)为概率密度函数,按该密度函数产生随机数的方法如下:

Python编程产生非均匀随机数的几种方法代码分享

基本的rejection methold步骤如下:

1. Draw x uniformly from [xmin xmax]

2. Draw x uniformly from [0, ymax]

3. if y < w(x),accept the sample, otherwise reject it

4. repeat

即落在曲线w(x)和X轴所围成区域内的点接受,落在该区域外的点舍弃。

例子:下面的代码使用basic rejection sampling methold在区间[0, 10]上生成随机数,其概率密度近似为P(x)=e-x

# -*- coding: utf-8 -*-
'''
The following code produces samples that follow the distribution P(x)=e^−x 
for x=[0, 10] and generates a histogram of the sampled distribution.
'''
import numpy as np
import matplotlib.pyplot as plt
P = lambda x: np.exp(-x)
# domain limits
xmin = 0 # the lower limit of our domain
xmax = 10 # the upper limit of our domain
# range limit (supremum) for y
ymax = 1
N = 10000  # the total of samples we wish to generate
accepted = 0 # the number of accepted samples
samples = np.zeros(N)
count = 0  # the total count of proposals
# generation loop
while (accepted < N):
    # pick a uniform number on [xmin, xmax) (e.g. 0...10)
  x = np.random.uniform(xmin, xmax)
    # pick a uniform number on [0, ymax)
  y = np.random.uniform(0,ymax)
    # Do the accept/reject comparison
  if y < P(x):
    samples[accepted] = x
    accepted += 1
    count +=1
  print count, accepted
# get the histogram info
# If bins is an int, it defines the number of equal-width bins in the given range 
(n, bins)= np.histogram(samples, bins=30) # Returns: n-The values of the histogram,n是直方图中柱子的高度
# plot the histogram
plt.hist(samples,bins=30,label=u'Samples')  # bins=30即直方图中有30根柱子
# plot our (normalized) function
xvals=np.linspace(xmin, xmax, 1000)
plt.plot(xvals, n[0]*P(xvals), 'r', label=u'P(x)')
# turn on the legend
plt.legend()
plt.show()

>>>

99552 10000

Python编程产生非均匀随机数的几种方法代码分享

3.推广的舍取抽样法

从上图中可以看出,基本的rejection methold法抽样效率很低,因为随机数x和y是在区间[xmin xmax]和区间[0 ymax]上均匀分布的,产生的大部分点不会落在w(x)曲线之下(曲线e-x的形状一边高一边低,其曲线下的面积占矩形面积的比例很小,则舍选抽样效率很低)。为了改进简单舍选抽样法的效率,可以构造一个新的密度函数q(x)(called a proposal distribution from which we can readily draw samples),使它的形状接近p(x),并选择一个常数k使得kq(x)≥w(x)对于x定义域内的值都成立。对应下图,首先从分布q(z)中生成随机数z0,然后按均匀分布从区间[0 kq(z0)]生成一个随机数u0。 if u0 > p(z0) then the sample is rejected,otherwise u0 is retained. 即下图中灰色区域内的点都要舍弃。可见,由于随机点u0只出现在曲线kq(x)之下,且在q(x)较大处出现次数较多,从而大大提高了采样效率。显然q(x)形状越接近p(x),则采样效率越高。

Python编程产生非均匀随机数的几种方法代码分享

根据上述思想,也可以表达采样规则如下:

1. Draw x from your proposal distribution q(x)

2. Draw y uniformly from [0 1]

3. if y < p(x)/kq(x) , accept the sample, otherwise reject it

4. repeat

下面例子中选择函数p(x)=1/(x+1)作为proposal distribution,k=1。曲线1/(x+1)的形状与e-x相近。

import numpy as np
import matplotlib.pyplot as plt
p = lambda x: np.exp(-x)     # our distribution
g = lambda x: 1/(x+1)      # our proposal pdf (we're choosing k to be 1)
CDFg = lambda x: np.log(x +1)  # generates our proposal using inverse sampling
# domain limits
xmin = 0 # the lower limit of our domain
xmax = 10 # the upper limit of our domain
# range limits for inverse sampling
umin = CDFg(xmin)
umax = CDFg(xmax)
N = 10000 # the total of samples we wish to generate
accepted = 0 # the number of accepted samples
samples = np.zeros(N)
count = 0 # the total count of proposals
# generation loop
while (accepted < N):
    # Sample from g using inverse sampling
  u = np.random.uniform(umin, umax)
  xproposal = np.exp(u) - 1
  # pick a uniform number on [0, 1)
  y = np.random.uniform(0, 1)
  # Do the accept/reject comparison
  if y < p(xproposal)/g(xproposal):
    samples[accepted] = xproposal
    accepted += 1
    count +=1
  print count, accepted
# get the histogram info
hinfo = np.histogram(samples,50)
# plot the histogram
plt.hist(samples,bins=50, label=u'Samples');
# plot our (normalized) function
xvals=np.linspace(xmin, xmax, 1000)
plt.plot(xvals, hinfo[0][0]*p(xvals), 'r', label=u'p(x)')
# turn on the legend
plt.legend()
plt.show()

 >>>

24051 10000

Python编程产生非均匀随机数的几种方法代码分享

可以对比基本的舍取法和改进的舍取法的结果,前者产生符合要求分布的10000个随机数运算了99552步,后者运算了24051步,可以看到效率明显提高。

总结

以上就是本文关于Python编程产生非均匀随机数的几种方法代码分享的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
通过Py2exe将自己的python程序打包成.exe/.app的方法
May 26 Python
对pandas的层次索引与取值的新方法详解
Nov 06 Python
详解如何用django实现redirect的几种方法总结
Nov 22 Python
Python XlsxWriter模块Chart类用法实例分析
Mar 11 Python
Python 实现一个手机号码获取妹子名字的功能
Sep 25 Python
python装饰器代替set get方法实例
Dec 19 Python
tensorflow实现二维平面模拟三维数据教程
Feb 11 Python
什么是Python中的顺序表
Jun 02 Python
Python基于xlrd模块处理合并单元格
Jul 28 Python
用python实现一个简单的验证码
Dec 09 Python
使用python tkinter开发一个爬取B站直播弹幕工具的实现代码
Feb 07 Python
Python中的协程(Coroutine)操作模块(greenlet、gevent)
May 30 Python
windows下Virtualenvwrapper安装教程
Dec 13 #Python
python实现机械分词之逆向最大匹配算法代码示例
Dec 13 #Python
Python语言描述KNN算法与Kd树
Dec 13 #Python
Python xlwt设置excel单元格字体及格式
Apr 18 #Python
Python语言实现百度语音识别API的使用实例
Dec 13 #Python
Python通过matplotlib绘制动画简单实例
Dec 13 #Python
Python数据结构与算法之字典树实现方法示例
Dec 13 #Python
You might like
给初学者的30条PHP最佳实践(荒野无灯)
2011/08/02 PHP
基于PHP实现微信小程序客服消息功能
2019/08/12 PHP
YII2框架中添加自定义模块的方法实例分析
2020/03/18 PHP
IE和Firefox下javascript的兼容写法小结
2008/12/10 Javascript
jquery mobile changepage的三种传参方法介绍
2013/09/13 Javascript
js 遍历json返回的map内容示例代码
2013/10/29 Javascript
node.js中使用node-schedule实现定时任务实例
2014/06/03 Javascript
采用自执行的匿名函数解决for循环使用闭包的问题
2014/09/11 Javascript
JavaScript中的splice()方法使用详解
2015/06/09 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
微信小程序 loading(加载中提示框)实例
2016/10/28 Javascript
微信小程序-获得用户输入内容
2017/02/13 Javascript
Input文本框随着输入内容多少自动延伸的实现
2017/02/15 Javascript
详解.vue文件中监听input输入事件(oninput)
2017/09/19 Javascript
Vue 创建组件的两种方法小结(必看)
2018/02/23 Javascript
vue中v-for加载本地静态图片方法
2018/03/03 Javascript
Vue.js 动态为img的src赋值方法
2018/03/14 Javascript
js中console在一行内打印字符串和对象的方法
2019/09/10 Javascript
Vue 开发必须知道的36个技巧(小结)
2019/10/09 Javascript
浅析VUE防抖与节流
2020/11/24 Vue.js
[01:37]全新的一集《真视界》——TI7总决赛
2017/09/21 DOTA
python3.5 email实现发送邮件功能
2018/05/22 Python
在PyCharm中实现关闭一个死循环程序的方法
2018/11/29 Python
Python 带有参数的装饰器实例代码详解
2018/12/06 Python
Python3实现二叉树的最大深度
2019/09/30 Python
Python使用sqlite3模块内置数据库
2020/05/07 Python
Python 如何展开嵌套的序列
2020/08/01 Python
GANT葡萄牙官方商店:拥有美国运动服传统的生活方式品牌
2018/10/18 全球购物
澳大利亚婴儿礼品公司:The Baby Gift Company
2018/11/04 全球购物
Dyson戴森波兰官网:Dyson.pl
2019/08/05 全球购物
linux面试题参考答案(11)
2012/05/01 面试题
网络编辑求职信
2014/04/30 职场文书
公证委托书格式
2014/09/13 职场文书
企业办公室主任岗位职责
2015/04/01 职场文书
2016年教师学习廉政准则心得体会
2016/01/20 职场文书
在CSS中使用when/else的方法
2022/01/18 HTML / CSS