web-dev-qa-db-ja.com

与えられた確率matlabで乱数を生成します

与えられた確率で乱数を生成したいのですが、どうすればいいのかわかりません:

1〜3の数字が必要です

num = ceil(Rand*3);

しかし、生成する確率が異なるためには、異なる値が必要です。

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

これは簡単だと確信していますが、どうすればいいのか考えられません。

25
Eamonn McEvoy

簡単な解決策は、( Rand を使用して)均一な分布で数値を生成し、それを少し操作することです。

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

またはワンライナーで:

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

説明

ここで、rは0〜1の一様分布乱数です。1〜3の整数を生成するには、[0、1]の範囲を3つのセグメントに分割します。各セグメントの長さは対応する確率に比例します。あなたの場合、あなたが持っているでしょう:

  • セグメント[0、0.5)、番号1に対応。
  • セグメント[0.5、0.6)、番号2に対応。
  • セグメント[0.6、1]、番号3に対応。

rがセグメントのいずれかに収まる確率は、各数値に必要な確率に比例します。 sum(r >= cumsum([0, prob]))は、整数をセグメントの1つにマッピングするだけの派手な方法です。

拡張

乱数のベクトル/行列の作成に関心がある場合は、ループまたは arrayfun を使用できます。

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

もちろん、ベクトル化されたソリューションもあります。私はそれを書くのが面倒です。

46
Eitan T

これまでの答えは正しいですが、入力が大きい場合は遅くなります。O(m * n)ここで、nは値の数で、mはランダムサンプルの数です。 cumsumの結果の単調性とhistcで使用されるバイナリ検索を利用するO(m * log(n))バージョンを次に示します。

% 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は必要に応じて配布されます。

5
Serg

Statistics and Machine Learning Toolboxrandsample関数を使用すると、指定された確率質量関数(pmf)で乱数を生成できます。

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

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

これが最も簡単な方法だと思います。

5
MohammadReza

もう少し一般的な解決策は次のとおりです。

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