无需更换的加权采样

时间:2011-11-20 22:53:07

标签: matlab random-sample

我在向量p中有一个w个索引和相应的权重。我想从此群体中获取k样本而无需替换,其中选择与随机的权重成比例。

我知道randsample可以通过说

来替代选择
J = randsample(p,k,true,w)

但是当我使用参数false而不是true来调用它时,我得到了

??? Error using ==> randsample at 184
Weighted sampling without replacement is not supported.

我将自己的函数编写为discussed in here

p = 1:n;
J = zeros(1,k);
for i = 1:k
    J(i) = randsample(p,1,true,w);
    w(p == J(i)) = 0;
end

但是由于它在循环中有k次迭代,我寻求更短/更快的方法来做到这一点。你有什么建议吗?

编辑:我想随机选择与某些加权条件成比例的矩阵的k个唯一列。这就是为什么我在没有替换的情况下使用采样。

4 个答案:

答案 0 :(得分:1)

我认为你应该继续使用for,但我建议将相应的重量减少一个。

w(p == J(i)) = w(p == J(i)) -1;

答案 1 :(得分:1)

这仍显示在搜索结果中,因此我想添加datasample函数作为选项。以下代码将根据相应的向量fromVector提供来自myWeights的5个单位的加权样本。

mySample = datasample(fromVector, 5, 'Replace', false, 'Weights', myWeights)

答案 2 :(得分:0)

如果样本数远小于元素数,那么petrichor for循环方法的替代方法表现良好,可以计算带有替换的加权随机样本,然后删除重复项。当然,如果样本数k接近元素数n,这是一个非常糟糕的想法,因为这需要多次迭代,但是通过避免循环,挂钟性能通常是更好。您的里程可能会有所不同。

function I=randsample_noreplace(n,k,w)
I = sort(randsample(n, k, true, w));
while 1
    Idup = find( I(2:end)-I(1:end-1) ==0);
    if length(Idup) == 0
            break
    else
            I(Idup)=randsample(n, length(Idup), true, w);
            I = sort(I);
    end
end

答案 3 :(得分:0)

如果你想选择很大一部分列(即k不小于n),或者权重非常偏斜,你可以使用Jeff的解决方案的这种改进,这可以确保每次调用randsample产生的样本与以前的样本不同。

此外,它按照顺序返回样本,其中没有替换的真实采样将返回它们,而不是排序。

function I=randsample_noreplace(n,k,w)
I = randsample(n, k, true, w);
while 1
    [II, idx] = sort(I);
    Idup = [false, diff(II)==0];
    if ~any(Idup)
        break
    else
        w(I) = 0;            %% Don't replace samples
        Idup (idx) = Idup;   %% find duplicates in original list
        I = [I(~Idup),  (randsample(n, sum(Idup), true, w))];
    end
end

当选择具有均匀权重的30个值中的29个(给出最少利益的情况)时,需要3或4次迭代,而没有附加线的则为26次。如果均匀地选择权重,则仍需要3到5次迭代,而没有额外的行则为80左右。

此外,迭代次数以k为界,但分布是偏斜的。