将均匀分布转换为正态分布
如何将一个均匀的分布(如大多数随机数发生器产生的,例如0.0和1.0之间)转换成正态分布? 如果我想要一个我select的平均和标准偏差怎么办?
Zigguratalgorithm对此非常高效,尽pipeBox-Muller变换从头开始更容易实现(而不是疯狂的慢)。
有很多方法:
- 不要使用Box Muller。 特别是如果你画许多高斯数字。 Box Muller得到了一个在-6和6之间的结果(假设双精度,浮点数加重)。 而且它的效率确实比其他可用的方法低。
- Ziggurat是好的,但需要一个表查找(由于caching大小问题和一些平台特定的调整)
- 制服比例是我最喜欢的,只有一些增加/乘法和1/50的时间(例如, 看那里 )。
- 反转CDF 是有效的(并忽略了,为什么?),如果你search谷歌,你可以快速实现它。 准随机数是强制性的。
改变任何函数的分布涉及到使用你想要的函数的反函数。
换句话说,如果你的目标是一个特定的概率函数p(x),你可以通过积分得到分布 – > d(x)=积分(p(x)),并使用它的逆:Inv(d(x)) 。 现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))来投射结果值。 你应该根据你select的函数得到随机分配的值。
这是通用的math方法 – 通过使用它,您现在可以select任何概率或分布函数,只要它具有逆或好的逆近似。
希望这有帮助,并感谢关于使用分布的小说,而不是概率本身。
这是一个使用Box-Muller转换的极坐标forms的javascript实现。
/* * Returns member of set with a given mean and standard deviation * mean: mean * standard deviation: std_dev */ function createMemberInNormalDistribution(mean,std_dev){ return mean + (gaussRandom()*std_dev); } /* * Returns random number in normal distribution centering on 0. * ~95% of numbers returned should fall between -2 and 2 * ie within two standard deviations */ function gaussRandom() { var u = 2*Math.random()-1; var v = 2*Math.random()-1; var r = u*u + v*v; /*if outside interval [0,1] start over*/ if(r == 0 || r >= 1) return gaussRandom(); var c = Math.sqrt(-2*Math.log(r)/r); return u*c; /* todo: optimize this algorithm by caching (v*c) * and returning next time gaussRandom() is called. * left out for simplicity */ }
使用中心极限定理维基百科入门 math世界条目给你的好处。
生成n个均匀分布的数字,将它们相加,减去n * 0.5,得到平均值为0且方差等于(1/12) * (1/sqrt(N))
的近似正态分布的输出(参见维基百科关于统一发行的最后一篇)
n = 10给你快一半体面的东西。 如果你想要超过一半体面的东西去tylers解决scheme( 正常分布的维基百科条目中所述)
其中R1,R2是随机统一的数字:
正态分布,SD为1:sqrt(-2 * log(R1))* cos(2 * pi * R2)
这是确切的…没有必要做所有这些慢循环!
我会用Box-Muller。 关于这个的两件事情:
- 最终每个迭代有两个值
通常,您caching一个值并返回另一个值。 在下一次调用样本时,您将返回caching的值。 - Box-Muller给出了一个Z分数
您必须按照标准偏差缩放Z值,并将平均值加上正态分布的全部值。
标准的Python库模块随机有你想要的:
normalvariate(mu,sigma)
正态分布。 mu是平均值,sigma是标准偏差。
对于algorithm本身,请查看Python库中的random.py函数。
手动input在这里
看起来不可思议的是,我可以在八年后添加一些东西,但是对于Java的情况,我想指出读者使用Random.nextGaussian()方法,该方法为您生成一个平均值为0.0,标准偏差为1.0的高斯分布。
一个简单的加法和/或乘法将改变你的需求的平均值和标准偏差。
我应该在EXCEL中试试这个: =norminv(rand();0;1)
。 这将产生应该正态分布的零均值和联合方差的随机数。 “0”可以提供任何值,这样数字将是所需的平均值,通过改变“1”,您将得到等于input平方的方差。
例如: =norminv(rand();50;3)
将产生正态分布的数字,其中MEAN = 50 VARIANCE = 9。
Q如何将均匀分布(如大多数随机数发生器产生的,例如0.0和1.0之间)转换为正态分布?
-
对于软件实现,我知道几个随机发生器的名称,它给你一个伪随机序列在[0,1](Mersenne Twister,线性同余发生器)。 我们称之为U(x)
-
它是存在的math领域,称为概率论。 第一件事:如果你想用积分分布F来模拟rv,那么你可以试着估计F ^ -1(U(x))。 在理论上,certificate这样的rv将具有整体分布F.
-
当F ^ -1可以毫无问题地推导出来时,步骤2可以适用于生成rv〜F而不需要使用任何计数方法。 (如exp.distribution)
-
要模拟正态分布,可以计算y1 * cos(y2),其中y1〜在[0,2pi]中是均匀的。 y2是相关分布。
问:如果我想要select一个平均值和标准差,该怎么办?
你可以计算sigma * N(0,1)+ m。
可以看出,这样的移位和缩放导致N(m,σ)
function distRandom(){ do{ x=random(DISTRIBUTION_DOMAIN); }while(random(DISTRIBUTION_RANGE)>=distributionFunction(x)); return x; }
近似:
function rnd_snd() { return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1); }