Count sketch
Пусть у нас есть поток данных (stream) , при этом все данные — элементы какого-то универсума . Мы хотим уметь считать, сколько раз элемент встретился в этом потоке к моменту времени , то есть уметь считать значение функции
Будем решать задачу для фиксированной временной границы .
Задача подсчета
Дан поток данных . Можно считать, что мы сделали временной срез при .
Нам нужно оценивать количество вхождений элемента в этот поток — значение функции .
Но ответы на запросы лояльные. Мы даем ответ с точностью , при этом позволяем себе ошибаться с вероятностью . Формально, , где — предсказанное нами количество вхождений.
А ещё нам нужно уметь обновлять поток — добавлять и удалять элементы.
Count-Min sketch
Для решения задачи подсчета можно использовать структуру данных Count-Min sketch. Она применима только тогда, когда в поток элементы только добавляются.
Будем использовать хеширование.
Пусть — глубина aka количество хеш-функций, и — размер хеш-пространства. Счётчики будем хранить в двумерном массиве высоты и ширины . Изначально массив проинициализирован нулями.
Создадим еще независимых хеш-функций .
const real delta = 0.01
const real epsilon = 0.01
const int w = ceil(e / epsilon)
const int d = ceil(ln(1 / delta))
const array h[d]
array[int] c[d][w]Обновление
При получении запроса на добавления в «счётчик» элемента мы для каждой строки массива увеличиваем значение соответствующего счётчика на .
function add(self, element):
for i = 0; i < d; i++:
column = h[i](element)
c[i][column] += 1Оценка
Для получения оценки количества вхождений элемента в поток данных нам надо посчитать минимум по всем счётчикам, включающим в себя этот элемент:
Все показатели счетчиков получаются завышенными, ведь у любой хеш-функции неизбежно будут коллизии. Когда мы берем минимум, мы выбираем наименее завышенную оценку.
Доказательство того, что структура работает, и работает хорошо.
Начнем с доказательства завышенности оценок. Для любой строки и любого элемента
Хеш-функции «хорошие», то есть они свои входы равномерно распределяют по выходам.
Рассмотрим произвольную строку . Ошибка оценки выражается как
Тогда математическое ожидание ошибки оценки
Применим неравенство Маркова
Выберем , тогда мы сможем получить оценку
Но это только для одной строки. А при получении оценки мы выбираем минимум, значит, общая ошибка превысит , только тогда, когда переоценку дадут все строк.
Учитывая, что , получаем оценку