读论文《Probabilistic Data Structures for Web Analytics and Data Mining》笔记

 Zipfian distribution:遵循zipf law分布的数据

zipf law :在给定的语料中,对于任意一个term,其频度(freq)的排名(rank)的乘积大致是一个常数。

Zipf应用

  相信你一定听过这样的说法:
  80%的财富集中在20%的人手中……
  80%的用户只使用20%的功能……
  20%的用户贡献了80%的访问量……
  …………
  你知道我在说“二八原则”或“20/80原则”,是的,没错!
  -----------
  如果把所有的单词(字)放在一起看呢?会不会20%的词(字)占了80%的出现次数?答案是肯定的。
  早在上个世纪30年代,就有人(Zipf)对此作出了研究,并给出了量化的表达——齐普夫定律(Zipf's Law):一个词在一个有相当长度的语篇中的等级序号(该词在按出现次数排列的词表中的位置,他称之为rank,简称r)与该词的出现次数(他称为frequency,简称f)的乘积几乎是一个常数(constant,简称C)。用公式表示,就是 r × f = C 。(此处的C一般认为取0.1)


Cardinality Estimation: Linear Counting,这个挺简单的,就是把所有元素都映射到一个hash表中,关键问题是有一些hash值冲突的元素,它们这时候会映射到同一个位置,瞿老师举了个例子,就像大家往墙上射子弹一样,,墙上是一个个方格(k*k),每个人可以射击任意次,但每个人不管射击几次都会射击到同一个弹孔;且一般不同的人不会打到同一个弹孔,但不保证。求最后通过看墙上的弹孔,要我们计算有几个人进行了射击。


Cardinality Estimation: Loglog Counting,这个不错,参数和误差都有公式可以计算,利用了这么一个现实。比如对于所有的3位的二进制数,1开头的有4个,01开头的有2个,001开头的有1个,总共有8个。001这个数里,1第一次出现的位置在第3位,所以总共的可能元素类型个数和即它的势是2^3。我们可以这么设计key-value,有一个桶,来一个元数x的时候,我们计算它的hash值的rank即(二进制里1第一次出现的位置)。这个桶的value就是来的那些数的最大的rank值。当所有数都读取完毕以后,2^value就是元素的种类个数和。这里还涉及到hash的设计。具体操作中我们可以设计n个桶,最后求这n个桶的平均值。当然我们不是重复这个事情n次,这样的话n次的平均值和一次不是一样的吗。有两种方案,一种是用n中不同的hash函数(此时一个桶做n次试验,hash函数在这只是用来计算rank,另一种是把这个元素分到这n个桶里去。hash函数得到的hash值分为两半,一半用来决定放到哪个桶(理论上放到每个桶的概率都是均匀的)另一半用来计算rank


Frequency Estimation: Count-Min Sketch,不是很准,效果必须用实验来验证,具体怎么实现,下面有涉及;


Frequency Estimation: Count-Mean-Min Sketch,对Count-Min Sketch改进,数据结构都一样,只不过计算frequency的方法不一样,此时不再是取最小的桶(每个value add以后,会依据hash(value,i) i可以取1,到d。我们数据结构E(是个二维数组)的宽是w,高是d,通过hash(value,i)可以得到d个hash值vh,则E[vh]值加1)的值。此时计算每个桶的值,时因为这个桶的水可能不只是我们所查询的value贡献的,有其他hash冲突的value也会贡献。总共有n个value,每一行E有W个桶,所以除去当前桶里水的计数,剩下w-1个桶的水计数的和应该是n-E[hash(value)],所以剩下w-1个桶,平均每个桶会装下这n-1个value贡献的水计数是(n-E[hash(value)])/(w-1),而当前桶装的其他value的水肯定也是这么多。然后我们就可以算出当前桶实际装了value贡献的水计数是E[hash(value)]-(n-E[hash(value)])/(w-1)。当然这只是一个平均的概念,然后因为每个value会给d个桶的水加计数。所以我们可以利用这个来做平均。抵消一些误差。求这d个桶的中位数。这个方法挺好的。


Heavy Hitters: Count-Min Sketch,既然Count-Min Sketch可以用来做频率估计,当然可以用来做Heavy Hitters了,把每个element的频率都算出来,然后top-k大的就是heavy Hitters,这里我们可以维持一个堆的数据结构,里面的元素使k各最大的。这个问题其实转化为求一个数组里(因为每个element的频率我们已经计算出来了)top-k。面试宝典里有两个算法,一个是使用快速排序的思想只要O(n)的时间复杂度,还有一个维持一个k个元素的最小堆,堆顶时k个里最小的元素,如果新来的元素比堆顶小则抛弃,如果比堆顶大,则替换,然后自顶向下重新建堆,把受到影响的都要修改。


Heavy Hitters: Stream-Summary,It allows one to detect most frequent items in the dataset and estimate their frequencies with explicitly
tracked estimation error.维持这么一个键值对,key是次数,下面链接的是出现这么多次数的那些元素,可以做成一个链表或者数组。该链表或者数组就是他的value。


Range Query: Array of Count-Min Sketches


Membership Query: Bloom Filter

著名的布鲁姆过滤器查询算法,简单说下这个算法。它其实是Linear Counting的一个扩展,同样和Linear Counting里一样,现在给你看墙,墙上有很多弹孔,要你判断男A刚才又没有进行射击?很简单,先通过hash函数找到A如果射击了,他的射击的弹孔的位置,然后看墙上有没有这个弹孔。如果没有那么A必然刚才没有进行射击,如果有,我们认为A刚才进行了射击,当然这个判断会有误差,误差原因是hash函数可能会有冲突,有另一个人B射击的弹孔位置(即hash值)和A一样。。。现在对这个进行扩展来减小误差,我们设计k面墙。而且一个人在各面墙上射击的方格安排不一样。即有k个hash函数。最后我们依次找这k面墙上A应该射击的方格上是否有弹孔。如果有一面墙的方格没有,则A必然没有进行射击,如果都有,则判断A进行了射击,淡然此时还是有可能误判。是假阳性误判(不属于集合中元素而判断为属于)。但是这个概率已经小多了,而且我们可以不断通过增加墙来减小无误差,误差是可控的。误判概率减小的原因有两个,一:刚才一个hash冲突的值,多个不同的hash函数还会冲突的概率会减小;二:带来了另外一个问题,可能value2和value3的hash值会覆盖value1的hash值,这在一个hash函数的时候是不可能发生的。

另外:其实多个hash函数的情况我们可以把k个hash函数认为是一个大的hash函数,k面墙组合为一面大墙,这是一种hash函数外部组合的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zlingh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值