将均匀分布转化为正态分布。

时间:2022-07-03 11:33:09

How can I convert a uniform distribution (as most random number generators produce, e.g. between 0.0 and 1.0) into a normal distribution? What if I want a mean and standard deviation of my choosing?

如何将一个均匀分布(如大多数随机数生成器生成,例如0.0和1.0之间)转换为正态分布?如果我想要我选择的均值和标准差呢?

14 个解决方案

#1


45  

The Ziggurat algorithm is pretty efficient for this, although the Box-Muller transform is easier to implement from scratch (and not crazy slow).

Ziggurat算法在这方面是相当有效的,尽管Box-Muller转换更容易从头实现(而不是疯狂的慢)。

#2


38  

There are plenty of methods:

有很多方法:

  • Do not use Box Muller. Especially if you draw many gaussian numbers. Box Muller yields a result which is clamped between -6 and 6 (assuming double precision. Things worsen with floats.). And it is really less efficient than other available methods.
  • 切勿使用箱式碾磨机。特别是如果你画了很多高斯分布。Box Muller产生的结果是夹在-6和6之间(假设精度加倍)。事情恶化与浮动)。而且它比其他可用的方法效率要低。
  • Ziggurat is fine, but needs a table lookup (and some platform-specific tweaking due to cache size issues)
  • Ziggurat很好,但是需要一个表查找(以及一些特定于平台的调整,因为缓存大小问题)
  • Ratio-of-uniforms is my favorite, only a few addition/multiplications and a log 1/50th of the time (eg. look there).
  • 我最喜欢的是制服,只有几次增加/增加和1/50的时间(如。看)。
  • Inverting the CDF is efficient (and overlooked, why ?), you have fast implementations of it available if you search google. It is mandatory for Quasi-Random numbers.
  • 反转CDF是有效的(并且被忽略了,为什么?),如果您搜索谷歌,那么它的快速实现是可用的。准随机数是强制性的。

#3


23  

Changing the distribution of any function to another involves using the inverse of the function you want.

将任何函数的分布更改为另一个函数,需要使用您想要的函数的逆。

In other words, if you aim for a specific probability function p(x) you get the distribution by integrating over it -> d(x) = integral(p(x)) and use its inverse: Inv(d(x)). Now use the random probability function (which have uniform distribution) and cast the result value through the function Inv(d(x)). You should get random values cast with distribution according to the function you chose.

换句话说,如果你的目标是一个特定的概率函数p(x),你可以通过积分得到它的分布——> d(x) =积分(p(x))并使用它的逆:Inv(d(x))。现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))来计算结果值。你应该根据你选择的函数得到随机值。

This is the generic math approach - by using it you can now choose any probability or distribution function you have as long as it have inverse or good inverse approximation.

这是一般的数学方法,通过使用它,你可以选择任何概率或分布函数只要它有逆或逆近似。

Hope this helped and thanks for the small remark about using the distribution and not the probability itself.

希望这能帮助和感谢关于使用分布的小评论,而不是概率本身。

#4


20  

Here is a javascript implementation using the polar form of the Box-Muller transformation.

这里是一个javascript实现,使用了Box-Muller转换的极坐标形式。

