如何将均匀分布(大多数随机数生成器产生,例如介于0.0和1.0之间)转换为正态分布?如果我想要选择的平均值和标准偏差怎么办?
答案 0 :(得分:47)
Ziggurat algorithm对此非常有效,尽管Box-Muller transform更容易从头开始实施(而不是疯狂的慢)。
答案 1 :(得分:40)
有很多方法:
答案 2 :(得分:26)
将任何函数的分布更改为另一个函数涉及使用所需函数的反函数。
换句话说,如果你的目标是一个特定的概率函数p(x),你可以通过积分来获得分布 - > d(x)=积分(p(x))并使用其逆:Inv(d(x))。现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))投射结果值。您应该根据您选择的函数获得随分布的随机值。
这是一般的数学方法 - 通过使用它,您现在可以选择任何概率或分布函数,只要它具有逆或良好的逆近似。
希望这有所帮助,并感谢关于使用分布的小注释,而不是概率本身。
答案 3 :(得分:20)
这是一个使用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 */
}
答案 4 :(得分:5)
使用中心限制定理wikipedia entry mathworld entry对您有利。
生成n个均匀分布的数,求和,减去n * 0.5,得到近似正态分布的输出,均值等于0,方差等于(1/12) * (1/sqrt(N))
(参见wikipedia on uniform distributions for最后一个)
n = 10给你一些快速的东西。如果你想要超过一半的东西去寻找解决方案(如wikipedia entry on normal distributions中所述)
答案 5 :(得分:1)
其中R1,R2是随机统一数字:
正态分布,SD为1:sqrt(-2 * log(R1))* cos(2 * pi * R2)
这是确切的......不需要做所有那些缓慢的循环!
答案 6 :(得分:1)
这是我从Donald Knuth的书计算机编程的艺术<3.4>的3.4.1节中的 Algorithm P (正常偏离的极化方法)的JavaScript实现。 / em>:
function normal_random(mean,stddev)
{
var V1
var V2
var S
do{
var U1 = Math.random() // return uniform distributed in [0,1[
var U2 = Math.random()
V1 = 2*U1-1
V2 = 2*U2-1
S = V1*V1+V2*V2
}while(S >= 1)
if(S===0) return 0
return mean+stddev*(V1*Math.sqrt(-2*Math.log(S)/S))
}
答案 7 :(得分:1)
似乎令人难以置信的是,我可以在八年后添加一些内容,但对于Java的情况,我想向读者指出Random.nextGaussian()方法,该方法生成平均值为0.0且标准差为1.0的高斯分布对你而言。
简单的加法和/或乘法会根据您的需要改变均值和标准差。
答案 8 :(得分:1)
标准的Python库模块 random 有你想要的:
normalvariate(mu,sigma)
正态分布。 mu是平均值,sigma是标准偏差。
对于算法本身,请查看Python库中random.py中的函数。
答案 9 :(得分:1)
我会使用Box-Muller。关于这一点的两件事:
答案 10 :(得分:0)
我觉得你应该在EXCEL中尝试这个:=norminv(rand();0;1)
。这将产生随机数,这些随机数应该正态分布,具有零均值和联合方差。 “0”可以提供任何值,因此数字将是所需的平均值,通过更改“1”,您将获得等于输入平方的方差。
例如:=norminv(rand();50;3)
将产生正态分布的数字,MEAN = 50 VARIANCE = 9。
答案 11 :(得分:0)
问我如何将均匀分布(大多数随机数生成器产生,例如介于0.0和1.0之间)转换为正态分布?
对于软件实现,我知道一对随机生成器名称,它们在[0,1](Mersenne Twister,Linear Congruate Generator)中为您提供伪均匀随机序列。我们称之为U(x)
存在称为概率论的数学领域。 第一件事:如果你想模特r.v.使用积分分布F,您可以尝试仅评估F ^ -1(U(x))。在理论上证明了这样的r.v.将有整体分布F.
步骤2可以适用于生成r.v.~F而不使用任何计数方法,因为可以在没有问题的情况下分析地导出F ^ -1。 (例如exp.distribution)
为了模拟正态分布,你可以计算y1 * cos(y2),其中y1~在[0,2pi]中是均匀的。和y2是转发分发。
问:如果我想要选择的平均值和标准偏差怎么办?
您可以计算sigma * N(0,1)+ m。
可以证明,这种移位和缩放导致N(m,sigma)
答案 12 :(得分:0)
这是一个使用Box-Muller转换的极坐标形式的Matlab实现:
功能randn_box_muller.m
:
function [values] = randn_box_muller(n, mean, std_dev)
if nargin == 1
mean = 0;
std_dev = 1;
end
r = gaussRandomN(n);
values = r.*std_dev - mean;
end
function [values] = gaussRandomN(n)
[u, v, r] = gaussRandomNValid(n);
c = sqrt(-2*log(r)./r);
values = u.*c;
end
function [u, v, r] = gaussRandomNValid(n)
r = zeros(n, 1);
u = zeros(n, 1);
v = zeros(n, 1);
filter = r==0 | r>=1;
% if outside interval [0,1] start over
while n ~= 0
u(filter) = 2*rand(n, 1)-1;
v(filter) = 2*rand(n, 1)-1;
r(filter) = u(filter).*u(filter) + v(filter).*v(filter);
filter = r==0 | r>=1;
n = size(r(filter),1);
end
end
并调用histfit(randn_box_muller(10000000),100);
这是结果:
与Matlab内置的randn相比,显然效率非常低。
答案 13 :(得分:0)
我有以下代码可能会有所帮助:
set.seed(123)
n <- 1000
u <- runif(n) #creates U
x <- -log(u)
y <- runif(n, max=u*sqrt((2*exp(1))/pi)) #create Y
z <- ifelse (y < dnorm(x)/2, -x, NA)
z <- ifelse ((y > dnorm(x)/2) & (y < dnorm(x)), x, z)
z <- z[!is.na(z)]
答案 14 :(得分:0)
使用实现的函数rnorm()也会更容易,因为它比编写用于正态分布的随机数生成器要快。参见以下代码作为证明
n <- length(z)
t0 <- Sys.time()
z <- rnorm(n)
t1 <- Sys.time()
t1-t0
答案 15 :(得分:-1)
function distRandom(){
do{
x=random(DISTRIBUTION_DOMAIN);
}while(random(DISTRIBUTION_RANGE)>=distributionFunction(x));
return x;
}
答案 16 :(得分:-2)
逼近:
function rnd_snd() {
return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1);
}