【问题标题】:What happens when prob argument in sample sums to less/greater than 1?当样本中的 prob 参数总和小于/大于 1 时会发生什么?
【发布时间】:2020-05-12 02:30:19
【问题描述】:

我们知道sample 中的prob 参数用于分配权重概率。

例如,

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 参数可用于给出一个权重向量,用于获取被采样向量的元素。它们的总和不必为 1,但它们应该是非负的且不全为零。如果 replace 为真,当有超过 200 个合理可能的值时使用 Walker 的别名方法 (Ripley, 1987):这给出的结果与 R

所以它说prob 参数不需要总和为 1,但不告诉当它不和为 1 时预期什么?我不确定我是否遗漏了文档的任何部分。有人知道吗?

【问题讨论】:

  • 它们被归一化为一
  • 是的,看看输出,这也是我的想法,但在文档中的任何地方都找不到。
  • 也许在文档中使用了“probability weights”,而不仅仅是 probabilities。似乎与使用 权重向量 而非概率有关。

标签: r sample


【解决方案1】:

如前所述,权重被归一化为总和为 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 

【讨论】:

    【解决方案2】:

    好问题。文档对此并不清楚,但可以通过查看源代码来回答问题。

    如果您查看 R 代码,sample 总是调用另一个 R 函数,sample.int 如果您将单个数字 x 传递给 sample,它将使用 sample.int 创建一个整数向量小于或等于该数字,而如果x 是一个向量,则它使用sample.int 生成一个小于或等于length(x) 的整数样本,然后将其用于子集x。

    现在,如果您检查函数 sample.int,它看起来像这样:

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

    .Internal 表示任何采样都是通过调用用 C 编写的编译代码完成的:在这种情况下,它是函数 do_sample,定义为 here in src/main/random.c

    如果您查看此 C 代码,do_sample 会检查它是否已通过 prob 向量。如果不是,它会在相同权重的假设下进行采样。如果prob 存在,该函数确保它是数字而不是NA。如果prob 通过这些检查,则会生成一个指向底层双精度数组的指针,并将其传递给random.c 中名为FixUpProbs 的另一个函数,定义为here

    此函数检查prob 的每个成员,如果prob 的任何元素不是正有限双精度数,则抛出错误。然后,它通过将每个数字除以所有数字的总和来规范化数字。因此,代码中固有的 prob 总和为 1 根本没有偏好。也就是说,即使 prob 在您的输入中总和为 1,该函数仍会计算总和并将每个数字除以它。

    因此,参数命名不当。正如其他人在这里指出的那样,它应该是“权重”。公平地说,文档只说prob 应该是权重向量,而不是绝对概率。

    所以我阅读代码时prob参数的行为应该是:

    1. prob 可以完全不存在,在这种情况下,采样默认为相等的权重。
    2. 如果prob 的任何数字小于零、无穷大或NA,函数将抛出异常。
    3. 如果任何prob 值不是数字,则应引发错误,因为在传递给C 代码的SEXP 中它们将被解释为NA
    4. prob 的长度必须与 x 相同,否则 C 代码会抛出
    5. 如果您指定了replace=T,则可以将零概率作为prob 的一个或多个元素传递,只要您至少有一个非零概率。
    6. 如果您指定replace=F,则您请求的样本数必须小于或等于prob 中的非零元素数。从本质上讲,如果您要求FixUpProbs 以零概率采样,它将抛出。
    7. 有效的prob 向量将被归一化为总和为 1 并用作采样权重。

    作为这种行为的一个有趣的副作用,如果您通过设置 probs = c(1, odds) 在 2 个备选方案之间进行选择,这允许您使用赔率而不是概率

    【讨论】:

    • 感谢您提供经过充分研究的答案。关于你最后的总结,特别是第 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 中所述。因此,replace = FALSE 的一个(或多个但不是全部)值的概率为 0 是可以的?
    • 好点@RonakShah。实际上,只有在强制以零概率采样时才会抛出。所以你可能可以做sample(1:4, 2, prob = c(0, 0, 2, 3), replace = F),但是如果你指定n=3,那么一旦样本中出现了3和4,它将尝试以0的概率对1或2进行采样并抛出。目前无法测试...
    • @RonakShah 我现在已经对其进行了测试,这确实是行为。答案已更新。
    猜你喜欢
    • 2016-01-26
    • 2020-11-13
    • 2022-01-21
    • 2021-05-13
    • 2016-06-19
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多