如何在Python中有效地计算非常大的数据集的基数?

时间:2012-04-15 18:01:14

标签: python optimization memcached set cardinality

我一直在玩一些非常大的数据集,通常是数十亿个元素,这些数据都保存在memcached云中,并定期转储到文件中,并且我的任务之一是我我试图计算这一集的基数。

对于某些上下文,每个项目都包含一个IP和一些其他标识一个人的属性,并以base64编码,项目大小为20个字节。通过删除某些字段来缩小项目的大小是不可能的。

以下是将我的数据集模拟为内存中版本的内容(感谢this post生成字符串):

import base64, os

dataset_size = 10000000000 # that's 10 billion, be careful if you run it !
big_dataset = [base64.b64encode(os.urandom(10)) for i in range(dataset_size)]

我的第一种方法是使用这样的哈希集:

uniques = set(big_dataset)
print "Cardinality: %d" % len(uniques)

虽然这在理论上适用于小型数据集,但您可以猜测有一个打嗝:

  • 我无法对数据的唯一性做出任何假设。我可以拥有50%的独特数据集,或者我也可以拥有100%的数据集。这是以固定的时间间隔动态生成的,并且根据许多因素(例如,时间)而变化
  • 数据集大小在100亿。以base 64编码的每个项目是20个字节,100亿个是平均几百亿个千兆字节。不幸的是,我无法访问拥有那么多RAM的机器!

我完成了我的家庭作业,并且发现了一些研究论文或一些不起眼的图书馆,但这部分目标的一部分是了解哪种方法有效以及为什么。

所以我打电话给你的Python用户,你知道任何有助于我有效估计基数的算法吗?复杂性我的意思是我并不关心运行时复杂性,但我更关注空间复杂性。我不介意牺牲一点准确性,如果它极大地提高性能(所以我不一定需要知道uniques的确切数量,即使这是理想的,但可能不是一个可行的方法)。我会说高达5%是可以接受的。我正在为这个项目寻找专门用于Python的东西。

感谢您提供的任何帮助!

正如有些人所说,我可以使用Hadoop / MR,但是对于这个特定的项目,我们不想采用MR方式,并且想要在一台机器上有效地探索算法,因为这可能是适用于其他一些不同的项目。

2 个答案:

答案 0 :(得分:8)

我建议使用Hash Sketches,即(超级)Log Log草图或Hyper Log Sketches。

您可以检查并使用和改进我所做的简单python实现: https://github.com/goncalvesnelson/Log-Log-Sketch

答案 1 :(得分:3)

我建议你尝试使用bloom过滤器。即使有如此大量的数据,您也可以通过适度的系统要求实现极低的错误率。鉴于您将使用(粗略)最优k = ln(2)*(布隆过滤器大小,以比特为单位)/(10亿个),您可以计算布隆过滤器大小的位数为 - ((10billions)* ln(期望误报)率))/ LN(2)^ 2。

例如,如果内存少于2 GB,您可以获得0.1%的错误率。 所有这一切的快速且极其简单的实现是http://mike.axiak.net/python-bloom-filter/docs/html/