HyperLogLog - это вероятностная структура данных . Он подсчитывает количество отдельных элементов в списке. Но по сравнению с простым способом сделать это (имея набор и добавляя элементы в набор), он делает это приблизительно.
Прежде чем посмотреть, как это делает алгоритм HyperLogLog, нужно понять, зачем он вам нужен. Проблема с простым способом состоит в том, что он потребляет O(distinct elements)
пространство. Почему здесь присутствует большая буква О вместо просто отдельных элементов? Это потому, что элементы могут быть разных размеров. Один элемент может быть 1
другим элементом "is this big string"
. Так что если у вас огромный список (или огромный поток элементов), это займет много памяти.
Вероятностный подсчет
Как можно получить разумную оценку количества уникальных элементов? Предположим, что у вас есть строка длины, m
которая состоит {0, 1}
с равной вероятностью. Какова вероятность того, что он начнется с 0, с 2 нулями, с k нулями? Это 1/2
, 1/4
и 1/2^k
. Это означает, что если вы встретили строку с k
нулями, вы примерно просмотрели 2^k
элементы. Так что это хорошая отправная точка. Имея список элементов, которые равномерно распределены между, 0
и 2^k - 1
вы можете подсчитать максимальное количество наибольшего префикса нулей в двоичном представлении, и это даст вам разумную оценку.
Проблема в том, что предположение о равномерно распределенных числах из 0
t 2^k-1
слишком сложно получить (данные, с которыми мы столкнулись, в основном не являются числами, почти никогда не распределяются равномерно и могут быть между любыми значениями. Но используя хорошую функцию хеширования, вы можете предположить, что выходные биты были бы равномерно распределены, и большинство хеш-функций имеют выходы между 0
и 2^k - 1
( SHA1 дает вам значения между 0
и 2^160
). Итак, мы достигли того, что мы можем оценить количество уникальных элементов с максимальной мощностью множества k
битов, сохраняя только одно число log(k)
битов размера . Недостатком является то, что у нас есть огромная разница в наших оценках. Классная вещь, которую мы почти создалиВероятностная счетная бумага 1984 года (с оценкой она немного умнее, но мы все еще близки).
LogLog
Прежде чем двигаться дальше, мы должны понять, почему наша первая оценка не так уж велика. Причина этого в том, что одно случайное появление высокочастотного 0-префиксного элемента может все испортить. Один из способов улучшить это - использовать множество хеш-функций, рассчитывать max для каждой из хеш-функций и в итоге усреднять их. Это отличная идея, которая улучшит оценку, но в статье LogLog использовался немного другой подход (вероятно, потому что хеширование довольно дорогое).
Они использовали один хеш, но разделили его на две части. Один называется bucket (общее количество сегментов равно 2^x
), а другой - в основном такой же, как наш хэш. Мне было трудно понять, что происходит, поэтому я приведу пример. Предположим, у вас есть два элемента и ваша хеш-функция, которая дает форму значений 0
для 2^10
произведенных двух значений: 344
и 387
. Вы решили иметь 16 ведер. Так что у тебя есть:
0101 011000 bucket 5 will store 1
0110 000011 bucket 6 will store 4
Имея больше сегментов, вы уменьшаете дисперсию (вы используете немного больше места, но она все еще крошечная). Используя математические навыки, они смогли количественно определить ошибку (которая есть 1.3/sqrt(number of buckets)
).
HyperLogLog
HyperLogLog не вводит никаких новых идей, но в основном использует много математики для улучшения предыдущей оценки. Исследователи обнаружили, что если вы удалите 30% самых больших чисел из сегментов, вы значительно улучшите оценку. Они также использовали другой алгоритм для усреднения чисел. Бумага тяжелая математика.
И я хочу закончить недавней статьей, в которой показана улучшенная версия алгоритма hyperLogLog (до сих пор у меня не было времени полностью понять его, но, возможно, позже я улучшу этот ответ).