这个问题与reservoir sampling解决的问题有点类似,但不一样。我认为这也是一个相当有趣的问题。
我有一个大型数据集(通常有数亿个元素),我想估计这个数据集中唯一元素的数量。在典型的数据集中,可能存在从少数到数百万个独特元素的任何地方。
当然,明显的解决方案是维护你遇到的元素的运行hashset,并在最后计算它们,这会产生一个确切的结果,但是需要我随身携带一个潜在的大量状态扫描数据集(即到目前为止遇到的所有独特元素)。
不幸的是,在我的情况下,这将需要比我更多的RAM(数据集可能远远大于可用RAM)。
我想知道是否会有一种统计方法可以让我在数据集中进行一次传递,并在最后得出估计的唯一元素数,同时保持相对较少的状态。我扫描数据集。
算法的输入将是数据集(Java用语中的迭代器),它将返回估计的唯一对象计数(可能是浮点数)。假设这些对象可以进行哈希处理(即,如果您愿意,可以将它们放在HashSet中)。通常它们是字符串或数字。
答案 0 :(得分:4)
您可以使用Bloom Filter来获得合理的下限。您只需对数据进行传递,计算并插入绝对不在集合中的项目。
答案 1 :(得分:2)
这个问题在文献中得到了很好的解决; http://www.edbt.org/Proceedings/2008-Nantes/papers/p618-Metwally.pdf对各种方法进行了很好的审查。最简单的方法(对于非常高的精度要求而言最紧凑)称为线性计数。您将元素哈希到位向量中的位置就像布隆过滤器一样(除了只需要一个哈希函数),但最后您可以通过公式估算不同元素的数量D = -total_bits * ln(unset_bits / total_bits) 。详情见文。
答案 2 :(得分:1)
如果你有一个你信任的哈希函数,那么你就可以像对准确的解决方案一样维护一个哈希集,但是抛出哈希值超出某个小范围的任何项目。例如,使用32位散列,但仅保留散列的前两位为0的项目。然后乘以末尾的适当因子以接近唯一元素的总数。