布隆过滤

布隆过滤

什么是布隆过滤

回答这个问题之前,先回答布隆过滤能干什么?
布隆过滤主要被用于判断一个元素是否是否属于某个数据集,通常这个数据集比较大,不能放入内存中。
但是布隆过滤会存在误判,就是 把某个不属于这个数据集的元素 误判为 这个数据集的元素 , 但是 如果某个元素 属于这个数据集 布隆过滤判断这个元素是否属于这个数据集 不会存在误判。

现在我们再来回到什么是布隆过滤
布隆过滤 有几大要素
      二进制数组
      指纹数组
      训练样本数
      Hash函数
就是根据 训练的样本 建立一个二进制数组 用来存储 样本中每个元素的特征 
怎么得到每个元素的特征  , 以及怎么把这些特征存储到二进制数组中,答案是hash函数

为了减少误判率,建了一个指纹数组,一般为8个,分八次 应用哈希函数 得到八个特征值,将这八个特征值映射到二进制数组对应的索引 , 8 个索引值对应的地方 的数被置为1  从而提取到了 这个元素的特征值,并把它存储到二进制数组中了

判断的时候也是同样 , 当被判断的元素的8个特征值对应的二进制数组索引上的数都为1 ,判断这个元素属于这个数据集  否则 不属于

误判率

