Как случайным образом поднять числа N с вектора a
с весом, присвоенным каждому числу?
Скажем:
a = 1:3; % possible numbers
weight = [0.3 0.1 0.2]; % corresponding weights
В этой вероятности случая для взятия 1 должно быть в 3 раза выше, чем взять 2.
Сумма всех весов может быть чем-либо.
R = randsample([1 2 3], N, true, [0.3 0.1 0.2])
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 )
Пояснение:
Рассмотрим интервал [0,1]. Мы назначаем каждому элементу в списке ( 1: 3
) подинтервал длины, пропорциональной весу каждого элемента; поэтому 1
get и интервал длины 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%
, которая более или менее соответствует нормализованным весам w./sum (w)
[0,5 0,16667 0,33333]
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
Однако для большой задачи такого размера, который я предложил выше, это быстро.
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.
По общему признанию, моя версия требует для написания 2 строчки. Операция индексации должна выполняться во второй строке, поскольку она использует второй вывод histc. Также обратите внимание, что я использовал возможности новой версии Matlab с оператором тильды (~) в качестве первого аргумента histc. Это приводит к тому, что первый аргумент немедленно выгружается в битовое ведро.