Рубрики
Без рубрики

Реализация простой структуры данных фильтра Bloom в Python

Фильтр цветения-это космическая вероятностная структура данных, созданная Бертоном Ховардом Блумом в 1970 году. Он используется, чтобы проверить, является ли элемент членом набора без ложных негативов. Помечено Python, Datastructure, новичками, обучением.

Эта статья была первоначально размещена на моем личном блог Анкет

Фильтр цветения-это космическая вероятностная структура данных, созданная Бертоном Ховардом Блумом в 1970 году. Он используется, чтобы проверить, является ли элемент элементом набора без Ложные негативы Анкет

В фильтре «Блум мы хэмплят элемент с алгоритмами k-хэширования», генерируем индексы из этих хэшей, а затем устанавливаем значение в этих индексах на 1 в списке фильтра. Чтобы проверить, находится ли элемент в наборе, мы запускаем одни и те же алгоритмы K-хэширования на этом элементе и проверяем, являются ли все значения в индексах, создаваемых хэшами, 1. Если все значения 1, то элемент равен Наверное В наборе и, если какое -либо из значения равна 0, то элемент равен Определенно не в наборе.

На рисунке выше, W это Определенно Не в наборе, так как одно из значений в списке фильтра составляет 0.

Фильтр Bloom чаще всего используется в слоях кэша, чтобы предотвратить кэширование «одного удара чудеса». Это избегает кэширования данных, запрашиваемых только один раз. Данные кэшируются только после нескольких запросов на одни и те же данные. Точно так же он также используется, чтобы избежать рекомендации статей, которые пользователь ранее читал. Есть много других применений фильтра Bloom, которые можно найти Здесь Анкет

Мы собираемся узнать о фильтре «Блум», написав простую реализацию с использованием Python в качестве языка программирования. В этой программе мы хотим проверить, является ли запрос определенно новый или Наверное, старый Используя фильтр Bloom.

Фильтр-спирт

Фильтр цветения может быть реализован с помощью списка определенной длины. Первоначально все члены списка инициализированы до нуля.

bloom_len = 10
bloom = [0] * bloom_len

Получение пользовательского ввода

Во -первых, мы получаем ввод от пользователя внутри цикла времени, чтобы мы могли принять несколько входов. Нам также необходимо кодировать входной текст в «UTF-8» для хэширования, который будет описан дальше.

while True:
    query = str(input("Enter a query: ")).encode('utf-8')

Хешинг

Здесь мы используем три алгоритмы хеширования – MD5 , SHA1 и SHA224 Поскольку они легко доступны в хэшлиб упаковка. Эти три алгоритма хеширования производят три выхода для того же запрос Пользовательские вводы. Выходы функций хэш хранятся в списке для дальнейшей обработки.

    # query = str(input("Enter a query: ")).encode('utf-8')

    m1 = hashlib.md5()
    m2 = hashlib.sha1()
    m3 = hashlib.sha224()

    m1.update(query)
    m2.update(query)
    m3.update(query)

    hash_values = [m1.digest(), m2.digest(), m3.digest()]

Найдите фильтру-индексы

После рассчитываемых значений хеш, которые имеют байты Тип данных, мы преобразуем их в целые числа и храним их в списке. Затем целые числа модули делятся на длину фильтра цветения, чтобы найти индексы, которые необходимо установить внутри фильтра цветения.

# bloom = [0] * bloom_len

def bytes_to_int(hash_value):
    return int.from_bytes(hash_value, byteorder='big')

def bloom_index(hashint):
    return hashint % bloom_len

# while True:
    # hash_values = [m1.digest(), m2.digest(), m3.digest()]

    hashints = list(map(bytes_to_int, hash_values))
    indices = list(map(bloom_index, hashints))

Фильтровать запрос

Теперь мы проверяем, является ли запрос новым или нет. Как мы уже упоминали, Bloom Filter находит, если запрос является Определенно новый или Наверное, старый Анкет Для этого мы проверяем значения, присутствующие в списке фильтра по индексам, которые мы получили, хэшировали запрос. Если какое -либо из значения в фильтре в этих индексах равно нулю, мы можем быть уверены, что запрос является новым. Если все значения едины, то запрос, вероятно, старый.

Если мы уверены, что запрос является новым, то мы устанавливаем значения в индексах на один для фильтрации будущих запросов.

        # return hashint % bloom_len

    def new_query(indices):
    new = False
    for i in indices:
        if bloom[i] == 0:
            new = True
            break

    return new

    def set_bloom(indices):
    for i in indices:
        bloom[i] = 1
    # indices = list(map(bloom_index, hashints))

    if new_query(indices):
        print("Definitely new query")
        set_bloom(indices)
    else:
        print("Probably old query")

Сброс фильтра

По мере того, как все больше и больше запросов обрабатываются, значения в списке фильтра обновляются, это означает, что скорость ложноположительного увеличения постоянно до тех пор, пока каждый элемент в списке не станет 1. Чтобы это не произошло, в нашей простой реализации мы сбросим список, если число 1s в списке превышает 80% от общего числа элементов в списке.

# while True:
    if fill_percentage() > 80.0:
        print("Resetting Bloom Filter-List")
        bloom = [0] * bloom_len

    # word = str(input("enter a word: ")).encode('utf-8')

Вывод

Вы можете попробовать программу, чтобы проверить получение вывода, сгенерированного после каждого запроса, придавая входы. Вы также можете изменить значение Bloom_len играть с программой. Дизайн этой небольшой реализации не предназначен для использования для реальных систем, но полезно узнать, как обычно работает фильтр Bloom.

Вот полный код для программы:

import hashlib

bloom_len = 10
bloom = [0] * bloom_len

def bytes_to_int(hash_value):
    return int.from_bytes(hash_value, byteorder='big')

def bloom_index(hashint):
    return hashint % bloom_len

def fill_percentage():
    return bloom.count(1) / bloom_len * 100;

def new_query(indices):
    new = False
    for i in indices:
        if bloom[i] == 0:
            new = True
            break

    return new

def set_bloom(indices):
    for i in indices:
        bloom[i] = 1

while True:
    if fill_percentage() > 80.0:
        print("Resetting Bloom Filter-List")
        bloom = [0] * bloom_len

    word = str(input("enter a word: ")).encode('utf-8')
    m1 = hashlib.md5()
    m2 = hashlib.sha1()
    m3 = hashlib.sha224()

    m1.update(word)
    m2.update(word)
    m3.update(word)

    hash_values = [m1.digest(), m2.digest(), m3.digest()]
    hashints = list(map(bytes_to_int, hash_values))
    indices = list(map(bloom_index, hashints))

    if new_query(indices):
        print("Definitely new query")
        set_bloom(indices)
    else:
        print("Probably old query")

Внешние ресурсы

Вы можете играть с демонстрацией интерактивного фильтра Bloom от Джейсон Дэвис Чтобы помочь визуализировать концепции. Википедия также имеет комплексную страницу на Bloom Filter Анкет

Рекомендации

  1. Википедия Анкет

Оригинал: “https://dev.to/anarchyrucks/implementing-a-simple-bloom-filter-in-python-11bh”