【问题标题】:How do you count cardinality of very large datasets efficiently in Python?如何在 Python 中有效地计算超大数据集的基数?
【发布时间】:2012-04-27 05:18:29
【问题描述】:

我一直在处理一些非常大的数据集,通常是数十亿个元素,它们都保存在 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 用户,你们知道有什么算法可以帮助我有效地估计基数吗?复杂性是指我不太关心运行时间复杂性,但我更关注空间复杂性。如果它极大地提高了性能,我不介意牺牲一点准确性(所以我不一定需要知道唯一性的确切数量,即使这是理想的,但可能不是一种可行的方法)。我会说最多 5% 是可以接受的。我正在为这个项目寻找专门的 Python 内容。

感谢您提供的任何帮助!

正如一些人所说,我可以使用 Hadoop/MR,但对于这个特定的项目,我们不想走 MR 方式,而是想探索算法以在单台机器上有效地做到这一点,因为这可能是应用于其他几个不同的项目。

【问题讨论】:

  • 只是一个建议,但这听起来可能对 Map-Reduce 框架有好处——将数据中的元素映射到字典或其他东西中的计数。为此,您可以使用由 Yelp 创建的 Python Map-Reduce 框架 MRJob。使用 MRJob 在 Amazon EC2 上运行它对您来说也是一个好主意。我以前用它来计算大型 corpra 中的词频。我想这完全取决于您如何解析单个数据元素。
  • 感谢您的建议,是的,我考虑过 MR(实际上我在其他项目中经常使用它),但是对于这个特定问题,MR/Hadoop 不是一个选项,我们'作为概念验证的一部分,我希望研究在单台机器上执行此操作的算法。
  • 如果 100% 的准确率不重要,也许一个会给你 5% 错误的布隆过滤器会适合内存?如果没有,并且需要一台机器,您可以简单地使用一些具有唯一键的简单 nosql 数据库,该数据库存储在磁盘上并删除重复项。它会很慢,但它适用于你拥有的任何数量的内存。您仍然可以并行化实际的插入工作。
  • 最近有一篇关于 HN 的精彩帖子,讲述了一家公司 (Clearspring) 在现实世界中这样做...Big Data Counting: How To Count A Billion Distinct Objects Using Only 1.5KB Of Memory
  • 哇,很棒的链接,这似乎正是我需要的!希望我以前见过。

标签: python optimization memcached set cardinality


【解决方案1】:

我建议您尝试使用布隆过滤器。即使拥有如此大量的数据,您也可以在适度的系统要求下实现极低的错误率。鉴于您将使用(大致)最佳 k=ln(2)*(bloom 过滤器大小,以位为单位)/(100 亿),您可以计算您的布隆过滤器大小(以位为单位) -((100 亿)*ln(期望的误报)率))/ln(2)^2.

例如,如果内存小于 2gig,则错误率为 0.1%。 所有这一切的一个非常快速且极其简单的实现是http://mike.axiak.net/python-bloom-filter/docs/html/

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 太棒了,它与上一篇文章中提到的布隆过滤器相比如何?你知道使用 LogLog/HyperLog 的利弊吗?
    • 这些技术的主要问题是它们对小基数 (Bloom Filters vs hash sketches 中,您可以看到对于几乎多达 2000 个元素的小基数,它们的误差大于 5%,但对于更大的基数,它们的误差低于您想要的 5%。尽管精度不如 Bloom Filters,但看看 [this] (cl.ly/3M2T1h3s1T2e1G0N1u1K),您可以检查这两种技术在空间方面是否更有效。
    • @goncalvesnelson 是否有任何源代码可用于生成这两个图?
    • @MaxGhenis 很久以前了,后来换了电脑,但是我找到了这些文件:dropbox.com/sh/omgxqmmt4hnjgfq/AABHAu42sEAz_UrGkXL2fUbJa?dl=0 肯定是benchmark和sizebenchmark文件,但是我不确定这些是最终版本。我希望这仍然有帮助。
    猜你喜欢
    • 2015-05-27
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多