(https://blog.csdn.net/sunnyyoona/article/details/43482843)

我提取到其中的一行文字

m为二进制数组的长度
n为训练样本中元素的个数
k为指纹数组的长度
表格中的数据为误判率

m/nk=1k=2k=3k=4k=5k=6k=7k=8
166%1%0.5%0.2%0.1%0.09%0.07%0.05%

16 表示 一个元素的特征用16个bit去记录它
k=8 表示这16 个bit位中有8个bit位被置为了1 其余八个还是0
如果两个元素的在这16个bit位中相同的8个bit位都被置为1 这两个元素有相同的特征值
布隆过滤就分不清这两个元素了 , 这就是误判存在的原因 如果相同的元素 他们的特征值一定相同 , 所以在相同元素的判断上不存在误判

实现

话说的太多,容易干,得整点硬菜
下面我就用scala 和 python 来实现布隆过滤

python code

import random
import time

"""
将一个十进制数组转化为 一个数   这个数  为2 的指数幂  大于这个十进制的数且最接近这个十进制数的 数

"""


def get_2_number(ten_number):
    bit_num = 1
    while True:
        re = ten_number >> bit_num
        if re <= 1:
            break
        else:
            bit_num += 1
    return 2 << bit_num


"""
  简单hash 函数 将 string 中的 特征提取出来 映射出 bit_array 的索引
"""


def simple_hash(string, finger_print, size):
    count = 1
    for ch in string:
        count = count * finger_print + ord(ch)
    return count & (size - 1)


class bloom_filter:
    """
    train_number 训练样本数
    finger_prints 指纹数组
    size          二进制数组的长度
    hashFun       哈希函数  用于提取单词的特征
    """

    def __init__(self, train_number, finger_prints):
        self.train_number = train_number
        self.finger_prints = finger_prints
        self.size = get_2_number(train_number) << 4
        self.bit_array = []
        for i in range(0, self.size, 1):
            self.bit_array[i] = False
        self.hashFun = simple_hash

    def __init__(self, train_number):
        self.train_number = train_number

        '''
        要每次产生随机数相同就要设置种子,相同种子数的Random对象,相同次数生成的随机数字是完全相同的
        '''

        random.seed(time.time)

        """   得到二进制数组的长度   """
        self.size = get_2_number(train_number) << 4

        """    生成指纹数组   """
        self.finger_prints = []
        self.finger_prints.append(random.randint(1, self.size) % train_number)
        exists = False
        index = 1
        while index < 8:
            num = random.randint(1, self.size) % train_number
            for j in range(0, index, 1):
                if self.finger_prints[j] == num:
                    exists = True
            if exists:
                exists = False
            else:
                self.finger_prints.append(num)
                index += 1

        """ 初始化二进制数组  """
        self.bit_array = []
        for i in range(0, self.size, 1):
            self.bit_array.append(False)
        """ 设定hash函数  """
        self.hashFun = simple_hash

    """ 提取样本元素的特征值 并将特征 存储到二进制数组  """

    def add(self, string):
        for finger_print in self.finger_prints:
            self.bit_array[self.hashFun(string, finger_print, self.size)] = True

    """ 判读元素是否在 数据集中 """

    def is_contain(self, string):
        contain = True
        for finger_print in self.finger_prints:
            if not self.bit_array[self.hashFun(string, finger_print, self.size)]:
                contain = False
        return contain


bloom = bloom_filter(3571)

""" train """
file = open("C:\\Users\\24590\\IdeaProjects\\PythonJava\\src\\com\\company\\bigdata\\xunlian", 'r')
for line in file.readlines():
    bloom.add(line.replace('\n', ''))

""" judge """

dics = ["act",
        "acting",
        "activity",
        "activate",
        "actualize",
        "enact",

        "actt",
        "actingt",
        "activityt",
        "activatet",
        "actualizet",
        "enactt"]
# for word in dics:
# bloom.add(word)

for word in dics:
    print(word + "   is in or  not in bloom :" + str(bloom.is_contain(word)))

scala code

package com.huawei.bigdata

import scala.util.Random
import scala.util.control.Breaks


class BloomFilterScala[T](trainNumber:Int){
  val random=new Random
  random.setSeed(System.currentTimeMillis)
  val size=getBitArraySize << 4
  var fingerPrints=getFingerPrints
  val bitArray:Array[Boolean]=new Array[Boolean](size)
  var hashFun:(T,Int)=>Int=(word:T,fingerPrint:Int)=>{
    (fingerPrint*word.hashCode()) & (size-1)
  }

  def add(element:T): Unit ={
        for(fingerPrint<-fingerPrints){
              val num:Int=hashFun(element,fingerPrint)
              if(num <0 || num >=size){
                   throw new ArrayIndexOutOfBoundsException(num +"is not between 0 to " + (size-1) )
              }else
                bitArray(num)=true
        }
  }

  def isContain(element: T): Boolean ={
    var contain=true
    for(fingerPrint<-fingerPrints){
      val num:Int=hashFun(element,fingerPrint)
      if(num <0 || num >=size){
        throw new ArrayIndexOutOfBoundsException(num +"is not between 0 to " + (size-1) )
      }else
        if(!bitArray(num)) contain=false
    }
    contain
  }
  def getFingerPrints ={

      val array=new Array[Int](8)
      array(0)=(random.nextInt(size)+1) % trainNumber
      var index=1
      var exists=false
      var num=0
      while(index<8){
          num=(random.nextInt(size)+1)%trainNumber
          for(j <- (0 to index-1)){
              if(array(j)==num) exists=true
          }
          if(exists)
               exists=false
          else {
            array(index) = num
            index += 1
          }
      }
     array
  }

  def getBitArraySize: Int ={
      var bitNum=1
      val break=new Breaks
      break.breakable(
          while(true){
             val re=trainNumber >> bitNum
             if(re <=1) break.break
             else bitNum+=1
          }
      )
      2 << bitNum
  }
}

import sys.process._
object test1 {
  def main(args: Array[String]): Unit = {
      val bloom:BloomFilterScala[String]=new BloomFilterScala[String](3571)
      bloom.hashFun=(word:String,fingerPrint:Int)=>{
          var count=1
          for(w<-word){
             count=count*fingerPrint+w
          }
          count & ( bloom.size -1)
      }
      val lines="cat C:\\Users\\24590\\IdeaProjects\\MRShuffle\\src\\com\\huawei\\bigdata\\xunlian ".lines_!

      lines.foreach(line=>{
         bloom.add(line)
      })

     val list= Array[String]("act",
    "acting",
    "activity",
    "activate",
    "actualize",
    "enact",
    /*******************************/
    "actt",
    "actingt",
    "activityt",
    "activatet",
    "actualizet",
    "enactt")
     list.foreach(word=>{
         val result=bloom.isContain(word)
         println(s"$word is in or not in 数据集 : $result")
     })
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值