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求素数示例分享
Feb 16 Python
Python3基础之基本运算符概述
Aug 13 Python
python初学者,用python实现基本的学生管理系统(python3)代码实例
Apr 10 Python
python文件选择对话框的操作方法
Jun 27 Python
django获取from表单multiple-select的value和id的方法
Jul 19 Python
Django发送邮件和itsdangerous模块的配合使用解析
Aug 10 Python
Python3 搭建Qt5 环境的方法示例
Jul 16 Python
python接口自动化之ConfigParser配置文件的使用详解
Aug 03 Python
Python从文件中读取数据的方法步骤
Nov 18 Python
如何向scrapy中的spider传递参数的几种方法
Nov 18 Python
Python+Appium实现自动抢微信红包
May 21 Python
如何使用Python提取Chrome浏览器保存的密码
Jun 09 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 ajax 异步执行不等待执行结果的处理方法
2015/05/27 PHP
PHP随机数函数rand()与mt_rand()的讲解
2019/03/25 PHP
javascript 写类方式之三
2009/07/05 Javascript
最短的IE判断代码
2011/03/13 Javascript
jquery构造器的实现代码小结
2011/05/16 Javascript
For循环中分号隔开的3部分的执行顺序探讨
2014/05/27 Javascript
js获取元素相对窗口位置的实现代码
2014/09/28 Javascript
Javascript 构造函数详解
2014/10/22 Javascript
Javascript常用小技巧汇总
2015/06/24 Javascript
Js与Jq获取浏览器和对象值的方法
2016/03/18 Javascript
jQuery实现的简单悬浮层功能完整实例
2017/01/23 Javascript
bootstrap输入框组使用方法
2017/02/07 Javascript
jQuery中 bind的用法简单介绍
2017/02/13 Javascript
JS实现图片预加载之无序预加载功能代码
2017/05/12 Javascript
ionic环境配置及问题详解
2017/06/27 Javascript
JS通过调用微信API实现微信支付功能的方法示例
2017/06/29 Javascript
JavaScript之map reduce_动力节点Java学院整理
2017/06/29 Javascript
layui结合form,table的全选、反选v1.0示例讲解
2018/08/15 Javascript
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
JS内置对象和Math对象知识点详解
2020/04/03 Javascript
python3+requests接口自动化session操作方法
2018/10/13 Python
Python中浅拷贝copy与深拷贝deepcopy的简单理解
2018/10/26 Python
python实现杨氏矩阵查找
2019/03/02 Python
安装好Pycharm后如何配置Python解释器简易教程
2019/06/28 Python
python将音频进行变速的操作方法
2020/04/08 Python
如何使用PyCharm将代码上传到GitHub上(图文详解)
2020/04/27 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
耐克美国官网:Nike.com
2016/08/01 全球购物
eBay德国站:eBay.de
2017/09/14 全球购物
马耳他航空公司官方网站:Air Malta
2019/05/15 全球购物
CHARLES & KEITH台湾官网:新加坡时尚品牌
2019/07/30 全球购物
Invicta手表官方商店:百年制表历史的瑞士腕表品牌
2019/09/26 全球购物
团日活动总结书
2014/05/08 职场文书
企业文化宣传标语
2014/06/09 职场文书
班主任培训研修日志
2015/11/13 职场文书
SQL Server Agent 服务无法启动
2022/04/20 SQL Server