web-dev-qa-db-fra.com

Générer un nombre aléatoire avec un matlab de probabilité donné

Je veux générer un nombre aléatoire avec une probabilité donnée mais je ne sais pas comment:

J'ai besoin d'un nombre entre 1 et 3

num = ceil(Rand*3);

mais j'ai besoin de valeurs différentes pour avoir différentes probabilités de générer par exemple.

0.5 chance of 1
0.1 chance of 2
0.4 chance of 3

Je suis sûr que c'est simple mais je ne peux pas penser à comment le faire.

25
Eamonn McEvoy

La solution simple est de générer un nombre avec une distribution uniforme (en utilisant Rand ), et de le manipuler un peu:

r = Rand;
prob = [0.5, 0.1, 0.4];
x = sum(r >= cumsum([0, prob]));

ou en monoplace:

x = sum(Rand >= cumsum([0, 0.5, 0.1, 0.4]));

Explication

Ici r est un nombre aléatoire uniformément réparti entre 0 et 1. Pour générer un nombre entier entre 1 et 3, l'astuce consiste à diviser la plage [0, 1] en 3 segments, où la longueur de chaque segment est proportionnelle à sa probabilité correspondante. Dans votre cas, vous auriez:

  • Segment [0, 0,5), correspondant au numéro 1.
  • Segment [0,5, 0,6), correspondant au numéro 2.
  • Segment [0,6, 1], correspondant au numéro 3.

La probabilité que r tombe dans l'un des segments est proportionnelle aux probabilités que vous souhaitez pour chaque nombre. sum(r >= cumsum([0, prob])) n'est qu'un moyen sophistiqué de mapper un nombre entier à l'un des segments.

Extension

Si vous souhaitez créer un vecteur/matrice de nombres aléatoires, vous pouvez utiliser une boucle ou arrayfun :

r = Rand(3); % # Any size you want
x = arrayfun(@(z)sum(z >= cumsum([0, prob])), r);

Bien sûr, il y a aussi une solution vectorisée, je suis juste trop paresseux pour l'écrire.

46
Eitan T

Jusqu'à présent, les réponses sont correctes, mais lentes pour les entrées de grande taille: O (m * n) où n est le nombre de valeurs et m est le nombre d'échantillons aléatoires. Voici une version O (m * log (n)) qui tire parti de la monotonie du résultat cumsum et de la recherche binaire utilisée dans histc:

% assume n = numel(prob) is large and sum(prob) == 1
r = Rand(m,1);
[~,x] = histc(r,cumsum([0,prob]));
9
Alec Jacobson
>> c = cumsum([0.5, 0.1, 0.4]);
>> r = Rand(1e5, 1);
>> x = arrayfun(@(x) find(x <= c, 1, 'first'), r);
>> h = hist(x, 1:3)

h =

       49953       10047       40000

x distribué comme vous le souhaitez.

5
Serg

en utilisant la fonction randsample de Statistics and Machine Learning Toolbox, vous pouvez générer des nombres aléatoires avec une fonction de masse de probabilité spécifiée (pmf):

pmf = [0.5, 0.1, 0.4];
population = 1:3;
sample_size = 1;

random_number = randsample(population,sample_size,true,pmf);

Je pense que c'est la méthode la plus simple.

5
MohammadReza

Une solution un peu plus générale serait:

r=Rand;
prob=[.5,.1,.4];
prob=cumsum(prob);
value=[1,2,3];    %values corresponding to the probabilities
ind=find(r<=prob,1,'first');
x=value(ind)
4
user1860611