离散ziggurat算法python实现_漫谈正态分布的生成
本文作者简介:王夜笙,就读于郑州大学信息工程学院,感兴趣的方向为逆向工程和机器学习,长期从事数据抓取工作(长期与反爬虫技术作斗争~),涉猎较广(技艺不精……),详情请见我的个人博客~
感谢怡轩同学的悉心指导~
之前拜读了靳志辉(@rickjin)老师写的《正态分布的前世今生》,一直对正态分布怀着一颗敬畏之心,刚好最近偶然看到python标准库中如何生成服从正态分布随机数的源码,觉得非常有趣,于是又去查找其他一些生成正态分布的方法,与大家分享一下。
利用中心极限定理生成正态分布
设X1,X2,⋯,Xn为独立同分布的随机变量序列,均值为μ,方差为σ2,则
Zn=X1+X2+⋯+Xn−nμσn√
具有渐近分布N(0,1),也就是说当n→∞时,
P{X1+X2+⋯+Xn−nμσn√≤x}→12π−−√∫x−∞e−t22dt
换句话说,n个相互独立同分布的随机变量之和的分布近似于正态分布,n越大,近似程度越好。当然也有例外,比如n个独立同分布的服从柯西分布随机变量的算术平均数仍是柯西分布,这里就不扩展讲了。
根据中心极限定理,生成正态分布就非常简单粗暴了,直接生成n个独立同分布的均匀分布即可,看代码
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
def getNormal(SampleSize,n):
result = []
for i in range(SampleSize):
# 利用中心极限定理,[0,1)均匀分布期望为0.5,方差为1/12
iid = (np.mean(np.random.uniform(0,1,n))-0.5)*np.sqrt(12*n)
result.append(iid)
return result
# 生成10000个数,观察它们的分布情况
SampleSize = 10000
# 观察n选不同值时,对最终结果的影响
N = [1,2,10,1000]
plt.figure(figsize=(10,20))
subi = 220
for index,n in enumerate(N):
subi += 1
plt.subplot(subi)
normal = getNormal(SampleSize, n)
# 绘制直方图
plt.hist(normal,np.linspace(-4,4,81),facecolor="green",label="n={0}".format(n))
plt.ylim([0,450])
plt.legend()
plt.show()
得到结果如下图所示
可以看到,n=1时其实就是均匀分布,随着n逐渐增大,直方图轮廓越来越接近正态分布了~因此利用中心极限定理暴力生成服从正态分布的随机数是可行的。但是这样生成正态分布速度是非常慢的,因为要生成若干个同分布随机变量,然后求和、计算,效率是非常低的。
利用逆变换法生成正态分布
假设u=F(x)是一个概率分布函数(CDF),F−1是它的反函数,若U是一个服从(0,1)均匀分布的随机变量,则F−1(U)服从函数F给出的分布。例如要生成一个服从指数分布的随机变量,我们知道指数分布的概率分布函数(CDF)为F(x)=1–e–λx,其反函数为F−1(x)=−ln(1−x)λ,所以只要不断生成服从(0,1)均匀分布的随机变量,代入到反函数中即可生成指数分布。
正态分布的概率分布函数(CDF)如下图所示,
在y轴上产生服从(0,1)均匀分布的随机数,水平向右投影到曲线上,然后垂直向下投影到x轴,这样在x轴上就得到了正态分布。
当然正态分布的概率分布函数不方便直接用数学形式写出,求反函数也无从说起,不过好在scipy中有相应的函数,我们直接使用即可。
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
def getNormal(SampleSize):
iid = np.random.uniform(0,1,SampleSize)
result = norm.ppf(iid)
return result
SampleSize = 10000000
normal = getNormal(SampleSize)
plt.hist(normal,np.linspace(-4,4,81),facecolor="green")
plt.show()
结果如下图所示,
以上两个方法虽然方便也容易理解,但是效率实在太低,并不实用,那么在实际中到底是如何生成正态分布的呢?
Box–Muller算法
说来也巧,某天闲的无聊突然很好奇python是如何生成服从正态分布的随机数的,于是就看了看random.py的代码,具体实现的代码就不贴了,大家自己去看,注释中有下面几行
# When x and y are two variables from [0, 1), uniformly
# distributed, then
#
# cos(2*pi*x)*sqrt(-2*log(1-y))
# sin(2*pi*x)*sqrt(-2*log(1-y))
#
# are two *independent* variables with normal distribution
顿时感觉非常神奇,也就是说当x和y是两个独立且服从(0,1)均匀分布的随机变量时,cos(2πx)⋅–2ln(1–y)−−−−−−−−−√和sin(2πx)⋅–2ln(1–y)−−−−−−−−−√是两个独立且服从正态分布的随机变量!
后来查了查这个公式,发现这个方法叫做Box–Muller,其实本质上也是应用了逆变换法,证明方法比较多,这里我们选取一种比较好理解的
我们把逆变换法推广到二维的情况,设U1,U2为(0,1)上的均匀分布随机变量,(U1,U2)的联合概率密度函数为f(u1,u2)=1(0≤u1,u2≤1),若有:
{U1=g1(X,Y)U2=g2(X,Y)
其中,g1,g2的逆变换存在,记为
{x=h1(u1,u2)y=h2(u1,u2)
且存在一阶偏导数,设J为Jacobian矩阵的行列式
|J|=∣∣∣∣∂x∂u1∂y∂u1∂x∂u2∂y∂u2∣∣∣∣≠0
则随机变量(X,Y)的二维联合密度为(回顾直角坐标和极坐标变换):
f[h1(u1,u2),h2(u1,u2)]⋅|J|=|J|
根据这个定理我们来证明一下,
{Y1=−2lnX1−−−−−−−√cos(2πX2)Y2=−2lnX1−−−−−−−√sin(2πX2)
求反函数得
⎧⎩⎨X1=e–Y21+Y222X2=12πarctanY2Y1
计算Jacobian行列式
|J|=∣∣∣∣∂X1∂Y1∂X2∂Y1∂X1∂Y2∂X2∂Y2∣∣∣∣=∣∣∣∣−Y1⋅e−12(Y21+Y22)−Y22π(Y21+Y22)−Y2⋅e−12(Y21+Y22)Y12π(Y21+Y22)∣∣∣∣=e−12(Y21+Y22)[−Y212π(Y21+Y22)−Y222π(Y21+Y22)]=−
离散ziggurat算法python实现_漫谈正态分布的生成相关推荐
- 离散ziggurat算法python实现_花式生成正态分布
◆◆ ◆ 前言 "So much of life, it seems to me, is determined by pure randomness." – Sidney Poit ...
- 离散ziggurat算法python实现_一种基于LWE采样算法的实现与优化
一种基于 LWE 采样算法的实现与优化 王柯翔,黎 琳,彭双和 [摘 要] 基于带错误学习问题 (Learning With Errors , LWE) 构造的密码体制 能够抵御量子攻击,它的应用效率 ...
- 数据结构python版 答案,中国大学 MOOC_数据结构与算法Python版_章节测验答案
中国大学 MOOC_数据结构与算法Python版_章节测验答案 更多相关问题 认识的本质是()A.肯定世界是可知的B.主体对客体的能动反映C.主体对客体的直观反映D.实践是 水灰比是影响混凝土()的主 ...
- mooc数据结构与算法python版期末测验_中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案...
中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案 更多相关问题 采用fopen()函数打开文件,支持文件读取的参数有: [简答题]简单阐述高分子材料热-机械特征及成型加工的关系,并 ...
- 多元线性回归算法python实现_手写算法-Python代码推广多元线性回归
1.梯度下降-矩阵形式 上篇文章介绍了一元线性回归,包括Python实现和sklearn实现的实例.对比,以及一些问题点,详情可以看这里: 链接: 手写算法-Python代码实现一元线性回归 里面封装 ...
- 数据结构与算法python描述_数据结构与算法——Python语言描述.pdf
数据结构与算法--Python语言描述.pdf 欢迎加入非盈利Python编学习交流程QQ群783462347,群里免费提供500+本Python书籍! 欢迎加入非盈利Python编程学习交流程QQ群 ...
- 排序算法python实现_用Python,Java和C / C ++实现的选择排序算法
排序算法python实现 The Selection Sort Algorithm sorts the elements of an array. In this article, we shall ...
- 排序算法python实现_合并排序算法– Java,C和Python实现
排序算法python实现 Merge sort is one of the most efficient sorting algorithms. It works on the principle o ...
- 社区发现算法python视频_社区发现FN算法Python实现
社区发现FN算法Python实现 算法原理 评价指标 结果对比 源码 2004年,Newman在GN(Girvan and Newman, 2002)算法的基础上,提出了另外一种快速检测社区的算法, ...
最新文章
- 三种方法实现Linux系统调用方法分享
- shell批量监控网站状态码
- Spring-AOP底层实现
- 【行为型模式】《大话设计模式》——读后感 (15)烤羊肉串引来的思考?——命令模式...
- 记下MD5验签可能出现的问题
- Failed to execute goal on project xxx: Could not resolve dependencies for project com
- iOS: How To Make AutoLayout Work On A ScrollView
- cdoj 1150 排名表 拓扑排序
- PWA(Progressive Web App)入门系列:(二)相关准备
- java学习(131):hashtable
- linux上c语言hdc句柄,控制台窗口的绘图
- 1021 个位数统计 (15 分)—PAT (Basic Level) Practice (中文)
- 正则表达式30分钟入门教程(转载)
- EmEditor中正则表达式
- windows下删除不掉文件夹:找不到该项目无法删除文件夹?
- IDEA安装插件(在线/离线)
- 瑞云Rayvision渲染的原创动画《吃饭睡觉打豆豆》震撼来袭 ——创造产业历史,日点击量过200万次...
- Python实战项目:俄罗斯方块(源码分享)(文章较短,直接上代码)
- 软件测试中的软件质量保证,软件质量保障全流程(上)
- 阿里云OSS对象存储搭建网盘教程