Что происходит, когда prob аргумент в выборке суммируется с меньшим / большим, чем 1?

#r #floating-point

#r #пример

Вопрос:

Мы знаем, что prob аргумент in sample используется для присвоения вероятности весов.

Например,

 table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6

#  1   2   3   4 
#0.2 0.4 0.3 0.1 


table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6

#    1     2     3     4 
#0.200 0.400 0.299 0.100 
  

В этом примере сумма вероятностей точно 1 (0.2 0.4 0.3 0.1), следовательно, это дает ожидаемое соотношение, но что, если вероятность не равна 1? Какой результат это даст? Я думал, что это приведет к ошибке, но это дает некоторое значение.

Когда вероятность суммируется с большим, чем 1.

 table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6

#     1      2      3      4 
#0.1544 0.3839 0.3848 0.0768 

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6

#     1      2      3      4 
#0.1544 0.3842 0.3848 0.0767 
  

Когда вероятность суммируется с меньшим, чем 1

 table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6

#    1     2     3     4 
#0.124 0.125 0.625 0.125 

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6

#    1     2     3     4 
#0.125 0.125 0.625 0.125 
  

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

Я попытался выполнить поиск в Интернете, но не нашел никакой соответствующей информации. Я просмотрел документацию, в ?sample которой есть

Необязательный аргумент prob может использоваться для задания вектора весов для получения элементов выбираемого вектора. Они не должны суммироваться с единицей, но они должны быть неотрицательными, а не полностью равными нулю. Если replace имеет значение true, метод псевдонимов Уолкера (Ripley, 1987) используется, когда имеется более 200 разумно вероятных значений: это дает результаты, несовместимые с результатами из R < 2.2.0.

Итак, он говорит, что prob аргумент не должен суммироваться с 1, но не сообщает, что ожидается, когда он не суммируется с 1? Я не уверен, что мне не хватает какой-либо части документации. У кого-нибудь есть идеи?

Комментарии:

1. Они нормализуются для суммирования до единицы

2. Да, глядя на результат, я тоже так думаю, но не смог найти его нигде в документации.

3. возможно, использование «весов вероятности » вместо просто вероятностей в документах. Кажется уместным, что вектор весов используется, а не вероятности.

4. researchgate.net/post/…

Ответ №1:

Хороший вопрос. В документах неясно, но на этот вопрос можно ответить, просмотрев исходный код.

Если вы посмотрите на код R, sample всегда вызывает другую функцию R, sample.int если вы передаете одно число x в sample , оно будет использоваться sample.int для создания вектора целых чисел, меньших или равных этому числу, тогда как if x — вектор, он используется sample.int для генерации выборки целых чисел, меньших или равных length(x) ,затем использует это для подмножества x.

Теперь, если вы изучите функцию sample.int , она выглядит так:

 function (n, size = n, replace = FALSE, prob = NULL, useHash = (!replace amp;amp; 
    is.null(prob) amp;amp; size <= n/2 amp;amp; n > 1e 07)) 
{
    if (useHash) 
        .Internal(sample2(n, size))
    else .Internal(sample(n, size, replace, prob))
}
  

Это .Internal означает, что любая выборка выполняется путем вызова скомпилированного кода, написанного на C: в данном случае это функция do_sample , определенная здесь в src /main /random.c .

Если вы посмотрите на этот C-код, do_sample проверяет, был ли ему передан prob вектор. Если нет, то выполняется выборка в предположении о равных весах. Если prob существует, функция гарантирует, что он числовой, а не NA . Если prob проходит эти проверки, генерируется указатель на базовый массив double и передается другой функции в random.c вызывается FixUpProbs , определяется здесь .

Эта функция проверяет каждый элемент prob и выдает ошибку, если какие-либо элементы prob не являются положительными конечными двойниками. Затем он нормализует числа, деля каждое на сумму всех. Поэтому нет никакого предпочтения для prob суммирования до 1, присущего коду. То есть, даже если prob на ваших входных данных сумма равна 1, функция все равно вычислит сумму и разделит на нее каждое число.

Поэтому параметр неправильно назван. Это должны быть «веса», как указывали другие здесь. Честно говоря, в документах говорится только, что это prob должен быть вектор весов, а не абсолютных вероятностей.

Таким образом, поведение prob параметра из моего чтения кода должно быть:

  1. prob может отсутствовать вообще, и в этом случае выборка по умолчанию имеет равные веса.
  2. Если какое prob -либо из чисел меньше нуля, или бесконечно, или NA, функция выдаст.
  3. Должна быть выдана ошибка, если какое-либо из prob значений нечисловое, поскольку они будут интерпретироваться как NA в SEXP, переданном в код C.
  4. prob должен иметь ту же длину, x что и или выдает код C
  5. Вы можете передать нулевую вероятность как один или несколько элементов prob , если вы указали replace=T , если у вас есть хотя бы одна ненулевая вероятность.
  6. Если вы укажете replace=F , количество запрашиваемых вами выборок должно быть меньше или равно количеству ненулевых элементов в prob . По сути, FixUpProbs он будет выдан, если вы попросите его выполнить выборку с нулевой вероятностью.
  7. Допустимый prob вектор будет нормализован для суммирования до 1 и использоваться в качестве весов выборки.

В качестве интересного побочного эффекта такого поведения это позволяет вам использовать коэффициенты вместо вероятностей, если вы выбираете между 2 альтернативами, устанавливая probs = c(1, odds)

Комментарии:

1. Спасибо за очень хорошо проработанный ответ. Что касается вашего резюме в конце, в частности, пункта 5). sample(1:4, 1, prob = c(0, 2, 3, 4)) похоже, работает так же хорошо, как table(replicate(1e6, sample(1:4, 1, prob = c(0, 2, 3, 4)))) replace = FALSE и с. Как упоминалось в документах They need not sum to one, but they should be non-negative and not all zero . Так что нормально иметь вероятность равной 0 для одного (или более, но не для всех) значения с replace = FALSE ?

2. Хорошая мысль @RonakShah. На самом деле, он будет выдавать только в том случае, если он вынужден выполнять выборку с вероятностью нуля. Вероятно, вы можете это сделать sample(1:4, 2, prob = c(0, 0, 2, 3), replace = F) , но если вы укажете n = 3, то после того, как в выборке присутствуют 3 и 4, он попытается выполнить выборку 1 или 2 с вероятностью 0 и выбросить. В настоящее время не могу это проверить…

3. @RonakShah Я проверил это сейчас, и это действительно поведение. Ответ обновлен.

Ответ №2:

Как уже упоминалось, веса нормализуются для суммирования до 1, что можно продемонстрировать:

 > x/sum(x)
[1] 0.15384615 0.38461538 0.38461538 0.07692308
  

Это соответствует вашим смоделированным табличным данным:

 #     1      2      3      4 
#0.1544 0.3839 0.3848 0.0768