martes, 14 de mayo de 2013

Recuperación de información (information retrieval) y búsqueda en la Web: Matrices de incidencia

Supongamos que mi colección de documentos no es ni más ni menos que las obras completas de William Shakespeare, y que la información que quiero conseguir es la siguiente:

   Todas las obras de Shakespeare que contengan las palabras: "Brutus" y "Cesar" pero no la palabra "Calpurnia".

    Una forma de solucionar este problema es hacer una búsqueda exhaustiva de todos los documentos, seleccionar primero aquellos que tienen las palabras "Brutus" y "Cesar" y luego eliminar de la lista los que también tienen la palabra "Calpurnia".  Con el comando grep de Linux se puede hacer en pocos pasos, pero: ¿es esta una buena solución?

La respuesta es no, y estos son los motivos:


  • Muy lento para grandes colecciones 
  • La condición "NO Calpurnia" no es trivial
  • No puedo realizar consultas más complejas como por ejemplo: buscar la palabra "Romanos" cerca de "compatriotas"
  • No puedo armar un ranking de los documentos devueltos indicando cuales se ajustan más a la consulta.
Una forma de resolver esto es utilizando matrices de incidencia de términos:

En esta matriz ponemos como filas todos los términos relevantes y como columnas los documentos, luego si el término aparece en el documento ponemos un "1" en la celda correspondiente y sino un "0"

Términos Antony and Cleopatra Julius Caesar The Tempest Hamlet Othello Macbeth
Antony1 1 0 0 0 1
Brutus1 1 0 1 0 0
Caesar1 1 0 1 1 1
Calpurnia0 1 0 0 0 0
Cleopatra1 0 0 0 0 0
mercy1 0 1 1 1 1


Una vez que tengo armada una matriz de este tipo puedo obtener rápidamente los documentos para cualquier búsqueda similar a la anterior.

La consulta se resuelve como una serie de operaciones booleanas:
Brutus:       110100    AND                                        (Obtengo el vector correspondiente al término)
Cesar:         110111    AND
Calpurnia:  101111                                                    (Obtengo el vector correspondiente negado)
---------------------------
                  100100

La respuesta es: "Antony and Cleopatra" y "Hamlet"

¿Funciona esta solución con grandes colecciones de datos?, that's the question

Imaginemos que tenemos una colección mediana: N= 1 millón de documentos, donde cada documento tiene en promedio 1000 palabras distintas.
En promedio una palabra ocupa: 6 bytes, incluyendo espacios y signos de puntuación.
Eso quiere decir que tenemos unos 6 Gb de información en documentos y supongamos que la cantidad de términos distintos entre todos los documentos es de 500 mil, es decir ese es el tamaño de nuestro vocabulario.

 Una matriz de 1000000 documentos x 500000 términos tiene un total de 500000000000 ceros y unos. (500 mil millones)

Lo cual es mucho espacio, si cada uno o cero ocupa un bit (pongamos por caso), la matriz sola ocuparía: 62500000000 bytes, es decir: 62 Gb ¡10 veces más que los documentos!

Sin embargo si meditamos un poco sobre la forma de esta matriz nos damos cuenta de que tendría muy pocos unos y casi todos ceros. ¿Por qué? porque cada documento en promedio tiene tan solo mil términos. Así que en principio la cantidad de unos sería un número similar a 1000000 documentos x 1000 términos existentes en un documento: mil millones. La conclusión lógica de esto es: solo guardar la posición de los unos. Eso lo veremos en el próximo post.





1 comentario: