Générer un nombre aléatoire avec une probabilité donnée matlab
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 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 à la façon de le faire.
5 réponses
la solution simple est de générer un nombre avec une distribution uniforme (en utilisant rand
), et le manipuler un peu:
r = rand;
prob = [0.5, 0.1, 0.4];
x = sum(r >= cumsum([0, prob]));
ou dans un one-liner:
x = sum(rand >= cumsum([0, 0.5, 0.1, 0.4]));
Explication
Ici r
est un chiffre aléatoire uniformément distribué entre 0 et 1. Pour générer un nombre entier entre 1 et 3, le truc est de diviser l'intervalle [0, 1] en 3 segments, où la longueur de chaque segment est proportionnelle à son correspondant probabilité. Dans votre cas, vous devez:
- 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é de r
à l'intérieur de l'un des segments est proportionnelle aux probabilités que vous voulez pour chaque nombre. sum(r >= cumsum([0, prob]))
est juste une façon élégante de mappage d'un nombre entier à l'un des segment.
Extension
si vous êtes intéressé à 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.
Les réponses sont correctes, mais lent pour les grandes entrées: 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 profit de la monotonie de la cumsum
résultat et 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]));
>> 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 souhaité.
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)
en utilisant randsample
function boîte à outils de statistiques et D'apprentissage automatique, vous pouvez générer des nombres aléatoires avec la fonction de masse de probabilité (pmf) spécifiée:
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.