Domande rapide sulla distanza di martellamento in postgres


15

Ho un grande database (16 milioni di righe) contenente hash percettivi di immagini.

Mi piacerebbe essere in grado di cercare file percorrendo la distanza in un lasso di tempo ragionevole.

Attualmente, per quanto comprendo correttamente il problema, penso che l'opzione migliore qui sarebbe un'implementazione SP-GiST personalizzata che implementa un BK-Tree , ma che sembra un sacco di lavoro, e sono ancora confuso sul pratico dettagli sull'implementazione corretta di un indice personalizzato. Calcolo della distanza di Hamming è abbastanza trattabili, e mi fa sapere C, però.

Fondamentalmente, qual è l' approccio appropriato qui? Devo essere in grado di interrogare le partite entro una certa distanza di modifica di un hash. A quanto ho capito, la distanza di Levenshtein con stringhe di uguale lunghezza è funzionalmente a percussione della distanza, quindi esiste almeno un supporto esistente per quello che voglio, anche se non esiste un modo chiaro per creare un indice da esso (ricorda, il valore per cui sto richiedendo non posso pre-calcolare la distanza da un valore fisso, poiché sarebbe utile solo per quel valore).

Gli hash sono attualmente memorizzati come una stringa di 64 caratteri contenente la codifica ASCII binaria dell'hash (es. "10010101 ..."), ma posso convertirli in int64 abbastanza facilmente. Il vero problema è che devo essere in grado di eseguire query relativamente velocemente.

Sembra che potrebbe essere possibile ottenere qualcosa pg_trgmsulla falsariga di ciò che voglio con il , ma non sono abbastanza chiaro su come funzioni il mechamismo di corrispondenza del trigramma (in particolare, cosa rappresenta effettivamente la metrica di somiglianza che restituisce ? tipo di modifica-distanza).

Le prestazioni di inserimento non sono fondamentali (è molto costoso dal punto di vista computazionale calcolare gli hash per ogni riga), quindi mi interessa principalmente la ricerca.



@NeilMcGuigan - Interessante! La prima presentazione è in realtà da parte delle persone che mantengono i sistemi SP-GiST e GIST in Postgres.
Nome falso

Il primo link è per qualcosa di fondamentalmente diverso, però. stanno cercando intersezioni fisse, mentre io sto cercando una distanza percorsa. Potrei confondere i phash in un set, ma sarebbe estremamente disordinato e richiederebbe molto codice di supporto ovunque.
Nome falso

FWIW, A questo punto, ho più o meno concluso che devo implementare il mio sistema di indicizzazione. Al momento sto esaminando gli indici SP-GiST personalizzati, ma non ho idea di cosa stia facendo.
Nome falso

1
@FakeName: quando dici la distanza di hamming, suppongo che intendi la distanza di hamming delle stringhe dei valori di hash, non delle immagini? In altre parole, stai cercando di chiedere: Trova tutti i valori di hash che sono sostituzioni di bit X lontano dal parametro di input
Thomas Kejser,

Risposte:


11

Bene, ho passato un po 'a guardare la scrittura di un'estensione C postgres personalizzata e ho finito per scrivere un wrapper di database Cython che mantiene in memoria una struttura ad albero BK.

Fondamentalmente, mantiene una copia in memoria dei valori phash dal database e tutti gli aggiornamenti al database vengono riprodotti nell'albero BK.

Qui è tutto su github . Ha anche MOLTI test unitari.

La query su un set di dati di 10 milioni di valori hash per elementi con una distanza di 4 comporta il contatto ~ 0,25% -0,5% dei valori nella struttura e richiede ~ 100 ms.


BK-Tree in memoria con 16 milioni di righe in memoria? Stavo guardando qualcosa di simile, tuttavia con 1000 immagini e 2000 descrittori su ogni immagine la mia in memoria era enorme.
Stewart

@Stewart - Molto dipende dalla dimensione del tuo hash. Nel mio caso, l'output del valore hash è un singolo bitfield a 64 bit che memorizzo come int64. Sembra che tu abbia un tipo di dati phash molto più grande. Inoltre, non sono sicuro di come funzionerebbero le ricerche su un tipo di dati diverso. Sono ancora uno spazio metrico? Come si calcola la distanza?
Nome falso

Sto usando descrittori a 32 bit con il marcatore FLANN fornito con Opencv. Per calcolare la distanza uso il martellamento con una soglia basata sul rapporto di Lowe. A questo punto non sono sicuro che sia meglio provare a rimanere con in memoria FLANN che fornisce una struttura ad albero KD o per passare a una soluzione più simile alla tua. Perché hai finito per girare il tuo e non andare per qualcosa come libflann?
Stewart

@Stewart - Non ho fatto il mio. Sto usando hashing basato su DFT super noioso .
Nome falso

7

RISPOSTE LUMINOSE!

Ok, ho finalmente avuto il tempo di scrivere un'estensione di indicizzazione PostgreSQL personalizzata. Ho usato l' interfaccia SP-GiST .

Questo è stato abbastanza impegnativo, soprattutto perché Posgres è grande .

Comunque, come al solito, è su github qui .

Per quanto riguarda le prestazioni, attualmente è ~ 2-3 volte più lenta dell'implementazione in memoria pura nell'altra mia risposta a questa domanda, ma è molto più comodo da usare Mangerò felicemente quel colpo di prestazione (realisticamente, è ~ 50 ms / query - 150 ms / query, che è ancora piuttosto piccolo).


Sei fantastico! Puoi aggiungere un file README su come installare? Non ho mai installato nulla in Postgres: P
HypeWolf il

1
@HypeWolf - La radice del repository ha un file README . Non copre quello che vuoi?
Nome falso

Il mio errore, non l'ho visto, non sono sicuro di dove stavo guardando: /
HypeWolf

Stavo cercando anche il README. È nella cartella principale. Il collegamento sta per alcune sottocartelle. Era confuso.
luckydonald,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.