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 自动提交和抓取网页
Jul 13 Python
python实现ftp客户端示例分享
Feb 17 Python
Python入门篇之文件
Oct 20 Python
python检测是文件还是目录的方法
Jul 03 Python
Python实现PS滤镜碎片特效功能示例
Jan 24 Python
关于Numpy中的行向量和列向量详解
Nov 30 Python
详解Django配置JWT认证方式
May 09 Python
Python接口测试文件上传实例解析
May 22 Python
python怎么删除缓存文件
Jul 19 Python
如何通过python计算圆周率PI
Nov 11 Python
python中使用.py配置文件的方法详解
Nov 23 Python
python process模块的使用简介
May 14 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 数组遍历的差异(array_diff 的实现)
2008/03/23 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
url decode problem 解决方法
2011/12/26 PHP
深入理解require与require_once与include以及include_once的区别
2013/06/05 PHP
一个PHP实现的轻量级简单爬虫
2015/07/08 PHP
php基于双向循环队列实现历史记录的前进后退等功能
2015/08/08 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
ExtJS 2.0实用简明教程 之获得ExtJS
2009/04/29 Javascript
Javascript 设计模式(二) 闭包
2010/05/26 Javascript
跨域传值即主页面与iframe之间互相传值
2013/12/09 Javascript
JavaScript字符串对象toUpperCase方法入门实例(用于把字母转换为大写)
2014/10/17 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
2016/05/15 Javascript
Bootstrap Metronic完全响应式管理模板学习笔记
2016/07/08 Javascript
微信小程序开发之toast等弹框提示使用教程
2017/06/08 Javascript
浅谈React 服务器端渲染的使用
2018/05/08 Javascript
Angular6新特性之Angular Material
2018/12/28 Javascript
vue 实现移动端键盘搜索事件监听
2019/11/06 Javascript
Python3 能振兴 Python的原因分析
2014/11/28 Python
在Python中使用判断语句和循环的教程
2015/04/25 Python
python批量制作雷达图的实现方法
2016/07/26 Python
Python矩阵常见运算操作实例总结
2017/09/29 Python
Jupyter安装nbextensions,启动提示没有nbextensions库
2020/04/23 Python
PyQt5 pyqt多线程操作入门
2018/05/05 Python
python如何实现一个刷网页小程序
2018/11/27 Python
Python3内置模块random随机方法小结
2019/07/13 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
Python如何使用paramiko模块连接linux
2020/03/18 Python
python Socket网络编程实现C/S模式和P2P
2020/06/22 Python
社区版pycharm创建django项目的方法(pycharm的newproject左侧没有项目选项)
2020/09/23 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
2020/12/07 Python
介绍一下代理模式(Proxy)
2014/10/17 面试题
如果一个类实现了多个接口但是这些接口有相同的方法名将会怎样
2013/06/16 面试题
就业推荐表自我鉴定
2014/03/21 职场文书
简单租房协议书范本
2014/08/20 职场文书
2014年组织部工作总结
2014/11/14 职场文书