uniforme resueltos normal exponencial ejercicios ejemplos distribucion discreta continua aplicaciones algorithm language-agnostic random normal-distribution

algorithm - resueltos - Convertir una distribución uniforme a una distribución normal



distribucion uniforme excel (14)

¿Cómo puedo convertir una distribución uniforme (como la mayoría de los generadores de números aleatorios producen, por ejemplo, entre 0.0 y 1.0) en una distribución normal? ¿Qué pasa si quiero una desviación estándar y media de mi elección?



Aquí hay una implementación de javascript que usa la forma polar de la transformación 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 */ }


Cambiar la distribución de cualquier función a otra implica usar el inverso de la función que desee.

En otras palabras, si apuntas a una función de probabilidad específica p (x) obtienes la distribución integrando sobre ella -> d (x) = integral (p (x)) y usas su inversa: Inv (d (x)) . Ahora usa la función de probabilidad aleatoria (que tiene una distribución uniforme) y emite el valor del resultado a través de la función Inv (d (x)). Debería obtener valores aleatorios con distribución según la función que elija.

Este es el enfoque matemático genérico: al usarlo ahora puede elegir cualquier función de probabilidad o distribución que tenga, siempre que tenga una aproximación inversa inversa o buena.

Espero que esto ayude y gracias por el pequeño comentario sobre el uso de la distribución y no la probabilidad en sí misma.


Creo que deberías probar esto en EXCEL: =norminv(rand();0;1) . Esto producirá los números aleatorios que deberían distribuirse normalmente con la media cero y la varianza unida. "0" se puede suministrar con cualquier valor, de modo que los números serán de la media deseada, y al cambiar "1", obtendrá la varianza igual al cuadrado de su entrada.

Por ejemplo: =norminv(rand();50;3) cederá a los números distribuidos normalmente con MEAN = 50 VARIANCE = 9.


Donde R1, R2 son números uniformes al azar:

DISTRIBUCIÓN NORMAL, con SD de 1: sqrt (-2 * log (R1)) * cos (2 * pi * R2)

Esto es exacto ... ¡no hay necesidad de hacer todos esos bucles lentos!



El módulo de biblioteca de Python estándar al azar tiene lo que desea:

normalvariate (mu, sigma)
Distribución normal. mu es la media, y sigma es la desviación estándar.

Para el algoritmo en sí, eche un vistazo a la función en random.py en la biblioteca de Python.

La entrada manual está aquí


Esta es una implementación de Matlab que utiliza la forma polar de la transformación Box-Muller :

Función 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

E invocar a histfit(randn_box_muller(10000000),100); este es el resultado:

Obviamente, es realmente ineficiente en comparación con el randn incorporado de Matlab.


Hay muchos métodos:

  • No use Box Muller. Especialmente si dibujas muchos números gaussianos. Box Muller produce un resultado que se fija entre -6 y 6 (suponiendo una precisión doble. Las cosas empeoran con los flotadores). Y es realmente menos eficiente que otros métodos disponibles.
  • Ziggurat está bien, pero necesita una búsqueda de tabla (y algunos ajustes específicos de plataforma debido a problemas de tamaño de caché)
  • La relación de uniformes es mi favorita, solo unas pocas adiciones / multiplicaciones y un registro 1/50 de las veces (por ejemplo, mira allí ).
  • Invertir el CDF es eficiente (y se pasa por alto, ¿por qué?), Tiene implementaciones rápidas disponibles si busca en google. Es obligatorio para números cuasialeatorios.

P ¿Cómo puedo convertir una distribución uniforme (como la mayoría de los generadores de números aleatorios producen, por ejemplo, entre 0.0 y 1.0) en una distribución normal?

  1. Para la implementación del software, conozco un par de nombres de generador aleatorio que le dan una secuencia aleatoria pseudo uniforme en [0,1] (Mersenne Twister, Linear Congruate Generator). Vamos a llamarlo U (x)

  2. Es un área matemática existente que llamó teoría de la probidad. Lo primero: si desea modelar rv con distribución integral F, puede intentar simplemente evaluar F ^ -1 (U (x)). En pr.theory se demostró que tal rv tendrá una distribución integral F.

  3. El paso 2 puede ser apliable para generar rv ~ F sin utilizar ningún método de conteo cuando F ^ -1 puede obtenerse analíticamente sin problemas. (por ejemplo, exp.distribution)

  4. Para modelar la distribución normal, puede calcular y1 * cos (y2), donde y1 ~ es uniforme en [0,2pi]. y y2 es la distribución de relei.

P: ¿Qué sucede si quiero una desviación estándar y media de mi elección?

Puede calcular sigma * N (0,1) + m.

Se puede demostrar que dicho desplazamiento y escalado conducen a N (m, sigma)


Parece increíble que pueda agregar algo a esto después de ocho años, pero para el caso de Java me gustaría señalar a los lectores con el método Random.nextGaussian() , que genera una distribución gaussiana con una media de 0.0 y una desviación estándar de 1.0 para usted.

Una simple suma y / o multiplicación cambiará la media y la desviación estándar según sus necesidades.


Utilice la entrada del mundo matemático del teorema del límite central wikipedia para su ventaja.

Genera n de los números distribuidos uniformemente, sumándolos, restar n * 0.5 y tienes la salida de una distribución aproximadamente normal con una media igual a 0 y una varianza igual a (1/12) * (1/sqrt(N)) (ver wikipedia en distribuciones uniformes para ese último)

n = 10 te da algo medio decente rápido. Si desea algo más que medio decente, busque la solución tylers (como se indica en la entrada de wikipedia en distribuciones normales )


Yo usaría Box-Muller. Dos cosas sobre esto:

  1. Terminas con dos valores por iteración
    Normalmente, guarda en caché un valor y devuelve el otro. En la siguiente llamada para una muestra, devuelve el valor almacenado en caché.
  2. Box-Muller da un puntaje Z
    A continuación, debe escalar el puntaje Z por la desviación estándar y agregar la media para obtener el valor completo en la distribución normal.

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