Zjistil jsem, že žádné rozšíření to nedělá, takže jsem našel omezené řešení:
Pokud jsou A i B normalizovány (délka 1), cos(A, B) = 1 - 0.5 * ||A - B||^2
. ||A - B||
je euklidovská vzdálenost a cos(A, B)
je kosinusová podobnost. Takže větší euklidovská vzdálenost <=> menší kosinusová podobnost (dává smysl intuitivně, pokud si představíte jednotkovou kružnici), a pokud máte nenormální vektory, změna jejich velikosti bez změny jejich směru neovlivní jejich kosinovou podobnost. Skvělé, takže mohu normalizovat své vektory a porovnat jejich euklidovské vzdálenosti...
Je tu hezká odpověď zde o Cube , který podporuje n-rozměrné body a GiST indexy na euklidovském vzdálenost, ale podporuje pouze 100 nebo méně rozměrů (lze hacknout vyšší, ale měl jsem problémy kolem 135 a vyšší, takže se teď bojím). Vyžaduje také Postgres 9.6 nebo novější.
Takže:
- Ujistěte se, že mi nezáleží na tom, abych měl maximálně 100 dimenzí. Upgradujte na Postgres 9.6 nebo novější.
- Vyplňte mou tabulku poli, která budou reprezentovat vektory.
- Normalizací vektorů vytvořte další sloupec
cube
body. Vytvořte v tomto sloupci index GiST. - Řazení podle euklidovské vzdálenosti vzestupně pro získání kosinové podobnosti sestupně:
EXPLAIN SELECT * FROM mytable ORDER BY normalized <-> cube(array[1,2,3,4,5,6,7,8,9,0]) LIMIT 10;
Pokud potřebuji více než 100 dimenzí, mohl bych toho dosáhnout pomocí více indexovaných sloupců. V takovém případě aktualizuje odpověď.
Aktualizace: Jsem si jistý, že s rozdělením vektoru> 100 dimenzí do více sloupců nemohu nic dělat. Nakonec musím naskenovat celou tabulku.