25

我想以给定的概率生成一个随机数,但我不知道如何:

我需要一个 1 到 3 之间的数字

num = ceil(rand*3);

但我需要不同的值来产生不同的概率,例如。

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

我敢肯定这很简单,但我想不出该怎么做。

4

7 回答 7

46

简单的解决方案是生成一个具有均匀分布的数字(使用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]))只是将整数映射到其中一个段的一种奇特方式。

延期

如果您有兴趣创建随机数的向量/矩阵,可以使用循环或arrayfun

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

当然,也有矢量化的方案,就是懒得写了。

于 2012-12-17T12:24:49.210 回答
9

到目前为止的答案是正确的,但对于大型输入来说很慢:O(m*n) 其中 n 是值的数量,m 是随机样本的数量。这是一个 O(m*log(n)) 版本,它利用了cumsum结果的单调性和 中使用的二进制搜索histc

% assume n = numel(prob) is large and sum(prob) == 1
r = rand(m,1);
[~,x] = histc(r,cumsum([0,prob]));
于 2013-12-04T12:37:11.377 回答
5
>> 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根据需要分发。

于 2012-12-17T18:54:21.140 回答
5

使用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);

我认为这是最简单的方法。

于 2016-10-30T14:50:48.483 回答
4

一个稍微更通用的解决方案是:

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)
于 2012-12-17T16:24:13.623 回答
0

当概率是这样的好数字时,可以进行非常简单且高效的选择。我们重复人口元素,以便统一选择产生所需的概率分布。在这种情况下,我们创建了一个 10 的总体,5 乘以 1(被选中的概率为 0.5),等等。

p = [1,1,1,1,1,2,3,3,3,3];
x = p(randi(numel(p));

randi接受第二个输入参数,该参数确定输出的大小(默认值为 1),因此很容易从此分布生成许多值。

于 2020-07-09T02:03:45.940 回答
0

使用randcumsum和的矢量解min

r = rand(10,1);
p = [0.5 0.1 0.4];
[~, ind] = min(r >= cumsum(p), [], 2)
  • r使用 0..1 从 0..1随机采样rand。在这种情况下,我将数据放入列向量中。
  • 将每个输出索引的概率放入p.
  • r >= cumsum(p)比较 的每个组合r和 的累积概率p。在这种情况下,结果是一个二维矩阵,其中每一行以一系列 1 开始,以一系列 0 结束。第一个 0 表示该元素p是随机选择的。
  • min对所有行执行并返回第一个 0 的列索引。第三个输入min定义了计算最小值的维度。

如果要将其扩展到 的 n 维r:更改 的形状p,使其扩展到比现有的多一维r,并将该维度作为min的第三个输入。

r = rand(3, 5, 7);
p = []; 
p(1,1,1,:) = [0.5 0.1 0.4];
[~, ind] = min(r >= cumsum(p), [], 4)
于 2021-12-31T02:56:47.643 回答