Локальное хеширование в Java с использованием Java-LSH

1. Обзор

Алгоритм Locality-Sensitive Hashing (LSH) хэширует входные элементы, так что похожие элементы с высокой вероятностью отображаются в одни и те же сегменты.

В этой быстрой статье мы будем использовать библиотеку java-lsh , чтобы продемонстрировать простой вариант использования этого алгоритма.

2. Maven Dependency

Для начала нам нужно добавить зависимость Maven в https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22info.debatty%22%20AND%20a%3A%22java- Библиотека lsh% 22[ java-lsh ]:

<dependency>
    <groupId>info.debatty</groupId>
    <artifactId>java-lsh</artifactId>
    <version>0.10</version>
</dependency>

3. Вариант использования хеширования с учетом локальных особенностей

У LSH есть много возможных применений, но мы рассмотрим один конкретный пример.

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

Мы можем использовать LSH как часть этого решения:

  • Каждый документ может быть преобразован в вектор чисел или логических значений -

например, мы могли бы использовать word2vect алгоритм для преобразовать слова и документы в векторы чисел ** Как только у нас есть вектор, представляющий каждый документ, мы можем использовать LSH

алгоритм для вычисления хеша для каждого вектора, и из-за характеристики LSH, документы, представленные в виде похожих векторов будет иметь такой же или такой же хэш ** В результате, учитывая вектор конкретного документа, мы можем найти N

количество векторов, имеющих одинаковый хэш и возвращающих соответствующие документы конечному пользователю

4. Пример

Мы будем использовать библиотеку java-lsh для вычисления хэшей для наших входных векторов. Мы не будем освещать само преобразование, поскольку это огромная тема, выходящая за рамки этой статьи.

Однако предположим, что у нас есть три входных вектора, которые преобразованы из набора из трех документов, представленных в форме, которую можно использовать в качестве входных данных для алгоритма LSH:

boolean[]vector1 = new boolean[]{true, true, true, true, true};
boolean[]vector2 = new boolean[]{false, false, false, true, false};
boolean[]vector3 = new boolean[]{false, false, true, true, false};

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

Важно отметить, что первый вектор сильно отличается от второго и третьего, тогда как второй и третий векторы очень похожи друг на друга.

Давайте создадим экземпляр класса LSHMinHash . Нам нужно передать ему размер входных векторов - все входные векторы должны иметь одинаковый размер. Нам также нужно указать, сколько хеш-блоков мы хотим и сколько этапов вычисления (итераций) должен выполнять LSH:

int sizeOfVectors = 5;
int numberOfBuckets = 10;
int stages = 4;

LSHMinHash lsh = new LSHMinHash(stages, numberOfBuckets, sizeOfVectors);

Мы указываем, что все векторы, которые будут хешироваться алгоритмами, должны быть хешированы среди десяти сегментов. Мы также хотим иметь четыре итерации LSH для вычисления хэшей.

Чтобы вычислить хеш для каждого вектора, мы передаем вектор методу hash () :

int[]firstHash = lsh.hash(vector1);
int[]secondHash = lsh.hash(vector2);
int[]thirdHash = lsh.hash(vector3);

System.out.println(Arrays.toString(firstHash));
System.out.println(Arrays.toString(secondHash));
System.out.println(Arrays.toString(thirdHash));

Запуск этого кода приведет к выводу, похожему на:

----[0, 0, 1, 0][9, 3, 9, 8][1, 7, 8, 8]----

Рассматривая каждый выходной массив, мы можем видеть значения хеш-функции, рассчитанные на каждой из четырех итераций для соответствующего входного вектора. Первая строка показывает результаты хеширования для первого вектора, вторая строка для второго вектора и третья строка для третьего вектора.

После четырех итераций LSH дал результаты, как мы и ожидали - LSH рассчитал одинаковое хеш-значение (8) для второго и третьего векторов, которые были похожи друг на друга, и другое хеш-значение (0) для первого вектора, которое было отличается от второго и третьего векторов.

LSH - это алгоритм, основанный на вероятности, поэтому мы не можем быть уверены, что два одинаковых вектора попадут в один и тот же блок хэша.

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

Когда мы имеем дело с массивными массивами данных, LSH может быть удобным алгоритмом.

5. Заключение

В этой быстрой статье мы рассмотрели применение алгоритма локального хеширования и показали, как его использовать с помощью библиотеки java-lsh .

Реализацию всех этих примеров и фрагментов кода можно найти в проекте GitHub - это проект Maven, поэтому его легко импортировать беги как есть.