2010-03-26 12 views
12

Attualmente sto tentando di trovare K Nearest Neighbor di tutti i nodi di unequilibrata KD-Tree (con K = 2).metodo efficiente per la ricerca di KNN di tutti i nodi di un albero KD-

La mia implementazione è una variazione del codice dallo Wikipedia article ed è decentemente veloce per trovare KNN di qualsiasi nodo O (log N).

Il problema sta nel fatto che ho bisogno di trovare KNN di ogni nodo. Prossimamente con O (N log N) se eseguo l'iterazione su ciascun nodo ed eseguo la ricerca.

Esiste un modo più efficiente per farlo?

+0

Vuoi provocare qualche lista o scorrere i tuple (t, knn1, knn2) memorizzare? –

+0

Solo iterazione. Anche se sono curioso, quale sarebbe la differenza nell'approccio? –

+0

La differenza principale tra la ricerca KNN e la ricerca è che tutti i valori di ricerca sono già nella struttura. Quindi la ricerca inizia in un nodo che non è il nodo radice. Partendo da ogni nodo è possibile attraversare l'albero, trovare 2 candidati e attraversare fino a quando non ci può essere un altro candidato più vicino. Questo può essere sicuro per alcuni nodi traversali ma è ancora O (n log n) se l'albero è bilanciato. Forse c'è un modo per riutilizzare i calcoli (che sarà ancora O (n log n)). –

risposta

5

alt text http://www.cs.umd.edu/~mount/ANN/Images/annspeckle.gif

A seconda delle esigenze, si può decidere di sperimentare tecniche approssimative. Per i dettagli, controlla il lavoro di Arya and Mount sull'argomento. Una carta chiave è here. I dettagli di complessità BigO si trovano nel loro '98 paper.

Ho usato la loro libreria su dataset ad altissima dimensione con centinaia di migliaia di elementi. È più veloce di qualsiasi altra cosa ho trovato. La libreria gestisce sia le ricerche esatte che quelle approssimative. Il pacchetto contiene alcune utility CLI che è possibile utilizzare per sperimentare facilmente con il set di dati; e persino visualizzare il kd-tree (vedi sopra).

FWIW: Ho utilizzato il R Bindings.

Da manuale ANN:

... E 'stato dimostrato da Arya e il Monte [AM93b] e Arya, et al. [AMN + 98] che se l'utente è disposto a tollerare una piccola quantità di errore nella ricerca (restituzione di un punto che non può essere il vicino più prossimo, ma non è significativamente più lontano dal punto di interrogazione di il vicino più prossimo allo ) è quindi possibile ottenere miglioramenti significativi nel tempo di esecuzione . ANN è un sistema per che risponde alle domande più vicine del vicino sia esattamente che approssimativamente.

+0

Wow, grazie per la ricerca, Ryan. Purtroppo sto cercando risultati accurati. Se KNN che usa un albero KD è limitato a questa velocità, forse sto andando su questa ricerca con strutture dati sbagliate. Qualche suggerimento alternativo? –

+0

Come indica l'ultima frase di quella citazione dal loro manuale, puoi fare anche ricerche esatte con questa libreria. "ANN è un sistema per rispondere alle query del vicinato più prossimo sia esattamente che approssimativamente" –

+0

La ricerca approssimativa a volte è utile. Prova prima a cercare il percorso probabile e ad usare un calcolo della distanza che conosce gli iperpiani e i punti lungo il percorso. Se il punto finale non è così vicino a qualsiasi iperpiano, di solito è il vicino più vicino. – htmlfarmer

1

Se i nodi stessi sono punti di query, quindi il tempo di ricerca potrebbe essere inferiore. È possibile iniziare con la fase di backtracking ei primi nodi testati sono già vicini al punto di interrogazione. Quindi grandi aree dell'albero possono essere potate presto.

Il vicino più prossimo è una relazione simmetrica (se n1 è un vicino più prossimo di n2, lo stesso vale per n2) quindi è sufficiente cercare metà dei nodi saltando tutti i nodi già contrassegnati come vicini più vicini. Solo un'idea

Puoi anche provare la ricerca BBD di KD-Tree (Best-Bin First), che ti aiuterà a cercare prima i nodi più vicini (bin). L'ho implementato in C#, quindi scrivimi se ti interessa il codice sorgente.

Ovviamente, il tempo di esecuzione effettivo dipende dalla dimensionalità, dalla struttura dell'albero KD e dalla distribuzione dei punti nel set di dati.

clustering dei punti potrebbe anche essere appropriata.

2

ho usato albero di copertura per questo problema. Ecco il link: http://hunch.net/~jl/projects/cover_tree/cover_tree.html

In un set di dati per dimensione 50M (tutte le query kNN, k = 100), l'albero di copertina ha richiesto 5,5 secondi per la creazione e 120 secondi per l'esecuzione di query. Ann lib ha preso 3.3s per la creazione dell'albero e 138 per l'interrogazione.

aggiornamento: Il più vicino non è una relazione simmetrica. Considera questo: A (0,0) B (1,0) C (3,0). B è il più vicino per C mentre C non è il più vicino per B

+0

Sono necessari tutti i dati per adattarsi alla RAM o alla struttura ad albero? – mrgloom

0

Il termine da cercare è knn join. Più precisamente, probabilmente vorrai fare un self-join.

Forse questi risultati della ricerca di aiuto:

ho visto solo unirsi knn algoritmi per l'* -tree R. Tuttavia, nei miei esperimenti, non erano in grado di sovraperformare una query ripetuta. Potrei mancare alcune idee di implementazione. Ma in generale, tenere i dati in modo appropriato per un albero di join è molto più difficile di una singola query knn.