MATLAB中的加权随机数

yuk*_*yuk 17 random matlab

如何从向量中随机选取N个数字,a并为每个数字分配权重?

让我们说:

a = 1:3; % possible numbers
weight = [0.3 0.1 0.2]; % corresponding weights
Run Code Online (Sandbox Code Playgroud)

在这种情况下,拾取1的概率应该比拾取2的概率高3倍.

所有权重的总和可以是任何东西.

Amr*_*mro 39

R = randsample([1 2 3], N, true, [0.3 0.1 0.2])
Run Code Online (Sandbox Code Playgroud)

randsample包含在统计工具箱中


否则你可以使用某种轮盘选择过程.看到这个类似的问题(虽然不是MATLAB特定的).这是我的一行实现:

a = 1:3;             %# possible numbers
w = [0.3 0.1 0.2];   %# corresponding weights
N = 10;              %# how many numbers to generate

R = a( sum( bsxfun(@ge, rand(N,1), cumsum(w./sum(w))), 2) + 1 )
Run Code Online (Sandbox Code Playgroud)

说明:

考虑区间[0,1].我们为list(1:3)中的每个元素分配一个长度与每个元素的权重成比例的子区间; 因此,1获取和长度的区间0.3/(0.3+0.1+0.2),同为别人.

现在,如果我们生成一个均匀分布超过[0,1]的随机数,那么[0,1]中的任何数字都有相同的被选概率,因此子区间的长度决定了随机数落入的概率.每个间隔.

这符合我上面所做的:选择一个数字X~U [0,1](更像是N数字),然后找到它以矢量化方式落入的间隔.


您可以通过生成足够大的序列来检查上述两种技术的结果N=1000:

>> tabulate( R )
  Value    Count   Percent
      1      511     51.10%
      2      160     16.00%
      3      329     32.90%
Run Code Online (Sandbox Code Playgroud)

它或多或少与标准化权重相匹配 w./sum(w) [0.5 0.16667 0.33333]


小智 16

amro给出了一个很好的答案(我对其进行了评分),但如果您希望从大型集合中生成许多数字,那么它将非常密集.这是因为bsxfun操作可以生成一个巨大的数组,然后将其求和.例如,假设我有一组10000个值来取样,所有都有不同的权重?现在,从该样本生成1000000个数字.

这将需要做一些工作,因为它将在内部生成10000x1000000数组,其中包含10 ^ 10个元素.它将是一个逻辑阵列,但即便如此,必须分配10千兆字节的内存.

更好的解决方案是使用histc.从而...

a = 1:3
w = [.3 .1 .2];
N = 10;

[~,R] = histc(rand(1,N),cumsum([0;w(:)./sum(w)]));
R = a(R)
R =
     1     1     1     2     2     1     3     1     1     1
Run Code Online (Sandbox Code Playgroud)

但是,对于我上面建议的大型问题,它很快.

a = 1:10000;
w = rand(1,10000);
N = 1000000;

tic
[~,R] = histc(rand(1,N),cumsum([0;w(:)./sum(w)]));
R = a(R);
toc
Elapsed time is 0.120879 seconds.
Run Code Online (Sandbox Code Playgroud)

不可否认,我的版本需要2行才能编写.索引操作必须在第二行上进行,因为它使用histc的第二个输出.另请注意,我使用了新matlab版本的功能,使用波浪号(〜)运算符作为histc的第一个参数.这会导致第一个参数立即转储到位桶中.

  • @woodcihps,谢谢你的好解决方案.顺便说一句,Amro建议的RANDSAMPLE函数也使用histc方法. (2认同)