【问题标题】:Generate random number with given probability matlab生成具有给定概率matlab的随机数
【发布时间】:2012-12-04 13:02:24
【问题描述】:

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

我需要一个介于 1 和 3 之间的数字

num = ceil(rand*3);

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

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

我确信这很简单,但我想不出该怎么做。

【问题讨论】:

标签: matlab math random probability


【解决方案1】:

简单的解决方案是生成一个均匀分布的数字(使用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);

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

【讨论】:

  • 感谢您的帮助,在这种情况下,当概率为 [0,0,1] 时我可以做些什么,我需要答案为 3,但继续得到 1?
  • PS:你忘了在这一行加上 0 -> x = sum(rand >= cumsum([0.5, 0.1, 0.4));
  • @EamonnMcEvoy 谢谢,已修复。
  • 矢量化解:sum(bsxfun(@ge, r, cumsum([0, prob]),2) 其中r 是列向量,prob 是行向量。
  • @OlegKomarov 感谢矢量化解决方案 ;)
【解决方案2】:

到目前为止的答案是正确的,但对于大型输入来说速度很慢: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]));

【讨论】:

  • 小注意,取决于histc 的实现方式,这可能是 O(n+m*log(n))。虽然我希望因为第一个输出没有被使用,但事实并非如此。
  • 使用Alias Method 有一个更好的 O(n + m) 解决方案。我已经在sample_discrete.m 函数中实现了它。
  • 链接已损坏,仅供参考。
【解决方案3】:
>> 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 按需分发。

【讨论】:

  • @EitanT,我不认为sum()find(..., 'first') 快​​。此外,不需要添加零。请测试一下。在一般情况下,我只会添加:assert(c(end) == 1);
  • 现在想想,我的评论不合适。我很抱歉。
【解决方案4】:

使用 Statistics and Machine Learning Toolbox 中的randsample 函数,您可以生成具有指定概率质量函数 (pmf) 的随机数:

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

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

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

【讨论】:

    【解决方案5】:

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

    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)
    

    【讨论】:

      【解决方案6】:

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

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

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

      【讨论】:

        【解决方案7】:

        使用randcumsummin 的矢量解决方案。

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

        如果要将其扩展到r 的 n 维:更改 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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-05-18
          • 2016-01-06
          • 2012-02-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多