Repetido cálculo del vecino más cercano para millones de puntos de datos demasiado lento

14

Tengo un conjunto de datos que se ejecuta en millones de puntos de datos en 3D. Para el cálculo que estoy haciendo, necesito calcular el vecino (búsqueda de rango) para cada punto de datos en un radio, intentar ajustar una función, calcular el error para el ajuste, repetir esto para el siguiente punto de datos y así sucesivamente. Mi código funciona correctamente, pero está tardando mucho en ejecutarse, ¡alrededor de 1 segundo por punto de datos! Probablemente se deba a que para cada punto, debe buscar en todo el conjunto de datos. ¿Hay alguna manera de hacer que el proceso sea rápido? Tengo la idea de que si de alguna manera puedo establecer alguna relación de adyacencia entre los primeros vecinos, entonces esto puede ser menos lento. Si ayuda, estoy tratando de encontrar el ancho óptimo de la ventana Parzen en 3D.

Kaustubh Kaluskar
fuente

Respuestas:

9

Sugeriría buscar en Google las jerarquías de volumen delimitador (árbol BSP en particular). Dada su nube de puntos, puede encontrar un plano que lo divide en dos subclouds iguales. Luego, cuando necesite encontrar la colección de puntos que están dentro de un radio R de un punto de prueba, primero puede comparar su punto de prueba con ese plano, y si su altura es superior a R, entonces toda la subclona debajo del plano también debe estar más lejos que R (por lo que no necesita verificar ninguno de esos puntos). También puede aplicar esta idea de forma recursiva, en última instancia, generar n log n complejidades de tipo en lugar de n-cuadrado. (Esto es BSP / partición de espacio binario,

rchilton1980
fuente
7

Existen varias estructuras de datos para almacenar datos que conservan información sobre la posición y la proximidad; allí al permitir la determinación rápida del vecino más cercano.

En particular, R-trees (y formas especializadas como R * -trees ) y X-trees . Muchas opciones que están optimizadas para usos ligeramente diferentes.

La elección de un árbol R * en lugar de una búsqueda ingenua del vecino más cercano fue una gran parte de mi obtención de un factor de aceleración de 10000 de un código en particular. (OK, tal vez unos pocos cientos de quien fue la R * -tree, la mayor parte del resto se debía a que los ingenuos look-up había sido mal codificados de modo que rompió el caché. :: suspiro :: )

O(norteIniciar sesiónnorte)norteO(Iniciar sesiónnorte)

dmckee --- gatito ex moderador
fuente
5

Esto es muy similar a uno de los mayores desafíos en el campo de la dinámica molecular: calcular todas las interacciones por pares entre partículas no unidas.

Allí, usamos listas de celdas (o listas de vecinos ) para ayudarnos a descubrir qué hay cerca; Para esta aplicación, la lista de celdas es probablemente el algoritmo más fácil de usar:

  • Divide la caja en una serie de celdas.
  • Para cada partícula, determine a qué celda debe asignarse (O (1) por partícula).
  • Luego, para cada partícula, verifique la celda "propia" más las celdas vecinas; si alguno de estos está ocupado, entonces no es necesario realizar más búsquedas.
  • Si todos los vecinos más cercanos están vacíos, expanda a los vecinos más próximos, y así sucesivamente, hasta encontrar una partícula.

Si su sistema tiene una distribución de partículas más o menos uniforme, esto reducirá en gran medida el costo de su algoritmo, de acuerdo con la aspereza de la cuadrícula. Sin embargo, es necesario un ajuste fino: una grilla demasiado gruesa y no ahorrará mucho tiempo; demasiado bien, ¡y pasarás mucho tiempo recorriendo celdas de cuadrícula vacías!

aeismail
fuente
Debe señalar que la longitud del borde de la celda debe ser al menos el radio de búsqueda, o si cada partícula tiene su propio radio de búsqueda, entonces el radio máximo.
Pedro
Eso es cierto en el caso de MD; aquí, no sabemos cuál es ese radio a priori .
aeismail
Se usó un esquema similar en simulaciones de gravitación de nubes de partículas a gran escala durante mucho tiempo. No sé si todavía es parte del estado del arte.
dmckee --- ex-gatito moderador
4

Definitivamente, debe verificar los árboles y octrees KD que son los métodos de elección para los conjuntos de puntos (mientras que los BSP son para objetos generales y las cuadrículas para densidades más o menos uniformes). Pueden ser muy compactos y rápidos, minimizando la sobrecarga en memoria y computación, y son fáciles de implementar.

Cuando sus puntos estén distribuidos de manera más o menos uniforme (incluso con áreas vacías, pero no debe haber singularidad de densidad u otra alta concentración), verifique los empaques de esferas si desea probar una subdivisión de espacio no jerárquico en forma de cuadrícula.

Cuarzo
fuente
3

Probablemente debería considerar construir la triangulación de Delaunay (bueno, su análogo 3D). En 2D, es una triangulación especial de los puntos de datos que siempre contiene el vecino más cercano. Lo mismo ocurre en 3D, pero con tetraedros.

Puede construir de una vez por todas la triangulación, y luego buscar el vecino más cercano directamente en la triangulación. Creo que hay algunos buenos algoritmos para construir la triangulación: en 2D, la construcción de la triangulación está ennorteIniciar sesión(norte) y la búsqueda posterior del vecino más cercano es lineal en el número de puntos de datos.

¡Espero eso ayude!

Dr_Sam
fuente