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对Access读写操作
Mar 30 Python
python-opencv在有噪音的情况下提取图像的轮廓实例
Aug 30 Python
Python实现二维数组按照某行或列排序的方法【numpy lexsort】
Sep 22 Python
python去除扩展名的实例讲解
Apr 23 Python
使用tensorflow实现线性svm
Sep 07 Python
django框架模型层功能、组成与用法分析
Jul 30 Python
Python脚本操作Excel实现批量替换功能
Nov 20 Python
解决pyshp UnicodeDecodeError的问题
Dec 06 Python
python 比较2张图片的相似度的方法示例
Dec 18 Python
Tensorflow 使用pb文件保存(恢复)模型计算图和参数实例详解
Feb 11 Python
Pandas的Apply函数具体使用
Jul 21 Python
在python中对于bool布尔值的取反操作
Dec 11 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
thinkphp ajaxfileupload实现异步上传图片的示例
2017/08/28 PHP
PHP+JS实现的实时搜索提示功能
2018/03/13 PHP
php5.6.x到php7.0.x特性小结
2019/08/17 PHP
Gambit vs ForZe BO3 第二场 2.13
2021/03/10 DOTA
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
js日期时间补零的小例子
2013/03/05 Javascript
jquery实现tr元素的上下移动示例代码
2013/12/20 Javascript
简单选项卡 js和jquery制作方法分享
2014/02/26 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
全屏js头像上传插件源码高清版
2016/03/29 Javascript
Bootstrap轮播插件简单使用方法介绍
2016/06/21 Javascript
举例讲解jQuery对DOM元素的向上遍历、向下遍历和水平遍历
2016/07/07 Javascript
详解Angular中$cacheFactory缓存的使用
2016/08/19 Javascript
JS正则表达式验证中文字符
2017/05/08 Javascript
jQuery 利用ztree实现树形表格的实例代码
2017/09/27 jQuery
vue实现树形菜单效果
2018/03/19 Javascript
Vue ElementUi同时校验多个表单(巧用new promise)
2018/06/06 Javascript
3分钟了解vue数据劫持的原理实现
2019/05/01 Javascript
Vuex 模块化使用详解
2019/07/31 Javascript
Javascript数组及类数组相关原理详解
2020/10/29 Javascript
[07:38]2014DOTA2国际邀请赛 Newbee顺利挺进胜者组赛后专访
2014/07/15 DOTA
python使用arp欺骗伪造网关的方法
2015/04/24 Python
Django查询数据库的性能优化示例代码
2017/09/24 Python
分分钟入门python语言
2018/03/20 Python
python3下实现搜狗AI API的代码示例
2018/04/10 Python
python读写csv文件实例代码
2019/07/05 Python
Python 统计位数为偶数的数字代码详解
2020/03/15 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
css3 border-radius属性详解
2017/07/05 HTML / CSS
美国儿童珠宝在线零售商:Loveivy
2019/05/22 全球购物
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
2014/07/27 面试题
职称评定自我鉴定
2014/03/18 职场文书
2014年党员自我评价材料
2014/09/22 职场文书
世界红十字日活动总结
2015/02/10 职场文书
python自动化测试通过日志3分钟定位bug
2021/11/20 Python
Python 文字识别
2022/05/11 Python