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 相关文章推荐
使用Python编写简单的端口扫描器的实例分享
Dec 18 Python
Python中扩展包的安装方法详解
Jun 14 Python
Django实现简单分页功能的方法详解
Dec 05 Python
python处理数据,存进hive表的方法
Jul 04 Python
Python 爬虫之Beautiful Soup模块使用指南
Jul 05 Python
Python自定义一个类实现字典dict功能的方法
Jan 19 Python
浅析Python 实现一个自动化翻译和替换的工具
Apr 14 Python
Python 一键制作微信好友图片墙的方法
May 16 Python
python多线程共享变量的使用和效率方法
Jul 16 Python
Python之——生成动态路由轨迹图的实例
Nov 22 Python
TensorFlow实现打印每一层的输出
Jan 21 Python
使用sklearn的cross_val_score进行交叉验证实例
Feb 28 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
PHP中一些可以替代正则表达式函数的字符串操作函数
2014/11/17 PHP
Symfony2学习笔记之插件格式分析
2016/03/17 PHP
Laravel框架模型的创建及模型对数据操作示例
2019/05/07 PHP
经验几则 推荐
2006/09/05 Javascript
JavaScript设置FieldSet展开与收缩
2009/05/15 Javascript
js 实现css风格选择器(压缩后2KB)
2012/01/12 Javascript
jQuery中children()方法用法实例
2015/01/07 Javascript
javascript实现简单的鼠标拖动效果实例
2015/04/10 Javascript
解决js页面滚动效果scrollTop在FireFox与Chrome浏览器间的兼容问题的方法
2015/12/03 Javascript
Mvc提交表单的四种方法全程详解
2016/08/10 Javascript
js style.display=block显示布局错乱问题的解决方法
2016/09/21 Javascript
javascript动态创建对象的属性详解
2018/11/07 Javascript
vue+element表格导出为Excel文件
2019/09/26 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
2020/05/13 Javascript
[02:37]2015国际邀请赛选手档案—LGD.Xiao8
2015/07/28 DOTA
python通过socket实现多个连接并实现ssh功能详解
2017/11/08 Python
浅析Python函数式编程
2018/10/06 Python
Python编译为二进制so可执行文件实例
2019/12/23 Python
希腊品牌鞋类销售网站:epapoutsia.gr
2020/03/18 全球购物
校园之声广播稿
2014/01/31 职场文书
中班中秋节活动反思
2014/02/18 职场文书
经理秘书求职自荐信范文
2014/03/23 职场文书
服装设计专业毕业生求职信
2014/04/09 职场文书
校园文化标语
2014/06/18 职场文书
校车安全责任书
2014/08/25 职场文书
秋冬农业生产标语
2014/10/09 职场文书
上课睡觉检讨书300字
2014/11/18 职场文书
人事文员岗位职责
2015/02/04 职场文书
服装区域经理岗位职责
2015/04/10 职场文书
亮剑观后感300字
2015/06/05 职场文书
餐厅营销的秘密:为什么老顾客会流水?
2019/08/08 职场文书
python实现三阶魔方还原的示例代码
2021/04/28 Python
简单了解 MySQL 中相关的锁
2021/05/25 MySQL
SQL实现LeetCode(176.第二高薪水)
2021/08/04 MySQL
Consul在linux环境的集群部署
2022/04/08 Servers
解决Oracle数据库用户密码过期
2022/05/11 Oracle