Lingüística computacional: ¿Cuál es la mejor manera de encontrar coincidencias aproximadas de cadenas (duplicados difusos) entre un conjunto de N cadenas?

Otro enfoque es Minhashing (cubierto en el Capítulo 3 de Minería de conjuntos de datos masivos). Construye un conjunto de n-gramos de cada cadena y toma sus hashes (enteros). El minhash es el valor mínimo de hash. Dado que necesita un conjunto de valores minhash para representar cada cadena, para cada valor minhash, XOR el entero se divide con un entero aleatorio, luego toma el mínimo de eso. Usted hace esto para cada cadena, luego compara la superposición entre las firmas minhash (o bandas de firmas minhash) usando algo similar a Jaccard.

Una alternativa para comparar cada cadena con todas las demás es construir una matriz de similitud y llenar cada elemento con la similitud de Jaccard entre las firmas minhash. Esto es aproximadamente O (n ^ 2/2) para escribir desde sim (a, b) == sim (b, a) y sim (a, a) == 1. La búsqueda es O (1).

Otra alternativa (O (1) para escribir y leer) es escribir los minhashes en algún tipo de índice: he usado Lucene para esto, donde los elementos de la firma minhash se escriben en campos indexables de valores múltiples. Buscar cadenas similares a la actual es hacer una consulta OR para todos los minhashes para el documento de consulta. Los resultados se clasificarán primero por los documentos de mayor correspondencia. Si necesita cortar en algún grado de superposición, deberá verificar manualmente la similitud de los primeros con su consulta.

Nadie parece haber mencionado algunos de los métodos más fáciles de encontrar duplicados difusos. Aquí hay dos métodos que podría usar.

– Si la longitud de su anuncio (m) no es muy grande, podría considerar reducir el anuncio a su equivalente de índice de sonido. De esa forma, lidias con los errores ortográficos y tienes una base establecida para trabajar. Mire las diferentes funciones en PHP como soundex (), levenshtein () y metaphone (). Más aquí: soundex – Manual Puede emparejarlo con algo tan básico como Ordenar | Uniq (comando uniq) para eliminar duplicados o usar cualquiera de los otros métodos descritos.

– Para el texto que se ha repasado, es decir, si desea deducir: ” esto es una prueba ” y ” prueba es esto un “, puede usar la similitud de coseno (similitud de coseno). Esto también tiene la ventaja de darle un puntaje de similitud o diferencia en sus comparaciones.

Ambos métodos son bastante comunes y tienen muchas bibliotecas y herramientas estándar para ayudarlo. Como Sundar Lakshmanan señala correctamente, no puedes evitar el O (n * n) a menos que construyas modelos que puedan ayudarte con deducciones.

1. Como se menciona en la respuesta de Julián Solórzano a la Lingüística computacional: ¿Cuál es la mejor manera de encontrar coincidencias aproximadas de cadenas (duplicados difusos) entre un conjunto de N cadenas? La distancia de Levenshtein es la medida más común de la distancia de edición. Si el objetivo es indexar documentos para una búsqueda rápida aproximada, la indexación de N-gramos es el método más común ( http://citeseerx.ist.psu.edu/vie …)

2. Para su problema de obtener duplicados de N elementos rápidamente, recomendaría usar el popular algoritmo Bitap (el algoritmo detrás del popular comando agrep). En su adaptación del algoritmo, el patrón será el propio texto candidato.

3. Advertencia : he asumido que el tamaño del alfabeto (n) así como la longitud de cada anuncio (m) es pequeño. La complejidad del algoritmo Bitap es O (mn).

4. Si desea evitar la complejidad O (N²) que surge de la comparación, debe aplicar el conocimiento del dominio para construir la eliminación de candidatos basada en heurística o usar índices como n-gram. También puede probar el número de implementaciones de PP-Join: procesamiento eficiente de consultas de similitud (anteriormente Efficient Exact Similarity Join). Sin embargo, no he estudiado cómo funciona.

La distancia de Levenshtein es una forma común de determinar qué tan cerca están dos cadenas. Tiene en cuenta cuántas “ediciones” (inserciones, eliminaciones y sustituciones) necesitaría para transformar una cadena dada en otra. Entonces, una distancia baja de Levenshtein para dos cadenas dadas significa que son muy similares.

Las distancias de edición se calculan normalmente mediante programación dinámica. Puede buscar una implementación en el idioma que elija (por ejemplo, aquí hay una para Python). Sin embargo, para su problema, si desea una complejidad menor que O (N ^ 2), probablemente tendría que codificar la suya, para tener en cuenta N cadenas al mismo tiempo.

Depende en gran medida de la definición de “aproximada” aquí. Supongo que no buscas similitud semántica. En ese caso, este documento (Página en Cmu) le ofrece un buen conjunto de métricas aproximadas de distancia de cadena. Una métrica muy importante es la distancia de Levenshtein.

Una forma de abordar el problema podría ser

1. Calcule el simhash de todas las cadenas que tiene.
2. Luego, use las técnicas descritas en este documento (Página en la conferencia Www) para determinar los duplicados cercanos. Google (supuestamente) lo usa para la detección de páginas web casi duplicadas durante el rastreo. Sin embargo, sería interesante ver cómo funciona para cadenas más pequeñas (las cadenas similares tendrán valores hash muy similares o no).

¿Qué lenguaje de programación quieres usar? Hay algunas diferencias que dependen de su elección. Una buena forma de codificar algoritmos de cadenas difusas para php puede encontrar en este artículo Corrección automática de ortografía usando el algoritmo de coincidencia de cadenas trigram.

Si está buscando una herramienta comercial, marque Reifier en nombre a gran escala y aborde la normalización y la deduplicación. Utilizamos una combinación de aprendizaje automático y funciones de similitud para proporcionar coincidencia difusa.

Si mejor significa más simple, entonces use fuzzywuzzy.