2

我正在整理一些数字分类代码。所以我输入一个数字的图像,比如“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 中几乎总是有不止一种剥猫皮的方法),而且这可能对某人构成有价值的片段。

4

2 回答 2

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);
于 2016-10-06T08:57:41.593 回答
0

以下似乎有效:

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 可能会在每次迭代时重新分配内存(实际上它总是用相同的参数维度调用)。

于 2016-10-03T16:29:28.293 回答