/*
 * 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


5  

Use the central limit theorem wikipedia entry mathworld entry to your advantage.

使用中心极限定理,wikipedia条目mathworld条目对您的优势。

Generate n of the uniformly distributed numbers, sum them, subtract n*0.5 and you have the output of an approximately normal distribution with mean equal to 0 and variance equal to (1/12) * (1/sqrt(N)) (see wikipedia on uniform distributions for that last one)

生成n个均匀分布的数字,求和,减去n*0.5,得到一个近似正态分布的输出,均值等于0,方差等于(1/12)*(1/√n)(最后一项的均匀分布见*)

n=10 gives you something half decent fast. If you want something more than half decent go for tylers solution (as noted in the wikipedia entry on normal distributions)

n=10的时候,你可以很快地得到一些东西。如果你想要一些超过一半的体面的东西,可以选择tylers解决方案(正如*中关于正态分布的条目所指出的那样)

#6


1  

I would use Box-Muller. Two things about this:

我将用Box-Muller。两个事情:

  1. You end up with two values per iteration
    Typically, you cache one value and return the other. On the next call for a sample, you return the cached value.
  2. 通常,每次迭代的值为两个值,缓存一个值并返回另一个值。在下一个示例调用中,返回缓存的值。
  3. Box-Muller gives a Z-score
    You have to then scale the Z-score by the standard deviation and add the mean to get the full value in the normal distribution.
  4. Box-Muller给出了一个z分数,然后你必须按标准偏差对z分数进行缩放,并添加平均值来得到正态分布的全部值。

#7


1  

The standard Python library module random has what you want:

标准的Python库模块random拥有您想要的:

normalvariate(mu, sigma)
Normal distribution. mu is the mean, and sigma is the standard deviation.

normalvariate(μ、σ)正态分布。是均值,标准差是标准差。

For the algorithm itself, take a look at the function in random.py in the Python library.

对于算法本身,可以随意查看函数。在Python库中的py。

The manual entry is here

手动输入在这里。

#8


1  

Where R1, R2 are random uniform numbers:

R1 R2为随机均匀数:

NORMAL DISTRIBUTION, with SD of 1: sqrt(-2*log(R1))*cos(2*pi*R2)

正态分布,SD为1:sqrt(-2*log(R1))*cos(2*pi*R2)

This is exact... no need to do all those slow loops!

这是准确的…没有必要做所有那些缓慢的循环!

#9


1  

It seems incredible that I could add something to this after eight years, but for the case of Java I would like to point readers to the Random.nextGaussian() method, which generates a Gaussian distribution with mean 0.0 and standard deviation 1.0 for you.

似乎难以置信,我可以在8年后添加一些东西,但是对于Java,我想要将读者指向Random.nextGaussian()方法,它会生成一个带有均值0.0和标准偏差1.0的高斯分布。

A simple addition and/or multiplication will change the mean and standard deviation to your needs.

一个简单的加法和/或乘法将改变平均值和标准偏差到您的需要。

#10


0  

I thing you should try this in EXCEL: =norminv(rand();0;1). This will product the random numbers which should be normally distributed with the zero mean and unite variance. "0" can be supplied with any value, so that the numbers will be of desired mean, and by changing "1", you will get the variance equal to the square of your input.

我想您应该在EXCEL中尝试一下:=norminv(rand();0;1)。这将会产生随机的数字,这些随机数应该以零均值和统一方差分布。“0”可以提供任何值,因此数字将是期望的平均值,并且通过改变“1”,您将得到等于输入的平方的方差。

For example: =norminv(rand();50;3) will yield to the normally distributed numbers with MEAN = 50 VARIANCE = 9.

例如:=norminv(rand();50;3)将服从正态分布的均值= 50方差= 9。

#11


0  

Q How can I convert a uniform distribution (as most random number generators produce, e.g. between 0.0 and 1.0) into a normal distribution?

问:我如何将一个均匀分布(如大多数随机数生成器生成,例如介于0.0和1.0之间)转换为正态分布?

  1. For software implementation I know couple random generator names which give you a pseudo uniform random sequence in [0,1] (Mersenne Twister, Linear Congruate Generator). Let's call it U(x)

    对于软件实现,我知道一些随机生成器的名字,它们给你一个伪均匀随机序列在[0,1](Mersenne Twister,线性协调发电机)。我们叫它U(x)

  2. It is exist mathematical area which called probibility theory. First thing: If you want to model r.v. with integral distribution F then you can try just to evaluate F^-1(U(x)). In pr.theory it was proved that such r.v. will have integral distribution F.

    它是存在的数学领域,被称为可证明性理论。第一件事:如果你想模型分布随机变数积分然后你可以尝试评估F ^ 1(U(x))。在实践中,证明了这样的rv具有积分分布F。

  3. Step 2 can be appliable to generate r.v.~F without usage of any counting methods when F^-1 can be derived analytically without problems. (e.g. exp.distribution)

    第2步可以应用于生成r v。~ F F ^ 1时没有使用任何计算方法可以分析没有问题。(如exp.distribution)

  4. To model normal distribution you can cacculate y1*cos(y2), where y1~is uniform in[0,2pi]. and y2 is the relei distribution.

    为了模型正态分布,你可以计算y *cos(y2),其中y1~是均匀的[0,2]。y2是释放量分布。

Q: What if I want a mean and standard deviation of my choosing?

问:如果我想要我选择的平均值和标准偏差呢?

You can calculate sigma*N(0,1)+m.

你可以计算σ* N(0,1)+ m。

It can be shown that such shifting and scaling lead to N(m,sigma)

可以看出,这种移位和缩放会导致N(m,sigma)

#12


0  

This is a Matlab implementation using the polar form of the Box-Muller transformation:

这是一个Matlab实现,使用的是Box-Muller变换的极坐标形式:

Function randn_box_muller.m:

函数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

And invoking histfit(randn_box_muller(10000000),100); this is the result: 将均匀分布转化为正态分布。

和调用histfit(randn_box_muller(10000000),100);这是由于:

Obviously it is really inefficient compared with the Matlab built-in randn.

显然,与Matlab内置的randn相比,它是非常低效的。

#13


-1  

function distRandom(){
  do{
    x=random(DISTRIBUTION_DOMAIN);
  }while(random(DISTRIBUTION_RANGE)>=distributionFunction(x));
  return x;
}

#14


-3  

Approximation:

近似:

function rnd_snd() {
    return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1);
}

See http://www.protonfish.com/random.shtml

参见http://www.protonfish.com/random.shtml

#1


45  

The Ziggurat algorithm is pretty efficient for this, although the Box-Muller transform is easier to implement from scratch (and not crazy slow).

Ziggurat算法在这方面是相当有效的,尽管Box-Muller转换更容易从头实现(而不是疯狂的慢)。

#2


38  

There are plenty of methods:

有很多方法:

  • Do not use Box Muller. Especially if you draw many gaussian numbers. Box Muller yields a result which is clamped between -6 and 6 (assuming double precision. Things worsen with floats.). And it is really less efficient than other available methods.
  • 切勿使用箱式碾磨机。特别是如果你画了很多高斯分布。Box Muller产生的结果是夹在-6和6之间(假设精度加倍)。事情恶化与浮动)。而且它比其他可用的方法效率要低。
  • Ziggurat is fine, but needs a table lookup (and some platform-specific tweaking due to cache size issues)
  • Ziggurat很好,但是需要一个表查找(以及一些特定于平台的调整,因为缓存大小问题)
  • Ratio-of-uniforms is my favorite, only a few addition/multiplications and a log 1/50th of the time (eg. look there).
  • 我最喜欢的是制服,只有几次增加/增加和1/50的时间(如。看)。
  • Inverting the CDF is efficient (and overlooked, why ?), you have fast implementations of it available if you search google. It is mandatory for Quasi-Random numbers.
  • 反转CDF是有效的(并且被忽略了,为什么?),如果您搜索谷歌,那么它的快速实现是可用的。准随机数是强制性的。

#3


23  

Changing the distribution of any function to another involves using the inverse of the function you want.

将任何函数的分布更改为另一个函数,需要使用您想要的函数的逆。

In other words, if you aim for a specific probability function p(x) you get the distribution by integrating over it -> d(x) = integral(p(x)) and use its inverse: Inv(d(x)). Now use the random probability function (which have uniform distribution) and cast the result value through the function Inv(d(x)). You should get random values cast with distribution according to the function you chose.

换句话说,如果你的目标是一个特定的概率函数p(x),你可以通过积分得到它的分布——> d(x) =积分(p(x))并使用它的逆:Inv(d(x))。现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))来计算结果值。你应该根据你选择的函数得到随机值。

This is the generic math approach - by using it you can now choose any probability or distribution function you have as long as it have inverse or good inverse approximation.

这是一般的数学方法,通过使用它,你可以选择任何概率或分布函数只要它有逆或逆近似。

Hope this helped and thanks for the small remark about using the distribution and not the probability itself.

希望这能帮助和感谢关于使用分布的小评论,而不是概率本身。

#4


20  

Here is a javascript implementation using the polar form of the Box-Muller transformation.

这里是一个javascript实现,使用了Box-Muller转换的极坐标形式。

/*
 * 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


5  

Use the central limit theorem wikipedia entry mathworld entry to your advantage.

使用中心极限定理,wikipedia条目mathworld条目对您的优势。

Generate n of the uniformly distributed numbers, sum them, subtract n*0.5 and you have the output of an approximately normal distribution with mean equal to 0 and variance equal to (1/12) * (1/sqrt(N)) (see wikipedia on uniform distributions for that last one)

生成n个均匀分布的数字,求和,减去n*0.5,得到一个近似正态分布的输出,均值等于0,方差等于(1/12)*(1/√n)(最后一项的均匀分布见*)

n=10 gives you something half decent fast. If you want something more than half decent go for tylers solution (as noted in the wikipedia entry on normal distributions)

n=10的时候,你可以很快地得到一些东西。如果你想要一些超过一半的体面的东西,可以选择tylers解决方案(正如*中关于正态分布的条目所指出的那样)

#6


1  

I would use Box-Muller. Two things about this:

我将用Box-Muller。两个事情:

  1. You end up with two values per iteration
    Typically, you cache one value and return the other. On the next call for a sample, you return the cached value.
  2. 通常,每次迭代的值为两个值,缓存一个值并返回另一个值。在下一个示例调用中,返回缓存的值。
  3. Box-Muller gives a Z-score
    You have to then scale the Z-score by the standard deviation and add the mean to get the full value in the normal distribution.
  4. Box-Muller给出了一个z分数,然后你必须按标准偏差对z分数进行缩放,并添加平均值来得到正态分布的全部值。

#7


1  

The standard Python library module random has what you want:

标准的Python库模块random拥有您想要的:

normalvariate(mu, sigma)
Normal distribution. mu is the mean, and sigma is the standard deviation.

normalvariate(μ、σ)正态分布。是均值,标准差是标准差。

For the algorithm itself, take a look at the function in random.py in the Python library.

对于算法本身,可以随意查看函数。在Python库中的py。

The manual entry is here

手动输入在这里。

#8


1  

Where R1, R2 are random uniform numbers:

R1 R2为随机均匀数:

NORMAL DISTRIBUTION, with SD of 1: sqrt(-2*log(R1))*cos(2*pi*R2)

正态分布,SD为1:sqrt(-2*log(R1))*cos(2*pi*R2)

This is exact... no need to do all those slow loops!

这是准确的…没有必要做所有那些缓慢的循环!

#9


1  

It seems incredible that I could add something to this after eight years, but for the case of Java I would like to point readers to the Random.nextGaussian() method, which generates a Gaussian distribution with mean 0.0 and standard deviation 1.0 for you.

似乎难以置信,我可以在8年后添加一些东西,但是对于Java,我想要将读者指向Random.nextGaussian()方法,它会生成一个带有均值0.0和标准偏差1.0的高斯分布。

A simple addition and/or multiplication will change the mean and standard deviation to your needs.

一个简单的加法和/或乘法将改变平均值和标准偏差到您的需要。

#10


0  

I thing you should try this in EXCEL: =norminv(rand();0;1). This will product the random numbers which should be normally distributed with the zero mean and unite variance. "0" can be supplied with any value, so that the numbers will be of desired mean, and by changing "1", you will get the variance equal to the square of your input.

我想您应该在EXCEL中尝试一下:=norminv(rand();0;1)。这将会产生随机的数字,这些随机数应该以零均值和统一方差分布。“0”可以提供任何值,因此数字将是期望的平均值,并且通过改变“1”,您将得到等于输入的平方的方差。

For example: =norminv(rand();50;3) will yield to the normally distributed numbers with MEAN = 50 VARIANCE = 9.

例如:=norminv(rand();50;3)将服从正态分布的均值= 50方差= 9。

#11


0  

Q How can I convert a uniform distribution (as most random number generators produce, e.g. between 0.0 and 1.0) into a normal distribution?

问:我如何将一个均匀分布(如大多数随机数生成器生成,例如介于0.0和1.0之间)转换为正态分布?

  1. For software implementation I know couple random generator names which give you a pseudo uniform random sequence in [0,1] (Mersenne Twister, Linear Congruate Generator). Let's call it U(x)

    对于软件实现,我知道一些随机生成器的名字,它们给你一个伪均匀随机序列在[0,1](Mersenne Twister,线性协调发电机)。我们叫它U(x)

  2. It is exist mathematical area which called probibility theory. First thing: If you want to model r.v. with integral distribution F then you can try just to evaluate F^-1(U(x)). In pr.theory it was proved that such r.v. will have integral distribution F.

    它是存在的数学领域,被称为可证明性理论。第一件事:如果你想模型分布随机变数积分然后你可以尝试评估F ^ 1(U(x))。在实践中,证明了这样的rv具有积分分布F。

  3. Step 2 can be appliable to generate r.v.~F without usage of any counting methods when F^-1 can be derived analytically without problems. (e.g. exp.distribution)

    第2步可以应用于生成r v。~ F F ^ 1时没有使用任何计算方法可以分析没有问题。(如exp.distribution)

  4. To model normal distribution you can cacculate y1*cos(y2), where y1~is uniform in[0,2pi]. and y2 is the relei distribution.

    为了模型正态分布,你可以计算y *cos(y2),其中y1~是均匀的[0,2]。y2是释放量分布。

Q: What if I want a mean and standard deviation of my choosing?

问:如果我想要我选择的平均值和标准偏差呢?

You can calculate sigma*N(0,1)+m.

你可以计算σ* N(0,1)+ m。

It can be shown that such shifting and scaling lead to N(m,sigma)

可以看出,这种移位和缩放会导致N(m,sigma)

#12


0  

This is a Matlab implementation using the polar form of the Box-Muller transformation:

这是一个Matlab实现,使用的是Box-Muller变换的极坐标形式:

Function randn_box_muller.m:

函数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

And invoking histfit(randn_box_muller(10000000),100); this is the result: 将均匀分布转化为正态分布。

和调用histfit(randn_box_muller(10000000),100);这是由于:

Obviously it is really inefficient compared with the Matlab built-in randn.

显然,与Matlab内置的randn相比,它是非常低效的。

#13


-1  

function distRandom(){
  do{
    x=random(DISTRIBUTION_DOMAIN);
  }while(random(DISTRIBUTION_RANGE)>=distributionFunction(x));
  return x;
}

#14


-3  

Approximation:

近似:

function rnd_snd() {
    return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1);
}

See http://www.protonfish.com/random.shtml

参见http://www.protonfish.com/random.shtml