【问题标题】:How do I get an unbiased random sample from a really huge data set?如何从非常庞大的数据集中获得无偏的随机样本?
【发布时间】:2013-04-03 21:36:31
【问题描述】:

对于我正在开发的应用程序,我需要从一个非常大的数据集中抽取一小部分值,从大约 60 万亿(并且还在不断增长)中抽取大约几百个值。

通常我使用查看均匀随机数 r (0..1) 是否小于 S/T 的技术,其中 S 是我仍然需要的样本项数,T 是我还没有考虑过的设置。

但是,有了这些新数据,我没有时间为每个值掷骰子;太多了。相反,我想生成随机数量的条目以“跳过”,在下一个位置选择值,然后重复。这样我就可以掷骰子并访问列表 S 次。 (S是我想要的样本大小。)

我希望有一种直接的方法可以做到这一点,并按照 S/T 测试的思路创建一个无偏见的样本。

  • 说实话,大致不偏不倚就可以了。

  • 这与此人的问题有关(或多或少是后续问题):

https://math.stackexchange.com/questions/350041/simple-random-sample-without-replacement

  • 还有一个小问题……第一个向我展示这个的人称它为“邮递员算法”,但我不确定他是否在拉我的腿。对吗?

【问题讨论】:

  • 一个随机分发信件的邮递员?听起来很糟糕 =P 根据名字,也许他的意思是"travelling salesman" problem?无论如何,从01 中选择S 随机数,然后将它们乘以所有项目的数量,以获得数据集中的指标。请注意,当您选择下一个随机数时,您需要考虑留下选定的数字。
  • 这是一个类似的问题stats.stackexchange.com/questions/141238/…,其答案给出了一个有原则的、精确的算法。

标签: random-sample


【解决方案1】:

这个怎么样:

  • 预计算从 0 到数据集大小的 S 个随机数。
  • 按照从低到高的顺序排列您的号码
  • 将连续数字之间的差异存储为跳过大小
  • 使用上面的跳过大小遍历大型数据集。

...假设您收集样本的顺序无关紧要

【讨论】:

    【解决方案2】:

    于是想了想,得到了http://math.stackexchange.com的帮助

    归结为:

    • 如果我随机选择 n 个项目一次,第一个会落在哪里?也就是说,min({r_1 ... r_n})。 math.stackexchange 的一位乐于助人的人将其归结为以下等式:

    x = 1 - (1 - r) ** (1 / n)

    也就是说,分布将是 1 减去 (1 - r)n 次方。然后求解 x。很简单。

    • 如果我生成一个统一的随机数并将其插入 r,它的分布与 min({r_1 ... r_n}) 相同- 与最低物品掉落的方式相同。瞧!我刚刚模拟了选择第一个项目,就好像我随机选择了所有 n

    • 所以我跳过列表中的那么多项目,选择那个,然后....

    • 重复直到 n 为 0

    这样,如果我有一个大数据库(如 Mongo),我可以跳过、find_one、skip、find_one 等。直到我拥有我需要的所有项目。

    我遇到的唯一问题是我的实现偏爱列表中的第一个和最后一个元素。但我可以忍受。

    在 Python 2.7 中,我的实现如下所示:

    def skip(n):
        """
        Produce a random number with the same distribution as
        min({r_0, ... r_n}) to see where the next smallest one is
        """
        r = numpy.random.uniform()
        return 1.0 - (1.0 - r) ** (1.0 / n)
    
    
    def sample(T, n):
        """
        Take n items from a list of size T
        """
        t = T
        i = 0
        while t > 0 and n > 0:
            s = skip(n) * (t - n + 1)
            i += s
            yield int(i) % T
            i += 1
            t -= s + 1
            n -= 1
    
    if __name__ == '__main__':
    
        t = [0] * 100
        for c in xrange(10000):
            for i in sample(len(t), 10):
                t[i] += 1  # this is where we would read value i
    
        pprint.pprint(t)
    

    【讨论】:

      猜你喜欢
      • 2011-08-24
      • 2015-05-22
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 2014-09-15
      相关资源
      最近更新 更多