我正在阅读布隆过滤器,他们看起来很傻。使用bloom过滤器可以完成的任何事情,你可以在更少的空间内,更有效率地完成,使用单个散列函数而不是多个,或者它看起来像是什么。为什么要使用布隆过滤器?它有什么用?
答案 0 :(得分:139)
来自Wikipedia:
布隆过滤器有很强的空间 优于其他数据结构的优势 用于表示集合,例如 自平衡二叉搜索树, 尝试,哈希表或简单数组 或条目的链接列表。最 这些都需要至少存储 数据项本身,可以 从少数人那里需要任何地方 比特,对于小整数,对于 任意位数,例如for 字符串(尝试是一个例外,因为 他们之间可以共享存储 具有相同前缀的元素)。关联 结构产生额外的线性 指针的空间开销。绽放 过滤器有1%的误差和最佳 另一方面,k的值, 每个只需要大约9.6位 元素 - 无论大小 要素。这个优势来了 部分来自其紧凑性,继承 来自数组,部分来自数组 概率性质。如果1%假 每个人的积极率似乎都太高了 我们每个元素添加大约4.8位的时间 我们减少了十倍。
对我很清楚。
布隆过滤器不会存储元素本身,这是关键点。您不使用布隆过滤器来测试元素是否存在,您使用它来测试它是否肯定不存在,因为它保证不会出现错误否定。这使您无需为集合中不存在的元素(例如磁盘IO以查找它们)执行额外的工作。
并且所有这些空间都远远少于哈希表(对于大型数据集可能部分在磁盘上)。虽然您可以将布隆过滤器与结合使用,但是一旦确定该元素有可能存在,就可以使用。
因此,示例使用模式可能是:
你在磁盘上有很多数据 - 你决定你想要什么样的错误(例如1%),它规定了 m 的值。然后确定最佳 k (根据文章中给出的公式)。您可以从此磁盘绑定数据中填充过滤器一次。
现在你有了RAM中的过滤器。当您需要处理某个元素时,您会查询过滤器以查看它是否有可能存在于您的数据集中。如果没有,则不会进行额外的工作。没有磁盘读取等(如果是哈希或树,你必须这样做)。
否则,如果过滤器显示“是,它就在那里”,则有1%的可能性是错误的,所以你做了必要的工作才能找到答案。 99%的时间,它真的将存在,所以这项工作并非徒劳无功。
答案 1 :(得分:125)
让我们说我在Chrome团队中为谷歌工作,我想在浏览器中添加一项功能,通知用户他输入的网址是否是恶意网址。所以我有一个大约100万个恶意URL的数据集,这个文件的大小约为25MB。由于尺寸非常大(与浏览器本身的尺寸相比较大),我将这些数据存储在远程服务器上。
案例1:我使用带哈希表的哈希函数。我决定使用有效的散列函数,并通过散列函数运行所有100万个url以获取散列键。然后我创建一个哈希表(一个数组),其中哈希键将为我提供放置该URL的索引。所以现在一旦我散列并填充了散列表,我就检查它的大小。我已经在哈希表中存储了所有100万个URL及其密钥。所以大小至少为25 MB。此哈希表由于其大小将存储在远程服务器上。当用户出现并在地址栏中输入URL时,我需要检查它是否是恶意的。因此,我通过哈希函数运行URL(浏览器本身可以这样做),我得到该URL的哈希键。我现在必须使用该哈希密钥向我的远程服务器发出请求,以检查具有该特定密钥的哈希表中的特定URL是否与用户输入的内容相同。如果是,那么它是恶意的,如果不是,则它不是恶意的。因此,每次用户输入URL时,都必须向远程服务器发出请求以检查它是否是恶意URL。这将花费大量时间,从而使我的浏览器变慢。
案例2:我使用布隆过滤器。使用多个散列函数通过布隆过滤器运行100万个URL的整个列表,并且在大的0数组中将相应的位置标记为1。假设我们想要1%的误报率,使用布隆过滤器计算器(http://hur.st/bloomfilter?n=1000000&p=0.01),我们得到布隆过滤器的大小只需要1.13 MB。这个小的大小是预期的,即使数组的大小很大,我们只存储1或0而不是散列表中的URL。这个数组可以被视为位数组。也就是说,由于我们只有两个值1和0,我们可以设置单个位而不是字节。这将减少8倍的空间。这个1.13 MB的布隆过滤器由于体积小,可以存储在网页浏览器中!因此,当用户出现并输入URL时,我们只需应用所需的哈希函数(在浏览器本身中),并检查bloom过滤器中的所有位置(存储在浏览器中)。任何位置的值为0都告诉我们此URL绝对不在恶意URL列表中,用户可以自由进行。因此,我们没有调用服务器,因此节省了时间。值1表示URL可能位于恶意URL列表中。在这些情况下,我们调用远程服务器,在那里我们可以使用一些其他哈希函数和一些哈希表,如第一种情况一样,检索并检查URL是否实际存在。 由于大多数时候,URL不太可能是恶意URL,因此浏览器中的小型Bloom过滤器会将其显示出来,从而避免调用远程服务器,从而节省时间。只有在某些情况下,如果bloom过滤器告诉我们网址可能是恶意的,只有在那些情况下我们才会调用服务器。 '可能'是99%的权利。
因此,通过在浏览器中使用小型bloom过滤器,我们节省了大量时间,因为我们不需要为输入的每个URL进行服务器调用。
我们可以看到具有单个散列函数的散列表用于完全不同于Bloom过滤器的目的。希望这能清除您的疑虑:)
我已经为Python中的恶意URL测试任务实现了一个bloom过滤器。代码可以在这里找到 - https://github.com/tarunsharma1/Bloom-Filter 代码非常易于理解,自述文件中提供了详细说明。
答案 2 :(得分:21)
我将首先解释什么是布隆过滤器,它能做什么和不能做什么,为什么我们需要它,显示它是如何工作的直观描述然后在它们有用时给出一些例子
所以standard bloom filter是probabilistic data structure,可以 * :
definitely not in the set
或possibly in the set
这个possibly in the set
正是它被称为概率的原因。使用智能单词意味着false positive是可能的(可能存在错误地认为元素为正的情况)但是假阴性是不可能的。
但不能 * :
* 这组can / can&t用于基本布隆过滤器。因为它是很久以前创建的有用的数据结构,所以人们找到了augment如何使用其他useful功能。
但是等一下:我们已经知道一个数据结构,可以回答所有这些,而不会模糊“可能”。并且没有所有限制(无法删除,无法显示所有限制)。它被称为set。这里有一个布隆过滤器的主要优点:空间效率高,空间常数。
这意味着我们存储多少元素并不重要,空间将是相同的。是的,具有10^6
元素(无用布隆过滤器)的布隆过滤器将使用与10^20
元素的布隆过滤器相同的空间,并使用与具有0
元素的布隆过滤器相同的空间。那需要多少空间?由你来决定(但有一个交易:你拥有的元素越多,你就越不确定possible in the set
回答。
另一个很酷的事情是它是空间不变的。将数据保存到集合时,必须实际保存此数据。因此,如果存储this long string in the set
,则必须至少使用27个字节的空间。但是对于1%的误差和k ** 的最佳值,每个元素需要~9.6位(<2字节)(无论是短文本还是大文本墙) )。
另一个属性是所有操作都采用恒定时间,这与集合情况下的摊销常量时间绝对不同(请记住,如果集合有冲突,它可能会在O(n)
时间内恶化)。
** k是布隆过滤器中使用的散列函数的值
我不会描述bloom filters work(维基百科文章如何很好地解释所有内容)。在这里,我将简要介绍一下基础知识。
m
k
个不同的哈希函数(越独立越好)k
哈希值并将相应位设置为1 k
个哈希值,如果它们中至少有一个没有设置,那么它肯定不在集合中。否则它可以在集合中。即使这样描述也足以理解为什么我们无法确定(您可以从各种其他值中获取所有位)。这是a very nice visualization of how it works。
那么何时可以使用bloom过滤器?简短的回答是在任何可以接受假阳性的地方,以及你想要检查某些东西是否在集合的地方,但即使它们不是,它也可以作为排除昂贵的第一道防线调用验证者。
以下是更具体的说明列表:
答案 3 :(得分:13)
Bloom过滤器在生物信息学中非常有用。与使用常规哈希相比,它们可以更节省空间,特别是当您使用的字符串的大小可能是数亿字母,字母非常小,即{A,G,T,C}时。它们通常用于评估基因组中是否存在某种k聚体。有一个例子用于相关的here。
编辑:
多个哈希函数用于最小化误报。希望是在所有k-hash函数之间,每个值在位数组中将具有与每个其他可能值相比的唯一签名。但是,确实存在误报,但可以将它们最小化到可管理的水平。使用此技术,您可以对其大小的 元素进行哈希处理。当您搜索它们时,您使用每个哈希函数并检查以确保它们的位值都是1.
将此与人类基因组进行比较,其中元素大小的增加显着增加了哈希表的大小(表大小为4 * 4 k )。假设您使用2位/字母对元素进行编码。
答案 4 :(得分:7)
如果Bloom过滤器返回一个项目是该集合的成员,则存在误报的可能性。如果仅使用单个散列函数来指示集合中的成员资格,则误报的概率将高于使用多个散列函数。