Tengo (~ un millón) vectores de características. Hay (~ un millón) características binarias, pero en cada vector solo (~ mil) de ellas serían , el resto son . Estoy buscando los pares de vectores que tienen al menos (~ cien) características en común ( en ambos). El número de tales pares es de una magnitud similar a (~ un millón).
Creo que esto podría abordarse como la búsqueda de pares de puntos cercanos en un espacio de dimensiones muy altas. La función de distancia podría ser tal que se base en la cantidad de características que los dos vectores tienen en común. Pero probablemente también sería útil con una métrica de distancia más convencional (como Euclidiana).
¿Qué algoritmos conocidos serían útiles para abordar este problema? Cualquier cosa que sea cuadrática en o no será práctica.
Un ejemplo de formulación del problema en el mundo real es considerar a personas moviéndose entre varios lugares. Si dos personas estaban en el mismo lugar al mismo tiempo, decimos que se conocieron. (El número de combinaciones de ubicación y hora con al menos 1 persona presente es ). Estamos buscando amigos: personas que se hayan reunido al menos veces.
fuente
Respuestas:
Parece que el enfoque que está buscando es una combinación de firmas minhash y Locality Sensitive Hashing (LSH); El pdf (disponible gratuitamente) de Mining Massive Datasets describe este enfoque (y otras medidas de similitud) con cierto detalle en el Capítulo 3, pero brevemente:
Una firma minhash es una representación condensada de su matriz original que se construye aplicando un número n de funciones hash a las características, reduciendo así el número de características por observación. Esto reduce el tamaño de sus datos, sin embargo, probablemente notará que esto todavía lo deja con un problema de .O(N2)
Para abordar esto, MMDS aconseja que si todo lo que desea encontrar son pares por encima de un cierto umbral de similitud (que parece aplicarse en su caso), entonces puede concentrarse solo en los pares que tienen más probabilidades de ser similares: este enfoque se llama Hashing sensible a la localidad , y en la sección 3.4 explican un ejemplo de cómo combinar el enfoque de firma minhash con LSH.
Además del texto, también hay conferencias disponibles en el curso Coursera del mismo nombre.
fuente
Esto es solo un producto interno de vectores de características binarias. Cuando el producto interno es mayor que , el par tendrá al menos L elementos en común. Esto debería ser un cálculo relativamente rápido, al menos, más rápido que la distancia euclidiana, lo que sería un desperdicio y lento para estos datos. Debido a que se estipula que estás buscando parejas, esto será inherentemente significa que tenga que hacer ( NL−1 L cálculos para comparar cada vector.( N2)
Encontrar puntos que estén juntos es un problema de agrupamiento. Pero el primer paso de los algoritmos de agrupación con los que estoy familiarizado es calcular distancias o similitudes por pares. Estoy seguro de que alguien ha desarrollado alternativas más eficientes. Un punto sobre la terminología: ¡tener al menos vecinos comunes se expresa como una similitud , no como una distancia! Los productos internos son, en este caso, similitudes de coseno no normalizadas.L
Puede hacer que esto sea más manejable solo realizando el cálculo interno del producto cuando la suma del vector de características (que en este caso es la misma que la norma) para una observación es mayor que , ya que es imposible para ese vector de características binarias tener un producto interior con otro vector de características binario que satisfaga a mi criterio, cuando esta suma es menor que L . Obviamente, calcular estas sumas es solo una complejidad O ( N ) , por lo que es una forma económica de reducir la magnitud del paso interno del producto.L - 1 L O ( N)
Pero la forma clásica de reducir el alcance de este problema es hacer un prefiltrado adicional. ¿Está especialmente interesado cuando una característica poco común toma el valor 1? Si es así, solo realice el cálculo para esos vectores de características.
O tal vez podría beneficiarse reformulando su problema. Por ejemplo, se sabe que el muestreo tiene buenas propiedades; Las estadísticas inferenciales se desarrollan sobre esta idea con bastante profundidad. Entonces, quizás no sea factible analizar todo el conjunto de datos, pero es perfectamente factible examinar una pequeña muestra. No sé qué pregunta está tratando de responder, pero si diseña cuidadosamente su experimento, puede salirse con la suya solo mirando unos pocos miles de observaciones, con datos más que suficientes para fines de validación.
Después de algún pensamiento adicional, tengo una fuerte sospecha de que los datos que va a trabajar tiene algún tipo de gráfico . Es muy plausible que G esté compuesto por varios componentes conectados, en cuyo caso puede descomponer G en un conjunto de gráficos, con el feliz efecto secundario de reducir la dimensionalidad de los datos. Incluso si el gráfico es solo dos componentes conectados de aproximadamente el mismo tamaño, eso significa que sus comparaciones por pares de O ( N 2 ) tienen aproximadamente 1sol sol sol O ( N2) el costo total!14 4
Si el gráfico es simétrico, las siguientes observaciones pueden ser útiles:
Si tiene un gráfico bipartito que conecta a las personas con comportamientos, puede pensar en esto como una red de afiliación , con personas como filas y comportamientos como columnas. Si desea conectar a la gente a la gente a través de los comportamientos que tienen en común, se puede calcular B B T = A . A i j es la cantidad de comportamientos que las personas tienen en común. Obviamente, el conjunto de vértices donde A i j ≥ L responde a su pregunta.si B BT= A UNAyo j UNAyo j≥ L
fuente
Consulte también: datos
de búsqueda de vecinos muy cercanos en datascience.stackexchange
pairwise.py :
fuente
Para cada característica, cree un diccionario que contenga los índices que comparten esta característica. Con suerte, este número no será demasiado grande (si tiene una función compartida por todos los índices, este enfoque está arruinado, puede dejar de leer aquí).
Apliqué este método para implementar un KNN sobre un conjunto de texto grande (tren: 2 000 000 líneas, prueba 35 000 líneas, número de características: 10 000, número promedio de características por elemento: 20), que se ejecutó en aproximadamente una hora. .
fuente
L. Erotz, M. Steinbach y V. Kumar. "Un nuevo algoritmo compartido de agrupación de vecinos más cercanos y sus aplicaciones". Actas del 1er Taller sobre agrupamiento de datos de alta dimensión y sus aplicaciones, 2002.
fuente
Dado que su k es 100 y su n es 1e6, esto debería darle ~ 1e4x de velocidad en comparación con el clásico FFT.
Si necesita otros 20x de velocidad y es un tomador de riesgos, entonces, en lugar de convolucionar todas las filas contra el dominio y buscar el pico, podría arrancar un subconjunto de filas.
También puede prefiltrar columnas eliminando columnas cuyas sumas estén por debajo de 50, o algún otro umbral que esté en el orden de la mitad del número de filas que desea igualar. Como mínimo, debe eliminar las columnas de todos los ceros y todos los 1 como no informativos. Lo mismo con las filas que están completamente vacías o lo suficientemente vacías, o las filas que están tan llenas que son irrelevantes.
Tarea: debería poner un ejemplo aquí usando datos sintéticos y comparar algunos de los métodos.
fuente
Acabo de encontrar un artículo que es directamente relevante.
En realidad, está implementado en https://github.com/soundcloud/cosine-lsh-join-spark, que es donde lo encontré.
Se basa en el hashing sensible a la localidad (ya mencionado en otras respuestas). Después de haber reducido los vectores de características a un espacio de baja dimensión, utiliza una unión rápida de distancia de Hamming para encontrar los vecinos más cercanos.
fuente