PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Postgres:Index zur Cosinus-Ähnlichkeit von Float-Arrays für One-to-Many-Suche

Ich nehme an, dass keine Erweiterung dies tut, also habe ich eine begrenzte Problemumgehung gefunden:

Wenn A und B beide normalisiert sind (Länge 1), ist cos(A, B) = 1 - 0.5 * ||A - B||^2 . ||A - B|| der euklidische Abstand ist, und cos(A, B) ist die Kosinusähnlichkeit. Größerer euklidischer Abstand <=> geringere Kosinusähnlichkeit (ergibt intuitiv Sinn, wenn Sie sich einen Einheitskreis vorstellen), und wenn Sie nicht normale Vektoren haben, wirkt sich das Ändern ihrer Größen ohne Ändern ihrer Richtung nicht auf ihre Kosinusähnlichkeiten aus. Großartig, also kann ich meine Vektoren normalisieren und ihre euklidischen Abstände vergleichen ...

Es gibt eine nette Antwort hier über Cube , das n-dimensionale Punkte und GiST-Indizes auf Euclidean unterstützt Entfernung, aber es unterstützt nur 100 oder weniger Dimensionen (kann höher gehackt werden, aber ich hatte Probleme um 135 und höher, also fürchte ich jetzt). Erfordert außerdem Postgres 9.6 oder höher.

Also:

  1. Stellen Sie sicher, dass es mir egal ist, höchstens 100 Dimensionen zu haben. Aktualisieren Sie auf Postgres 9.6 oder höher.
  2. Fülle meine Tabelle mit Arrays, um Vektoren darzustellen.
  3. Normalisieren Sie die Vektoren, um eine zusätzliche Spalte cube zu erstellen Punkte. Erstellen Sie einen GiST-Index für diese Spalte.
  4. Aufsteigend nach euklidischer Distanz sortieren, um absteigende Kosinusähnlichkeit zu erhalten:EXPLAIN SELECT * FROM mytable ORDER BY normalized <-> cube(array[1,2,3,4,5,6,7,8,9,0]) LIMIT 10;

Wenn ich mehr als 100 Dimensionen benötige, kann ich dies möglicherweise mit mehreren indizierten Spalten erreichen. Werde die Antwort in diesem Fall aktualisieren.

Aktualisierung: Ich bin mir ziemlich sicher, dass ich nichts damit anfangen kann, den>100-dimensionalen Vektor in mehrere Spalten aufzuteilen. Am Ende muss ich die gesamte Tabelle scannen.