当前位置:  开发笔记 > 编程语言 > 正文

将均匀分布转换为正态分布

如何解决《将均匀分布转换为正态分布》经验,为你挑选了5个好方法。

如何将均匀分布(大多数随机数生成器产生,例如介于0.0和1.0之间)转换为正态分布?如果我想要选择的平均值和标准偏差怎么办?



1> Tyler..:

该通灵塔的算法是这个相当有效,虽然箱穆勒变换更容易从头开始实现(而不是疯狂的慢).


关于线性全等发生器的常见警告适用于这两种方法,因此使用适当的下层发生器.干杯.
如Mersenee Twister,或者您有其他建议吗?

2> Alexandre C...:

有很多方法:

千万不能用箱穆勒.特别是如果你绘制许多高斯数字.Box Muller产生的结果夹在-6和6之间(假设是双精度.浮子会恶化).它的效率确实低于其他可用方法.

Ziggurat很好,但需要一个表查找(由于缓存大小问题,还有一些特定于平台的调整)

制服比例是我最喜欢的,只有少数加法/乘法和1/50的时间日志(例如看那里).

反转CDF 有效的(并忽略了,为什么?),如果您搜索谷歌,您可以快速实现它.准随机数是强制性的.


@locster:反向CDF方法也共享这个不良属性.见http://www.cimat.mx/~src/prope08/randomgauss.pdf.这可以通过使用具有非零概率的均匀RNG来缓解,以产生非常接近零的浮点数.大多数RNG没有,因为它们生成一个(通常是64位)整数,然后映射到[0,1].这使得这些方法不适合对高斯变量的尾部进行采样(考虑在计算金融中定价低/高冲击选项).
我认为不使用Box Muller转换的建议会误导大部分用户.很高兴知道这个限制,但正如CrazyCasta所指出的那样,对于大多数并非严重依赖于异常值的应用程序,您可能不需要担心这一点.例如,如果您曾经依赖于使用numpy的法线采样,那么您依赖于Box Muller变换(极坐标形式)https://github.com/numpy/numpy/blob/c08d2647240555e730da7580374a61d8547a932e/numpy/random/ mtrand/randomkit.c#L619.
@AlexandreC.为了清楚两点,使用64位数字,尾部变为8.57或9.41(较低的值对应于在记录之前转换为[0,1)).即使被限制在[-6,6],超出这个范围的几率大约是1.98e-9,对于大多数人来说甚至在科学上也是如此.对于8.57和9.41的数字,这变为1.04e-17和4.97e-21.这些数字非常小,以至于Box Muller采样和真正的高斯采样之间的差异几乎完全是学术性的.如果你需要更好,只需加上其中四个除以2.

3> Adi..:

将任何函数的分布更改为另一个函数涉及使用所需函数的反函数.

换句话说,如果你瞄准特定概率函数p(x),你可以通过积分得到分布 - > d(x)=积分(p(x))并使用它的逆:Inv(d(x)) .现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))投射结果值.您应该根据您选择的函数获得随分布的随机值.

这是一般的数学方法 - 通过使用它,您现在可以选择任何概率或分布函数,只要它具有反向或良好的反向近似.

希望这有助于并感谢关于使用分布的小注释,而不是概率本身.


请注意,您需要反转累积分布函数,而不是概率分布函数.亚历山大暗示了这一点,但我认为更明确地提及它可能不会受到伤害 - 因为答案似乎暗示了PDF
+1这是一种用于生成非常好的高斯变量的被忽略的方法.在这种情况下,逆向CDF可以用牛顿法有效地计算(导数是e ^ { - t ^ 2}),初始近似很容易得到作为有理分数,因此你需要对erf和exp进行3-4次评估.如果你使用准随机数,这是必须的,你必须使用一个统一的数字才能获得高斯数.
这称为[逆变换采样](https://en.wikipedia.org/wiki/Inverse_transform_sampling)

4> user5084..:

这是一个使用Box-Muller转换的极性形式的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 */
}



5> jilles de wi..:

使用中心限制定理维基百科条目 mathworld条目对您有利.

生成n个均匀分布的数,求和,减去n*0.5,得到近似正态分布的输出,均值等于0,方差等于(1/12) * (1/sqrt(N))(参见上一个均匀分布的维基百科)

n = 10给你一些快速的东西.如果你想要超过一半的东西去做tylers解决方案(如正常发行版的维基百科条目中所述)

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有