Standortabhängiges Hashing in Java mit Java-LSH

1. Überblick

Der Algorithmus Locality-Sensitive Hashing (LSH) hasst Eingabeelemente, so dass ähnliche Elemente mit hoher Wahrscheinlichkeit auf dieselben Buckets abgebildet werden.

In diesem kurzen Artikel wird die Bibliothek java-lsh verwendet, um einen einfachen Anwendungsfall dieses Algorithmus zu demonstrieren.

2. Maven-Abhängigkeit

Um zu beginnen, müssen wir die Maven-Abhängigkeit zu https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22info.debatty%22%20AND%20a%3A%22java- hinzufügen. lsh% 22[ java-lsh ]-Bibliothek:

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

3. Ortsbezogener Hashing-Anwendungsfall

LSH hat viele mögliche Anwendungen, aber wir werden ein bestimmtes Beispiel betrachten.

Angenommen, wir haben eine Datenbank mit Dokumenten und möchten eine Suchmaschine implementieren, die ähnliche Dokumente identifizieren kann.

Wir können LSH als Teil dieser Lösung verwenden:

  • Jedes Dokument kann in einen Vektor von Zahlen oder Booleschen umgewandelt werden.

Zum Beispiel könnten wir die verwenden word2vect Algorithmus für verwandeln Wörter und Dokumente in Zahlenvektoren ** Sobald wir einen Vektor für jedes Dokument haben, können wir die LSH verwenden

Algorithmus zur Berechnung eines Hash für jeden Vektor und aufgrund der Eigenschaften von LSH, Dokumente, die als ähnliche Vektoren dargestellt werden wird einen ähnlichen oder gleichen Hash haben ** Als Ergebnis eines bestimmten Dokumentvektors können wir N finden.

Anzahl von Vektoren, die einen ähnlichen Hash haben und die entsprechenden Dokumente an den Endbenutzer zurücksenden

4. Beispiel

Wir werden die Bibliothek java-lsh verwenden, um Hashes für unsere Eingabevektoren zu berechnen. Wir werden die Transformation selbst nicht behandeln, da dies ein großes Thema ist, das über den Rahmen dieses Artikels hinausgeht.

Angenommen, wir haben drei Eingabevektoren, die aus einem Satz von drei Dokumenten transformiert werden und in einer Form dargestellt werden, die als Eingabe für den LSH-Algorithmus verwendet werden kann:

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};

Beachten Sie, dass in einer Produktionsanwendung die Anzahl der Eingabevektoren viel höher sein sollte, um den LSH -Algorithmus zu nutzen, aber aus Gründen der Demonstration werden wir nur drei Vektoren verwenden.

Es ist wichtig anzumerken, dass der erste Vektor sich stark vom zweiten und dritten unterscheidet, während der zweite und der dritte Vektor einander sehr ähnlich sind.

Erstellen wir eine Instanz der LSHMinHash -Klasse. Wir müssen die Größe der Eingabevektoren an sie übergeben - alle Eingabevektoren sollten gleich groß sein. Wir müssen auch angeben, wie viele Hash-Buckets wir benötigen und wie viele Berechnungsschritte (Iterationen) LSH durchführen soll:

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

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

Wir geben an, dass alle Vektoren, die von den Algorithmen gehasht werden sollen, zwischen zehn Buckets gehasht werden sollen. Wir möchten auch vier Iterationen von LSH zur Berechnung von Hashwerten haben.

Um den Hash für jeden Vektor zu berechnen, übergeben wir den Vektor an die Methode 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));

Wenn Sie diesen Code ausführen, erhalten Sie eine Ausgabe ähnlich der folgenden:

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

Betrachtet man jedes Ausgangsfeld, so können wir die Hashwerte sehen, die bei jeder der vier Iterationen für den entsprechenden Eingangsvektor berechnet wurden. Die erste Zeile zeigt die Hash-Ergebnisse für den ersten Vektor, die zweite Zeile für den zweiten Vektor und die dritte Zeile für den dritten Vektor.

Nach vier Iterationen lieferte die LSH wie erwartet Ergebnisse - LSH berechnete den gleichen Hashwert (8) für den zweiten und den dritten Vektor, die einander ähnlich waren, und einen anderen Hashwert (0) für den ersten Vektor unterscheidet sich von den zweiten und dritten Vektoren.

LSH ist ein auf der Wahrscheinlichkeit basierender Algorithmus. Wir können also nicht sicher sein, dass zwei ähnliche Vektoren im selben Hash-Bucket landen.

Wenn wir jedoch eine ausreichend große Anzahl von Eingangsvektoren haben, liefert der Algorithmus Ergebnisse, die eine hohe Wahrscheinlichkeit haben, ähnliche Vektoren denselben Buckets zuzuordnen.

Bei massiven Datensätzen ist LSH ein praktischer Algorithmus.

5. Fazit

In diesem kurzen Artikel haben wir uns eine Anwendung des Locality-Sensitive Hashing-Algorithmus angesehen und mit Hilfe der Bibliothek java-lsh gezeigt, wie er verwendet werden kann.

Die Implementierung all dieser Beispiele und Code-Snippets finden Sie im GitHub-Projekt . Dies ist ein Maven-Projekt lauf so wie es ist