Взвешенная выборка без замены - PullRequest
1 голос
/ 21 ноября 2011

У меня есть популяция p индексов и соответствующих весов в векторе w.Я хочу получить k выборки из этой совокупности без замены , где отбор производится пропорционально случайным весам.

Я знаю, что randsample можно использовать для выбора с заменой, сказав

J = randsample(p,k,true,w)

, но когда я вызываю его с параметром false вместо true, Я получаю

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

Я написал свою собственную функцию как , обсуждаемую здесь :

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 уникальных столбцов матрицы, пропорциональной некоторым весовым критериям.Вот почему я использую выборку без замены.

Ответы [ 5 ]

3 голосов
/ 21 ноября 2011

Я не думаю, что можно избежать какой-то петли, поскольку выборка без замены означает, что выборки больше не являются независимыми.Кроме того, что в действительности означает взвешивание при выборке без замены?

В любом случае, для сравнительно небольших выборок я не думаю, что вы заметите какие-либо проблемы с производительностью.Все решения, которые я могу придумать, в основном делают то, что вы сделали, но, возможно, расширяете то, что происходит в randsample.

1 голос
/ 22 марта 2017

Это все еще отображается в результатах поиска, поэтому я хотел добавить функцию datasample в качестве опции. Следующий код предоставит взвешенную выборку из 5 единиц от fromVector согласно соответствующему вектору myWeights.

mySample = datasample(fromVector, 5, 'Replace', false, 'Weights', myWeights)
1 голос
/ 30 мая 2012

Я думаю, вы должны продолжать использовать for, но я предлагаю уменьшить соответствующий вес на единицу.

w(p == J(i)) = w(p == J(i)) -1;
0 голосов
/ 09 июля 2015

Если вы хотите выбрать большую часть столбцов (т. Е. K не намного меньше n), или если веса очень искажены, вы можете использовать это уточнение решения Джеффа, которое гарантирует, что каждый вызов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

При выборе 29из 30 значений с одинаковыми весами (случай, который дает наименьшее преимущество), требуется 3 или 4 итерации, по сравнению с 26 без дополнительной строки.Если веса выбираются равномерно, все равно требуется от 3 до 5 итераций по сравнению с приблизительно 80 без дополнительной строки.

Кроме того, число итераций ограничено k, однако перекошено распределение.

0 голосов
/ 04 августа 2014

Альтернативой циклическому подходу петрикора, который хорошо работает, если число выборок намного меньше, чем количество элементов, является вычисление взвешенной случайной выборки с заменой и затем удаление дубликатов.Конечно, это очень плохая идея, если число выборок 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
...