赞
踩
原文链接:https://www.alanzucconi.com/2015/09/16/how-to-sample-from-a-gaussian-distribution/
假设有两个独立随机变量X, Y服从高斯分布:
若在二维平面上采样横纵坐标分别为(X, Y)的点,得到的图为:
点(X, Y)在该平面上的联合概率密度函数为:
将平面直角坐标系转换为极坐标系:
则点的横纵坐标可记做:
则联合概率密度函数可写作:
这又可以看成是两个独立的概率分布的联合:
这里的已经服从均匀分布了,回忆一下质数分布的定义:
发现R也服从均匀分布:
这样,两个变量就都服从均匀分布了,因此高斯分布可以用两个均匀分布来生成。
现在反推第一步的流程,得到生成高斯分布的算法:
(1)生成两个服从U[0, 1]均匀分布的变量
(2)由这两个变量生成R和:,
(3)将从极坐标系转换成笛卡尔坐标系
这就是 Box-Muller transform。下图显示了在单位正方形里用Box-Muller transform将均匀分布的点映射成高斯分布的方式。
Box-Muller transform的问题是:它本身使用了复杂的三角函数,这很影响运算速度。为解决该问题,Marsaglia polar method出现了。它是由一个服从二维(-1,1)的均匀分布的点中产生的。这个点必须在单位圆中出现,且不能是原点(0,0)。如果不满足上述条件,则选择下一个点。代码如下:
- public static float NextGaussian() {
- float v1, v2, s;
- do {
- v1 = 2.0f * Random.Range(0f,1f) - 1.0f;
- v2 = 2.0f * Random.Range(0f,1f) - 1.0f;
- s = v1 * v1 + v2 * v2;
- } while (s >= 1.0f || s == 0f);
-
- s = Mathf.Sqrt((-2.0f * Mathf.Log(s)) / s);
-
- return v1 * s;
- }
该方法中大约21%的点会被排除。
第三步中的算法提供了一种从中采样的方法。我们可以用如下方法将其转换为任意的正态分布:
- public static float NextGaussian(float mean, float standard_deviation)
- {
- return mean + NextGaussian() * standard_deviation;
- }
还有一个问题是,高斯分布可能会产生偏离均值很远的极值,这不是我们想要的结果。如何生成有着最值限制的,服从高斯分布的随机函数呢?代码如下所示:
- public static float NextGaussian (float mean, float standard_deviation, float min, float max) {
- float x;
- do {
- x = NextGaussian(mean, standard_deviation);
- } while (x < min || x > max);
- retun x;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。