PySpark 比例分层抽样 "sampleBy"

PySpark Proportionate Stratified Sampling "sampleBy"

问题:如果使用PySpark的sampleBy实现比例分层抽样,不就是随机抽样吗?

编辑:有成比例不成比例分层抽样。这个问题是关于前者的。

这是我对此的看法:

假设您在总人数 N = 1000 的人群中有 4 个组。这些组的比例为:

A:25%,B:50%,C:13%,D:12%

然后选择一个大小为 100 的比例分层样本意味着选择一个样本正好由 A 中的 25 个元素、B 中的 50 个元素、C 中的 13 个元素和 D 中的 12 个元素组成。(注意:不成比例的分层样本将是如果您的抽样率与总体抽样率不同。)

这与进行随机抽样形成对比,其中 A、B、C 和 D 的预期元素数分别为 25、50、13 和 12。

通过 sampleBy 方法在 PySpark 中实现比例分层抽样是很自然的

fractions = {'A': .1, 'B': .1, 'C': .1, 'D': .1}

如果此方法准确采样,您将分别有 25、50、13 和 12 个元素。但是,此方法是通过伯努利试验(抛硬币)实现的。对于分层抽样,由于所有分数都相同,因此每个元素的选择概率为 10%。

在这种情况下,先按层再按元素进行伯努利试验与对整个数据集进行伯努利试验是一样的。后者只是随机抽样。

结论:分层抽样在此范例中是“不可能的”。 这样理解正确吗?

我看过一些关于使用特殊技巧进行精确采样的 post。我会看看我是否可以使用下面的这些方法 (3) 回答我自己的 post。

注意:有一个 sampleByKeyExact 方法,但在 Python 中不受支持,如果支持,性能和扩展损失也不理想。

https://spark.apache.org/docs/2.2.0/mllib-statistics.html

相关帖子:

  1. Spark 中的分层抽样(提到 sampleByKeyExact Python 不支持)

  2. Investopedia 参考 https://www.investopedia.com/terms/stratified_random_sampling.asp

  3. 一种创造性的解决方法,使用可能有效的附加列。 pyspark - how to select exact number of records per strata using (df.sampleByKey()) in stratified random sampling

我认为这里存在一些与标准定义相关的混淆。通常当有人说“分层抽样”时,他们的意思是不同的 classes 应该得到不同的概率。在上面发布的示例中

A:25%,B:50%,C:13%,D:12%

一个标准的分层样本将给出分数,以确保在预期中样本将具有相同数量的 A、B、C、D。例如

fractions = {'A': .2, 'B': .1, 'C': 0.1*50/13, 'D': 0.1*50/12}

应该在每个 class.

中给出 5 个元素

在上面给出的例子中

fractions = {'A': .1, 'B': .1, 'C': 0.1, 'D': 0.1}

行为确实与比例为 0.1 的简​​单 sample 相同。

真正的问题是,你的目标是什么?如果您希望您的样本具有与原始样本 完全 相同比例的 classes,那么 samplesampleByKey 都不会提供。查看文档,似乎 sampleByKeyExact 确实可以解决问题。

编辑详细说明 samplesampleByKey 的行为: 对于 sample,map 操作基本上遍历每个元素,并根据随机变量决定是否保留该项目(以及在 withReplacement == True 的情况下保留多少份)。这个随机变量在所有元素中都是 i.i.d。在 sampleByKey 中,随机变量是独立的,但具有基于键值的不同分布,或者更准确地说,基于 fractions 参数中的相应值。如果 fractions 中的值相同,则此随机变量将对所有键值具有相同的分布 - 这就是 samplesampleByKey.

的行为变得相同的原因