【问题标题】:Efficient binary sampling from vector of probability distribution vectors in MatLabMatLab中概率分布向量向量的高效二进制采样
【发布时间】:2023-05-27 04:30:02
【问题描述】:

我正在整理一些数字分类代码。所以我输入一个数字的图像,比如“7”,然后我得到 10 个概率(即总和为 1)。如果我的算法运行良好,第 7 个元素的值应该最高。

另外一个复杂之处是我正在处理 100 个元素的批次。所以我实际上有一个 COLxROW = 100x10 MATRIX,其中每行总和为 1。

现在我希望从这 100 个分布中的每一个中进行采样,即我需要根据我的概率为每个批次项目生成一个类似于 [0 0 0 1 0 0 0 0 0 0] 的向量(即 3)分布。

现有的实现是:

samp = pd*0;
layers = cumsum( pd, 2 );
randoms = rand( batchSize, 1 );
for k = 1:batchSize
    index = find( randoms(k) <= layers(k,:),  1 );
    samp( k, index ) = 1;
end

但是我更愿意避免显式循环(正如我所读的那样,它通常会导致性能不佳)。

效率是关键,因为此例程在最紧凑的循环中执行。

如何有效地做到这一点?

编辑我将尝试回答我的问题,如果有人可以改进答案,我会发布(在 MatLab 中几乎总是有不止一种方法可以给猫剥皮),​​而且这可能构成一个有价值的 sn- p 给某人。

【问题讨论】:

    标签: matlab performance processing-efficiency probability-distribution


    【解决方案1】:

    这是一种避免循环的方法:

    % preparing some data:
    batchSize = 100;
    probs = [ones(1,9)*0.01 0.9];
    pd = zeros(batchSize,10);
    for k = 1:batchSize
        pd(k,:) = probs(randperm(10));
    end
    
    % the actual answer:
    layers = cumsum(pd,2);
    randoms = rand(batchSize,1);
    index = 11-cumsum((layers-repmat(randoms,1,10))>0,2);
    samp = bsxfun(@eq,index(:,end),1:10);
    

    【讨论】:

      【解决方案2】:

      以下似乎有效:

      function sample = sampleFromPDs( pd )
          [batchSize_, nOutputs] = size( pd );
      
          bools = cumsum(pd,2) > repmat( rand(batchSize_,1), 1, nOutputs );
      
          % e.g. 001 111 gives (6+1) - 4 = 3
          indexOfFirstONE = (nOutputs+1) - sum(bools, 2);
      
          sample = 0 .* pd;  
          sample( ...
              sub2ind( size(pd), 1:batchSize_, indexOfFirstONE' ) ...
              ) = 1;    
      end
      

      但是,我有点担心 MatLab 可能会在每次迭代时重新分配内存(实际上它总是使用相同的参数维度调用)。

      【讨论】: