随笔 - 18, 文章 - 0, 评论 - 326, 阅读 - 133万

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

 

 

BloomFilter——大规模数据处理利器

 

  Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法。通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合。

 

. 实例 

  为了说明Bloom Filter存在的重要意义,举一个实例:

  假设要你写一个网络蜘蛛(web crawler)。由于网络间的链接错综复杂,蜘蛛在网络间爬行很可能会形成“环”。为了避免形成“环”,就需要知道蜘蛛已经访问过那些URL。给一个URL,怎样知道蜘蛛是否已经访问过呢?稍微想想,就会有如下几种方案:

  1. 将访问过的URL保存到数据库。

  2. 用HashSet将访问过的URL保存起来。那只需接近O(1)的代价就可以查到一个URL是否被访问过了。

  3. URL经过MD5或SHA-1等单向哈希后再保存到HashSet或数据库。

  4. Bit-Map方法。建立一个BitSet,将每个URL经过一个哈希函数映射到某一位。

  方法1~3都是将访问过的URL完整保存,方法4则只标记URL的一个映射位。

 

  以上方法在数据量较小的情况下都能完美解决问题,但是当数据量变得非常庞大时问题就来了。

  方法1的缺点:数据量变得非常庞大后关系型数据库查询的效率会变得很低。而且每来一个URL就启动一次数据库查询是不是太小题大做了?

  方法2的缺点:太消耗内存。随着URL的增多,占用的内存会越来越多。就算只有1亿个URL,每个URL只算50个字符,就需要5GB内存。

  方法3:由于字符串经过MD5处理后的信息摘要长度只有128Bit,SHA-1处理后也只有160Bit,因此方法3比方法2节省了好几倍的内存。

  方法4消耗内存是相对较少的,但缺点是单一哈希函数发生冲突的概率太高。还记得数据结构课上学过的Hash表冲突的各种解决方法么?若要降低冲突发生的概率到1%,就要将BitSet的长度设置为URL个数的100倍。

 

  实质上上面的算法都忽略了一个重要的隐含条件:允许小概率的出错,不一定要100%准确!也就是说少量url实际上没有没网络蜘蛛访问,而将它们错判为已访问的代价是很小的——大不了少抓几个网页呗。 

 

. Bloom Filter的算法 

 

  废话说到这里,下面引入本篇的主角——Bloom Filter。其实上面方法4的思想已经很接近Bloom Filter了。方法四的致命缺点是冲突概率高,为了降低冲突的概念,Bloom Filter使用了多个哈希函数,而不是一个。

    Bloom Filter算法如下:

    创建一个m位BitSet,先将所有位初始化为0,然后选择k个不同的哈希函数。第i个哈希函数对字符串str哈希的结果记为h(i,str),且h(i,str)的范围是0到m-1 。

 

(1) 加入字符串过程 

 

  下面是每个字符串处理的过程,首先是将字符串str“记录”到BitSet中的过程:

  对于字符串str,分别计算h(1,str),h(2,str)…… h(k,str)。然后将BitSet的第h(1,str)、h(2,str)…… h(k,str)位设为1。

 

  图1.Bloom Filter加入字符串过程

  很简单吧?这样就将字符串str映射到BitSet中的k个二进制位了。

 

(2) 检查字符串是否存在的过程 

 

  下面是检查字符串str是否被BitSet记录过的过程:

  对于字符串str,分别计算h(1,str),h(2,str)…… h(k,str)。然后检查BitSet的第h(1,str)、h(2,str)…… h(k,str)位是否为1,若其中任何一位不为1则可以判定str一定没有被记录过。若全部位都是1,则“认为”字符串str存在。

 

  若一个字符串对应的Bit不全为1,则可以肯定该字符串一定没有被Bloom Filter记录过。(这是显然的,因为字符串被记录过,其对应的二进制位肯定全部被设为1了)

  但是若一个字符串对应的Bit全为1,实际上是不能100%的肯定该字符串被Bloom Filter记录过的。(因为有可能该字符串的所有位都刚好是被其他字符串所对应)这种将该字符串划分错的情况,称为false positive 。

 

(3) 删除字符串过程 

   字符串加入了就被不能删除了,因为删除会影响到其他字符串。实在需要删除字符串的可以使用Counting bloomfilter(CBF),这是一种基本Bloom Filter的变体,CBF将基本Bloom Filter每一个Bit改为一个计数器,这样就可以实现删除字符串的功能了。

 

  Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率。

 

. Bloom Filter参数选择 

 

   (1)哈希函数选择

     哈希函数的选择对性能的影响应该是很大的,一个好的哈希函数要能近似等概率的将字符串映射到各个Bit。选择k个不同的哈希函数比较麻烦,一种简单的方法是选择一个哈希函数,然后送入k个不同的参数。

   (2)Bit数组大小选择 

     哈希函数个数k、位数组大小m、加入的字符串数量n的关系可以参考参考文献1。该文献证明了对于给定的m、n,当 k = ln(2)* m/n 时出错的概率是最小的。

     同时该文献还给出特定的k,m,n的出错概率。例如:根据参考文献1,哈希函数个数k取10,位数组大小m设为字符串个数n的20倍时,false positive发生的概率是0.0000889 ,这个概率基本能满足网络爬虫的需求了。  

 

. Bloom Filter实现代码 

    下面给出一个简单的Bloom Filter的Java实现代码:

 

import java.util.BitSet;

publicclass BloomFilter
{
/* BitSet初始分配2^24个bit */
privatestaticfinalint DEFAULT_SIZE =1<<25;
/* 不同哈希函数的种子,一般应取质数 */
privatestaticfinalint[] seeds =newint[] { 5, 7, 11, 13, 31, 37, 61 };
private BitSet bits =new BitSet(DEFAULT_SIZE);
/* 哈希函数对象 */
private SimpleHash[] func =new SimpleHash[seeds.length];

public BloomFilter()
{
for (int i =0; i < seeds.length; i++)
{
func[i]
=new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}

// 将字符串标记到bits中
publicvoid add(String value)
{
for (SimpleHash f : func)
{
bits.set(f.hash(value),
true);
}
}

//判断字符串是否已经被bits标记
publicboolean contains(String value)
{
if (value ==null)
{
returnfalse;
}
boolean ret =true;
for (SimpleHash f : func)
{
ret
= ret && bits.get(f.hash(value));
}
return ret;
}

/* 哈希函数类 */
publicstaticclass SimpleHash
{
privateint cap;
privateint seed;

public SimpleHash(int cap, int seed)
{
this.cap = cap;
this.seed = seed;
}

//hash函数,采用简单的加权和hash
publicint hash(String value)
{
int result =0;
int len = value.length();
for (int i =0; i < len; i++)
{
result
= seed * result + value.charAt(i);
}
return (cap -1) & result;
}
}
}

 

 

 

参考文献:

 

[1]Pei Cao. Bloom Filters - the math.

http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html

[2]Wikipedia. Bloom filter.

http://en.wikipedia.org/wiki/Bloom_filter

posted @ 2011-01-02 19:08 苍梧 阅读(75258) 评论(30) 推荐(28) 编辑

摘要: 优化算法入门系列文章目录(更新中): 1. 模拟退火算法 2. 遗传算法 遗传算法 ( GA , Genetic Algorithm ) ,也称进化算法 。 遗传算法是受达尔文的进化论的启发,借鉴生物进化过程而提出的一种启发式搜索算法。因此在介绍遗传算法前有必要简单的介绍生物进化知识。一.进化论知识 作为遗传算法生物背景的介绍,下面内容了解即可: 种群(Population):生物的进化以群体的形式进行,这样的一个群体称为种群。 个体:组成种群的单个生物。 基因 ( Gene ) :一个遗传因子。 染色体 ( Chromosome ) :包含一组的基因。 生存竞争,适者生存:... 阅读全文

posted @ 2010-12-23 13:12 苍梧 阅读(211418) 评论(42) 推荐(42) 编辑

摘要: 优化算法入门系列文章目录(更新中): 1.模拟退火算法 2.遗传算法一. 爬山算法 ( Hill Climbing ) 介绍模拟退火前,先介绍爬山算法。爬山算法是一种简单的贪心搜索算法,该算法每次从当前解的临近解空间中选择一个最优解作为当前解,直到达到一个局部最优解。 爬山算法实现很简单,其主要缺点是会陷入局部最优解,而不一定能搜索到全局最优解。如图1所示:假设C点为当前解,爬山算法搜索到A点这个局部最优解就会停止搜索,因为在A点无论向那个方向小幅度移动都不能得到更优的解。图1二. 模拟退火(SA,Simulated Annealing)思想 爬山法是完完全全的贪心法,每次都鼠目寸光的... 阅读全文

posted @ 2010-12-20 17:01 苍梧 阅读(313827) 评论(98) 推荐(138) 编辑

2011年3月9日

摘要: 第1题 Alice和她的同学Bob通过网上聊天商量明天早晨谁去教室打扫卫生的事,Bob说:“我在桌上放了一枚硬币,你猜一下,是正面朝上还是反面朝上?如果猜对了,我去扫地。如果猜错了,嘿嘿…。” Alice显然不会同意,担心自己不论猜正面还是反面,Bob都说她错了。分析:看到这题,我的第一反应是葛优的“分歧终端机”。(╯▽╰) 最关键是要找到一种方法使得Alice给出她的猜测后Bob不能抵赖。一种参考答案如下:1. Bob与Alice商量选取一个哈希函数hash(),hash()的值域应该尽可能大。2. Bob选择一个大随机数x,计算hash(x);通过网络告诉Alice hash(x)的值3. 阅读全文

posted @ 2011-03-09 13:43 苍梧 阅读(7884) 评论(6) 推荐(4) 编辑

2011年3月8日

摘要: 在做分类时常常需要估算不同样本之间的相似性度量(SimilarityMeasurement),这时通常采用的方法就是计算样本间的“距离”(Distance)。采用什么样的方法计算距离是很讲究,甚至关系到分类的正确与否。 本文的目的就是对常用的相似性度量作一个总结。本文目录:1.欧氏距离2.曼哈顿距离3. 切比雪夫距离4. 闵可夫斯基距离5.标准化欧氏距离6.马氏距离7.夹角余弦8.汉明距离9.杰卡德距离& 杰卡德相似系数10.相关系数& 相关距离11.信息熵1. 欧氏距离(EuclideanDistance) 欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公 阅读全文

posted @ 2011-03-08 23:42 苍梧 阅读(123042) 评论(21) 推荐(28) 编辑

2011年3月7日

摘要: 本文主要内容包括: (1) 介绍神经网络基本原理,(2)AForge.NET实现前向神经网络的方法,(3) Matlab实现前向神经网络的方法 。第0节、引例 本文以Fisher的Iris数据集作为神经网络程序的测试数据集。Iris数据集可以在http://en.wikipedia.org/wiki/Iris_flower_data_set 找到。这里简要介绍一下Iris数据集:有一批Iris花,已知这批Iris花可分为3个品种,现需要对其进行分类。不同品种的Iris花的花萼长度、花萼宽度、花瓣长度、花瓣宽度会有差异。我们现有一批已知品种的Iris花的花萼长度、花萼宽度、花瓣长度、花瓣宽度的. 阅读全文

posted @ 2011-03-07 22:30 苍梧 阅读(249138) 评论(37) 推荐(62) 编辑

2011年1月18日

摘要: 摘要:看完本文,你将 (1)了解什么是MPEG-7 (2)理解MPEG-7中的一些基本概念(什么是D,DS,DDL)。一.MPEG-7简介(1) 什么是MPEG-7 MPEG-7的正式名称是“多媒体内容描述接口”(Multimedia Content Description Interface),是由运动图像专家组(MPEG, Moving Picture Experts Group)提出的一个用于描述多媒体内容的ISO/IEC标准。 简单而言,MPEG-7其实就是一个规定如何来描述多媒体内容的特征的标准。明确一点:MPEG-7跟MPEG-2、MPEG-4等除了名字有点像以外没有更多的相同点。 阅读全文

posted @ 2011-01-18 17:15 苍梧 阅读(8485) 评论(1) 推荐(3) 编辑

2011年1月2日

摘要: 1 综述(1)什么是特征选择特征选择 ( FeatureSelection )也称特征子集选择(Feature Subset Selection , FSS ) ,或属性选择( AttributeSelection ) ,是指从全部特征中选取一个特征子集,使构造出来的模型更好。(2)为什么要做特征选择 在机器学习的实际应用中,特征数量往往较多,其中可能存在不相关的特征,特征之间也可能存在相互依赖,容易导致如下的后果:Ø 特征个数越多,分析特征、训练模型所需的时间就越长。Ø 特征个数越多,容易引起“维度灾难”,模型也会越复杂,其推广能力会下降。特征选择能剔除不相关(irrel 阅读全文

posted @ 2011-01-02 14:40 苍梧 阅读(106108) 评论(13) 推荐(16) 编辑

2010年12月22日

摘要: 先来思考几个问题,并不难,各位大牛应能秒杀:1. 小明是个卖苹果的,小红一次在小明那买N(N<1024)个苹果。小明每次都要数N个苹果给小红,唉,太麻烦了。于是小明想出了一种方法:他把苹果分在10个袋子中,则无论小红来买多少个苹果,则他都可以整袋整袋的拿给小红。问怎样分配苹果到各个袋子?2. 有16种溶液,其中有且只有一种是有毒的,这种有毒的溶液与另一种试剂A混合会变色,而其他无毒溶液与A混合不会变色。已知一次实验需要1小时,由于一次混合反应需要使用1个试管,问最少使用多少个试管可以在1小时内识别出有毒溶液?3. 27个小球。其中一个比其他小球都要重一点。给你一个天平,最多称3次,找出这 阅读全文

posted @ 2010-12-22 12:43 苍梧 阅读(11524) 评论(4) 推荐(4) 编辑

2010年11月22日

摘要: 有一个12品脱(pint)的酒瓶,里面装满葡萄酒,另有8品脱和5品脱的瓶子各一个。问如何从中分出6品脱的酒出来?传说泊松年轻时成功解决了该问题,勾起了他对数学的兴趣而投身数学研究,因此该问题被称为泊松分酒问题。另外这个问题又被称为分油问题啦,分水问题啦等等。小学的时候在一本《十万个问什么——数学卷》中看到过这个问题,那本书直接给出了一个解答过程,又没说原理,看得我糊里糊涂。一 . 解答过程为了方便说明,将容量为12品脱,8品脱,5品脱瓶子分别称为大瓶子,中瓶子,小瓶子。按照下面2种规则中的如何一种可以解决这个问题:第一套规则:1. 大瓶子只能倒入中瓶子2. 中瓶子只能倒入小瓶子3. 小瓶子只能 阅读全文

posted @ 2010-11-22 18:20 苍梧 阅读(10589) 评论(7) 推荐(3) 编辑

点击右上角即可分享
微信分享提示