Generar números aleatorios con probabilidad dada matlab
Quiero generar un número aleatorio con una probabilidad determinada pero no estoy seguro de cómo hacerlo:
necesito un numero entre 1 y 3
num = ceil(rand*3);
pero necesito valores diferentes para tener diferentes probabilidades de generar, por ejemplo.
0.5 chance of 1
0.1 chance of 2
0.4 chance of 3
Estoy seguro de que esto es sencillo, pero no se me ocurre cómo hacerlo.
La solución simple es generar un número con una distribución uniforme (usando rand
) y manipularlo un poco:
r = rand;
prob = [0.5, 0.1, 0.4];
x = sum(r >= cumsum([0, prob]));
o en una sola línea:
x = sum(rand >= cumsum([0, 0.5, 0.1, 0.4]));
Explicación
Aquí r
hay un número aleatorio distribuido uniformemente entre 0 y 1. Para generar un número entero entre 1 y 3, el truco consiste en dividir el rango [0, 1] en 3 segmentos, donde la longitud de cada segmento es proporcional a su probabilidad correspondiente. . En tu caso tendrías:
- Segmento [0, 0,5), correspondiente al número 1.
- Segmento [0.5, 0.6), correspondiente al número 2.
- Segmento [0.6, 1], correspondiente al número 3.
La probabilidad de r
caer dentro de cualquiera de los segmentos es proporcional a las probabilidades que desea para cada número. sum(r >= cumsum([0, prob]))
es sólo una forma elegante de asignar un número entero a uno de los segmentos.
Extensión
Si está interesado en crear un vector/matriz de números aleatorios, puede usar un bucle o arrayfun
:
r = rand(3); % # Any size you want
x = arrayfun(@(z)sum(z >= cumsum([0, prob])), r);
Por supuesto, también hay una solución vectorizada, pero soy demasiado vago para escribirla.
Las respuestas hasta ahora son correctas, pero lentas para entradas grandes: O(m*n) donde n es el número de valores y m es el número de muestras aleatorias. Aquí hay una versión O(m*log(n)) que aprovecha la monotonicidad del cumsum
resultado y la búsqueda binaria utilizada en histc
:
% assume n = numel(prob) is large and sum(prob) == 1
r = rand(m,1);
[~,x] = histc(r,cumsum([0,prob]));