PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgres:indice sulla somiglianza del coseno degli array float per la ricerca uno-a-molti

Ho capito che nessuna estensione lo fa, quindi ho trovato una soluzione alternativa limitata:

Se A e B sono entrambi normalizzati (lunghezza 1), cos(A, B) = 1 - 0.5 * ||A - B||^2 . ||A - B|| è la distanza euclidea e cos(A, B) è la somiglianza del coseno. Quindi maggiore distanza euclidea <=> minore somiglianza del coseno (ha senso intuitivamente se immagini un cerchio unitario) e se hai vettori non normali, cambiare le loro grandezze senza cambiare le loro direzioni non influisce sulle loro somiglianze del coseno. Ottimo, così posso normalizzare i miei vettori e confrontare le loro distanze euclidee...

C'è una bella risposta qui su Cubo , che supporta punti n-dimensionali e indici GiST su Euclideo distanza, ma supporta solo 100 o meno dimensioni (può essere violato più in alto, ma ho avuto problemi intorno a 135 e oltre, quindi ora temo). Richiede anche Postgres 9.6 o successivo.

Quindi:

  1. Assicurati che non mi interessi avere al massimo 100 dimensioni. Esegui l'upgrade a Postgres 9.6 o successivo.
  2. Riempi la mia tabella con gli array per rappresentare i vettori.
  3. Normalizza i vettori per creare una colonna extra di cube punti. Crea un indice GiST su questa colonna.
  4. Ordina per distanza euclidea crescente per ottenere la somiglianza del coseno decrescente:EXPLAIN SELECT * FROM mytable ORDER BY normalized <-> cube(array[1,2,3,4,5,6,7,8,9,0]) LIMIT 10;

Se ho bisogno di più di 100 dimensioni, potrei essere in grado di ottenere questo risultato utilizzando più colonne indicizzate. Aggiornerò la risposta in tal caso.

Aggiornamento: Abbastanza sicuro che non posso fare nulla con la divisione del vettore a 100 dimensioni in più colonne. Finisco per dover scansionare l'intera tabella.