2011-04-11 22 views
5

En algún código quiero elegir n números aleatorios en [0,1) que suman 1.Elegir n números con suma fija

lo hago por la elección de los números de forma independiente en [0,1) y la normalización de ellas dividiendo cada uno por la suma total:

numbers = [random() for i in range(n)] 
numbers = [n/sum(numbers) for n in numbers] 

Mi "problema" es decir, que la distribución salgo es bastante asimétrica. Elegir un millón de números, ni uno solo, supera el 1/2. Por algún esfuerzo he calculado el pdf, y no es bueno.

Aquí es el pdf de aspecto extraño que me pasa por 5 variables:

enter image description here

¿Tiene una idea para un buen algoritmo para elegir los números, que se traducen en una mayor distribución uniforme o simple?

+5

No estoy seguro de entender, si se divide el número 1 en un millón de piezas al azar, _debería_ no ser una que supere el 0,5. Si hubiera, eso significaría que los otros 999.999 tendrían que caber en la otra mitad. – DShook

+0

posible duplicado de [Generar múltiples números aleatorios para igualar un valor en python] (http://stackoverflow.com/questions/3589214/generate-multiple-random-numbers-to-equal-a-value-in-python) –

Respuesta

15

que busca para dividir la distancia de 0 a 1.

Elija n - 1 números de 0 a 1, clasificarlos y determinar las distancias entre cada uno de ellos.

Esto dividirá el espacio de 0 a 1, lo que debería dar lugar a grandes resultados ocasionales que no se obtienen.

Aún así, para valores grandes de n, generalmente puede esperar que su valor máximo también disminuya, pero no tan rápido como su método.

+1

Un encantador algoritmo. ¿Sabes en qué distribución puede resultar esto? –

+0

Aparte de llamarlo una "partición aleatoria", no sé cómo referirme a ella. Siempre lo he visto desde el lado de la partición de las cosas, no desde la distribución de las longitudes de los segmentos. – LanceH

+0

He deducido el cdf '1- (1-x)^n' y pmf' n (1-x)^(n-1) '. La distribución tiende a tener una mayor probabilidad de pequeños números (no tiene el pico cerca de 1/n) que la mía, por lo que probablemente también tenga más números grandes. Todavía no lo he comparado con la distribución de Dirichlet. –

4

Eche un vistazo a Random Vectors with Fixed Sum. El enlace de descarga lleva a un archivo con código MATLAB y un documento que explica el algoritmo.

+0

Esto parece ser un caso general en el que cada 'xi' está restringido' a <= xi <= b'. –

4

Puede que le interese el Dirichlet distribution que se utiliza para generar cantidades que suman 1 si está buscando probabilidades. También hay una sección sobre cómo generarlos utilizando distribuciones gamma here.

+0

Por lo general, necesita una distribución que no sea uniforme para extraer sus números. Como sugiere la respuesta del trabajo, puede usar la distribución Gamma con alfa <1 para obtener resultados "pico". Si lo hace, le dará un sorteo de la distribución de Dirichlet que es conveniente, ya que es el conjugado anterior al multinomial que busca. –

+0

El artículo tiene una buena sección de "dibujo", a la que he agregado algunos ejemplos de código. No estoy seguro si importa cuáles son los parámetros, ¿y si son iguales? –

0

Otra forma de obtener n números aleatorios que suman hasta 1:

import random 


def create_norm_arr(n, remaining=1.0): 
    random_numbers = [] 
    for _ in range(n - 1): 
     r = random.random() # get a random number in [0, 1) 
     r = r * remaining 
     remaining -= r 
     random_numbers.append(r) 
    random_numbers.append(remaining) 
    return random_numbers 

random_numbers = create_norm_arr(5) 
print(random_numbers) 
print(sum(random_numbers)) 

Esto hace que un mayor número más probable.

Cuestiones relacionadas