Implementación de una variable aleatoria gaussiana utilizando una variable aleatoria uniforme

11

Estoy tratando de escribir una función C ++ que devolverá valores aleatorios gaussianos, dadas sus medias y variaciones.

Hay una función de biblioteca rand(), que devuelve números aleatorios entre 0y RAND_MAX. RAND_MAXno tiene un valor fijo, pero se garantiza que será al menos . Su PDF es uniforme.2151

Estoy usando el Teorema del límite central para transformar esto rand()en una variable gaussiana. Lo que estoy haciendo exactamente es llamar rand()a un usuario las horas especificadas, luego sumar sus valores de retorno, luego cambiar su media a la media especificada por el usuario.

PDF gaussiano
En el trazado anterior, llamé a mi generador aleatorio gaussiano veces y tracé las frecuencias de sus valores de retorno. Como puede ver, su variación es enorme, ya que se crea mediante la suma de muchos otros valores aleatorios.107

Devuelve con éxito una variable gaussiana con un PDF gaussiano y con el valor medio especificado. Sin embargo, el problema es su varianza. Estoy atascado en este punto, porque no sé cómo cambiar su variación al valor especificado por el usuario.

Este es mi código (incompleto por ahora; se ignora el parámetro "Varianza"):

template <class T>
T Random::GetGaussian(T Mean /*= 0*/, T Variance /*= 1*/)
{
    T MeanOfSum = NUM_GAUSSIAN_SUMS / static_cast<T>(2);
    T Rand = 0;
    for (uint64_t i=0; i<NUM_GAUSSIAN_SUMS; i++)
    {
        Rand += static_cast<T>(rand()) / RAND_MAX;
    }
    return Rand - (MeanOfSum - Mean);
}

Suponga que NUM_GAUSSIAN_SUMSes 100 y RAND_MAXes 32767.

Quiero cambiar la varianza de la variable aleatoria de acuerdo con el parámetro de la función. Mi pregunta es, ¿cómo puedo cambiar la varianza de esta variable aleatoria? ¿Cómo puedo hacerlo?

hkBattousai
fuente
3
Hay formas mejores y más rápidas que el teorema del límite central para generar variables aleatorias gaussianas. Busque el método Box-Muller para uno; Se dice que un método de zigurat es aún mejor.
Dilip Sarwate
3
En los viejos tiempos, cuando el tiempo de ejecución era una consideración importante, las personas sumaban variables aleatorias (no ) y restaban para obtener una aproximación simple a una variable aleatoria estándar , y luego escalar para obtener una variable aleatoria . (Para saber por qué esto funciona, vea la respuesta de @ Hilmar). Para muchas aplicaciones, este método simple funcionó muy bien, pero los valores se restringieron al rango y esta idea simple se abandonó cuando Six-Sigma se convirtió en una palabra de moda. U ( 0 , 1 ) 100 6 N ( 0 , 1 ) Y = σ X + μ N ( μ , σ 2 ) ( μ - 6 σ , μ + 6 σ )12 U(0,1)1006N(0,1)Y=σX+μN(μ,σ2)(μ6σ,μ+6σ)
Dilip Sarwate
@DilipSarwate tal vez deberías publicar esas alternativas como respuesta con una justificación de por qué preferiríamos eso
Ivo Flipse
@IvoFlipse La respuesta a la pregunta fue "¿Cómo soluciono la varianza después de haber arreglado la media?" es esencialmente lo que dice la respuesta aceptada por Hilmar, modificada por los comentarios: corrija la varianza escalando y luego vuelva a arreglar la media, o mejor aún, no comience arreglando la media primero ya que tendrá que volver a arreglar eso mas tarde; corrija la varianza primero escalando y luego corrija la media. El OP no indica que él / ella esté interesado en mejores métodos y ni siquiera ha votado por el enlace de nibot, que incluso tiene el código para el método Box-Muller. Así que dejaré las cosas como están.
Dilip Sarwate

Respuestas:

6

Su algoritmo inicial crea una variable aleatoria que se distribuye uniformemente entre 0 y 1. La varianza de eso es 1/12. Si sumas NUM_GAUSSIAN_SUMSinstancias de eso, la varianza será NUM_GAUSSIAN_SUMS/12. Para llegar a una varianza objetivo V, debe multiplicar la variable aleatoria sumada con sqrt(V*12/NUM_GAUSSIAN_SUMS).

Como nota al margen, una plantilla funcionará razonablemente bien para flotadores y dobles, pero habrá problemas numéricos significativos con cualquier tipo de punto fijo.

Hilmar
fuente
5

¿Cómo puedo cambiar la varianza de esta variable aleatoria?

Por multiplicación, por supuesto. La varianza de , donde es la constante multiplicativa y es la variable aleatoria, es la varianza de .c X c 2 XcXcXc2X

Emre
fuente
Desafortunadamente, la media de es veces la media de , por lo que uno de los parámetros que el OP estableció antes de intentar corregir la variación debe restablecerse al valor deseado. c XcXcX
Dilip Sarwate
1
Centrar, reescalar, luego restaurar la media. Escalar una variable aleatoria centrada no afectará la media (cero).
Emre
1

¡Hay otra manera!

Piénsalo, ¿y si quisieras alguna otra distribución en lugar de Gauss? En ese caso, no podrías usar el teorema del límite central; ¿Cómo lo resuelves entonces?

Hay una manera de convertir una variable aleatoria uniforme en PDF arbitrario. Este método se llama Método de transformación inversa

Si se distribuye uniformemente en el intervalo (0, 1), entoncesU[01]

X=FX1(U)

tiene cdf .FX(x)

Por lo tanto, todo lo que necesita hacer es aplicar la función CDF inversa a la variable que ha recuperado de la muestra de rv uniforme.

Además, a diferencia de los métodos anteriores, esto no requerirá ninguna iteración y no dependerá de cuántas iteraciones se tomarán para hacer que los resultados se acerquen a Gauss.

Aquí está una de las referencias que da prueba de esto.

Dipan Mehta
fuente
3
> ¡Hay otra manera! Cierto, pero irrelevante para la pregunta en consideración, que es específicamente sobre las variables aleatorias gaussianas. Ni el CDF gaussiano ni su inverso pueden expresarse en términos elementales utilizando un número finito de operaciones, por lo que el método sugerido no puede utilizarse.
Dilip Sarwate