【问题标题】:Iterative or Lazy Reservoir Sampling迭代或惰性油藏采样
【发布时间】:2014-08-02 02:05:42
【问题描述】:

我非常熟悉使用 Reservoir Sampling 在单次遍历数据中从一组未确定的长度中进行采样。在我看来,这种方法的一个限制是,在返回任何结果之前,它仍然需要遍历整个数据集。从概念上讲,这是有道理的,因为必须允许整个序列中的项目有机会替换以前遇到的项目以实现统一的样本。

有没有办法在整个序列被评估之前产生一些随机结果?我正在考虑一种适合 python 的伟大 itertools 库的惰性方法。也许这可以在某些给定的容错范围内完成?如有任何关于此想法的反馈,我将不胜感激!

为了稍微澄清一下这个问题,这张图总结了我对不同采样技术的内存与流式权衡的理解。我想要的是属于 Stream Sampling 类别的东西,我们事先不知道人口的长度。

显然,不知道先验长度并仍然获得统一样本似乎是矛盾的,因为我们很可能会将样本偏向于总体的开始。有没有办法量化这种偏见?是否需要权衡取舍?有人有聪明的算法来解决这个问题吗?

【问题讨论】:

  • 您可以这样做,但这样做会失去生成某些序列的能力。例如,如果您想从列表中随机选择 10 件商品,但您对一件或多件商品进行了某种类型的提前退货,那么您的样本将永远不会包含列表中的最后 10 件商品。如果您可以对输出进行偏置,那么您可以提前返回。否则,您必须等到检查完整个列表。
  • 实现水库采样会更有意义,以便它始终迭代其整个可迭代对象。如果调用者想要一个更快的结果而不迭代其整个可迭代对象,它可以传入截断的可迭代对象本身。产生可迭代的储层没有多大意义,因为连续的储层高度相关(它们在 0 或 1 个位置上不同)。
  • @TimothyShields 我同意 API 设计方面的看法,人们会并且应该期望储层样本具有这种行为方式。我在这里寻找的是某种类似的统计上的聪明才智,它可以让我们提前归还物品,或者一些很好的论据,说明为什么这根本不可能。
  • @Stankalank 出于什么目的提前退货?请参阅我之前评论中的最后一句话。
  • @TimothyShields 假设我们有一个大小为 100 的群体,我们想要一个大小为 15 的样本。人们可以很容易地设计一种算法,将群体保存在内存中并从样本中流式传输(迭代地产生)项目.或者,如果我们要使用水库采样,我们会将样本保存在内存中并流式传输总体。我想要一种同时传输人口和样本的方法。 ALA 此图:littleml.files.wordpress.com/2013/01/memory.png

标签: python algorithm random reservoir-sampling


【解决方案1】:

如果您事先知道可迭代population 将产生的项目总数,则可以在遇到population 样本的项目时产生它们(不仅在到达末尾之后)。如果您不提前知道总体规模,这是不可能的(因为无法计算任何项目在样本中的概率)。

这是一个执行此操作的快速生成器:

def sample_given_size(population, population_size, sample_size):
    for item in population:
        if random.random() < sample_size / population_size:
            yield item
            sample_size -= 1
        population_size -= 1

请注意,生成器按照它们在总体中出现的顺序生成项目(不是随机顺序,如 random.sample 或大多数水库采样代码),因此样本的一部分不会是随机子样本!

【讨论】:

  • 这是一个真正的流式水库样本,非常好。在事先不知道人口规模的情况下,这可能吗?
  • @Stankalank:不。想想人口中的第一个元素:如果我们不允许“改变”从样本中包含或排除它的决定(作为“流输出”算法暗示),除非我们知道人口规模,否则我们到底应该如何知道包含它的概率?
  • @Stankalank,不,提前知道尺寸很重要。简化这一点,您会更容易看到它:将您的问题限制为选择大小为 1 的样本。您应该能够轻松地说服自己,在不事先知道人口规模的情况下,您不仅不能尽早切断它,您甚至无法提出具有任何实际价值的“近似值”。当样本量超过 1 时,它不会变得更容易 ;-)
  • 如果您事先假设错误的人口规模,您的结果会不会完全错误(统计上的偏差)? (不考虑人口规模意味着使用不同的概率公式,这相当于假设一定人口规模。)
  • @TimPeters 当我问这个问题时,我完全理解了问题陈述中看似矛盾的地方。但是,在我发现比我聪明得多的人发明了一种算法之前,我也曾认为在单程中进行随机样本(水库样本)是不可能的。我想知道这些同样聪明的人是否有类似的流采样解决方案=)
【解决方案2】:

如果事先知道人口规模,你不能只生成 sample_size 随机“指数”(在流中)并用它来做一个惰性产量吗?您不必阅读整个信息流。

例如,如果 population_size 为 100,sample_size 为 3,您会生成一个从 1 到 100 的随机整数集,例如您得到 10、67 和 72。

现在您生成流的第 10、62 和 72 个元素并忽略其余元素。

我想我不明白这个问题。

【讨论】:

  • 如果人口规模是先验已知的,那么问题就相当简单了,请参阅公认的解决方案。我正在考虑一个长度为 unknown 的数据流,我们希望在其中同时传输总体和样本。不幸的是,我似乎从其他答案中得到的是,这实际上是不可能的。
猜你喜欢
  • 1970-01-01
  • 2016-05-21
  • 2011-01-16
  • 2012-09-20
  • 2016-04-26
  • 2012-06-28
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多