2010-01-31 13 views
16

Dada una matriz de tamaño n Quiero generar probabilidades aleatorios para cada índice tal que Sigma(a[0]..a[n-1])=1Generación de una distribución de probabilidad

Un resultado posible podría ser:

0  1  2  3  4 
0.15 0.2 0.18 0.22 0.25 

Otro resultado perfectamente legal puede ser:

0  1  2  3  4 
0.01 0.01 0.96 0.01 0.01 

¿Cómo puedo generar estos de forma fácil y rápida? Las respuestas en cualquier idioma son buenas, se prefiere Java.

+0

por Sigma quiere decir la desviación estándar? Espero que te des cuenta de que tan pronto como dices desviación estándar, automáticamente implica que estás sacando tus números aleatorios de la distribución normal. – ldog

+0

La mayoría de los RNG de computadora extraen números de la distribución uniforme. – ldog

+0

Puede dar un paso al frente de este problema al darse cuenta de que el teorema del límite central puede ayudar: http://en.wikipedia.org/wiki/Text_limit_theorem – ldog

Respuesta

15

La tarea que está tratando de lograr es equivalente a dibujar un punto al azar de la unidad de dimensión simple simplex.

http://en.wikipedia.org/wiki/Simplex#Random_sampling podría ayudarlo.

Una solución ingenua podría ir tan siguiente:

public static double[] getArray(int n) 
    { 
     double a[] = new double[n]; 
     double s = 0.0d; 
     Random random = new Random(); 
     for (int i = 0; i < n; i++) 
     { 
      a [i] = 1.0d - random.nextDouble(); 
      a [i] = -1 * Math.log(a[i]); 
      s += a[i]; 
     } 
     for (int i = 0; i < n; i++) 
     { 
      a [i] /= s; 
     } 
     return a; 
    } 

Para dibujar un punto uniformemente de la unidad de N-dimensional simplex, hay que tener un vector de variables aleatorias exponencialmente distribuido, entonces normalizarla por la suma de esas variables. Para obtener un valor distribuido exponencialmente, tomamos un valor log negativo de distribución uniforme.

+3

En la mayoría de los idiomas, debe crear 'Random' solo una vez, o obtendrá resultados no aleatorios (y en muchos casos, el mismo número una y otra vez). También me preocupa el uso de 'log'. ¿Puedes explicar por qué está ahí? – Kobi

+0

+1 para una buena referencia, pero creo que 'nextDouble()' ya se ajusta para una distribución uniforme: http://java.sun.com/javase/6/docs/api/java/util/Random.html#nextDouble() – trashgod

+0

Kobi, gracias por señalar la 'nueva cosa aleatoria()'. En cuanto a 'log', he editado mi publicación para incluir una explicación más completa. – viaclectic

22

Obtenga n números aleatorios, calcule su suma y normalice la suma en 1 dividiendo cada número con la suma.

+0

Nice :) no pensé en eso ... תודה! –

+12

Esto introduce un sesgo. No se puede muestrear uniformemente desde un símplex de esta manera. – dreeves

+0

@dreeves - ¿puedes dar más detalles? –

0

Si desea generar valores de una distribución normal de manera eficiente, intente con Box Muller Transformation.

+0

Buen consejo, pero creo que no es pertinente. – dreeves

1

Esto es relativamente tarde, pero para mostrar la enmienda a la respuesta simple y directa de @ Kobi dada en este paper apuntado por @dreeves que hace que el muestreo sea uniforme. El método (si lo entiendo claramente) es

  1. Generar distintas valores de la gama de 1 n-[1, 2, ..., M-1].
  2. Ordene el vector resultante
  3. Agregue 0 y M como primer y último elemento del vector resultante.
  4. Generar un nuevo vector computando x i - x i-1 donde i = 1,2, ... n. Es decir, el nuevo vector está formado por las diferencias entre los elementos consecutivos del viejo vector.
  5. Divida cada elemento del nuevo vector por M. ¡Tiene la distribución uniforme!

tengo curiosidad para saber si la generación de valores aleatorios distintos y la normalización de ellos a 1 dividiendo por su suma también producirá una distribución uniforme.

0

Obtenga n números aleatorios, calcule su suma y normalice la suma en 1 dividiendo cada número con la suma.

Expanding on Kobi's answer, aquí hay una función de Java que hace exactamente eso.

public static double[] getRandDistArray(int n) { 
    double randArray[] = new double[n]; 
    double sum = 0; 

    // Generate n random numbers 
    for (int i = 0; i < randArray.length; i++) { 
     randArray[i] = Math.random(); 
     sum += randArray[i]; 
    } 

    // Normalize sum to 1 
    for (int i = 0; i < randArray.length; i++) { 
     randArray[i] /= sum; 
    } 
    return randArray; 
} 

En una prueba de funcionamiento, getRandDistArray(5) devolvió el siguiente

[0.1796505603694718, 0.31518724882558813, 0.15226147256596428, 0.30954417535503603, 0.043356542883939767] 
Cuestiones relacionadas