Esta es una implementación básica de un motor de búsqueda de archivos basado en Python para responder consultas en archivos de texto en un sistema local. Hemos utilizado "ponderación de términos tf-idf" y "similitud de coseno" para clasificar la relevancia de los documentos coincidentes. Los cálculos tf-idf están precalculados, lo que hace que la búsqueda sea mucho más rápida. También para agilizar la búsqueda se ha utilizado Stemming (Porter Stemmer). Se proporciona una interfaz de usuario básica que utiliza la biblioteca Tkinter de Python.
python2 createIndex_tfidf.py stopwords.dat testIndex.dat titleIndex.dat
createIndex_tfidf.py se ejecutará solo una vez para calcular los valores tdf-idf en el corpus
python2 queryIndex_tfidf.py stopwords.dat testIndex.dat titleIndex.dat
En general, en este paso se crean tres archivos diferentes:
títuloIndex.dat
Este archivo almacena el docId (ID de documento) único que se asigna a cada documento del corpus.
testIndex.dat
En esto, se crea un archivo de índice (también conocido como estructura de datos de índice invertido) que contiene información sobre todos los términos únicos (excepto las palabras vacías) que aparecen en todos los documentos. A cada documento se le asigna una identificación única que comienza en 0, tal como se almacena en el índice de títulos. dat. La información sobre un término se almacena en el archivo de índice de la siguiente manera: term|docID0:pos1,pos2;docID1:pos3,pos4,pos5;…..|tf0,tf1,tf2...|idf Aquí tf0,tf1,tf2 representa la frecuencia del término en docID0, docID1, docID2 respectivamente. idf representa la frecuencia inversa del documento y pos1 representa la posición del término en el documento respectivo y así sucesivamente.
lineas.dat
Este archivo almacena la información sobre las líneas en las que está presente el término en varios documentos. La información de esta línea se representa como: término|docID0:línea1,línea2;docID1:línea3,línea4,línea5
Antes de la creación de estos archivos, todos los términos de los documentos se verifican en la lista de palabras vacías. Si un término aparece en las palabras vacías, se omite; de lo contrario, su información se almacena en los archivos anteriores. Además, Porter Stemmer deriva cada término antes de agregarlo al índice.
En esto, en primer lugar, toda la información de los archivos lines.dat, titleIndex.dat y testIndex.dat se almacena nuevamente usando un diccionario en Python.
Ahora, los diferentes tipos de consultas admitidas son:
Consultas de una palabra (OWQ) Esta es una consulta de un solo término y su resultado es una lista de documentos que contienen el término solicitado junto con los números de línea donde el término está presente en el documento respectivo.
Consultas de varias palabras (MWQ) La entrada en MWQ es una secuencia de palabras y la salida es la lista de documentos que contienen cualquiera de los términos de consulta junto con los números de línea.
Consultas de frases (PQ) La entrada en PQ es nuevamente una secuencia de palabras, y los documentos coincidentes son los que contienen todos los términos de consulta en el orden especificado.
Ahora que hemos encontrado la lista de documentos en los que está presente la consulta, es hora de clasificarlos. El esquema de clasificación que hemos utilizado aquí se basa en tf-idf. Tf-Idf es un esquema de ponderación que asigna a cada término de un documento una ponderación basada en su frecuencia de término (tf) y su frecuencia inversa de documento (idf). Los términos con puntuaciones de peso más altas se consideran más importantes. Es uno de los esquemas de ponderación más populares en recuperación de información.
La frecuencia del término (tf) de un término es específica del documento. Básicamente es el número de apariciones del término t en el documento D. Es bastante lógico elegir tf como parámetro porque a medida que un término aparece más en el documento se vuelve más importante. Podemos representar un documento mediante un vector cuyo tamaño sea igual al no. de términos únicos en el documento y cada valor denota el recuento del término en el documento dado. La representación de documentos como vectores en un espacio vectorial común se conoce como modelo de espacio vectorial y es muy fundamental para la recuperación de información. Pero aquí hay un inconveniente. A medida que el documento crezca en tamaño, el peso de tf aumentará a medida que aumentará la frecuencia de los términos. Por lo tanto, un documento que contenga la misma información que otro documento, copiado más de una vez, se considerará más importante. Para erradicar este inconveniente dividiremos cada valor de un vector por su norma para que el vector se convierta en un vector unitario.
No podemos usar solo frecuencias de términos para calcular el peso de un término en el documento, porque tf considera que todos los términos son igualmente importantes. Sin embargo, algunos términos aparecen con menos frecuencia y son más discriminativos que otros. Si usamos tf únicamente como medida para clasificar, entonces si buscamos un tema como ondas sonoras, podríamos terminar obteniendo muchos documentos que contienen ondas de luz y otras ondas, ya que la frecuencia del término es el único parámetro.
Para mitigar este efecto, utilizamos la frecuencia de documentos inversa. La frecuencia de documentos de un término es básicamente la cantidad de documentos que contienen el término. Entonces, la frecuencia inversa de documentos (idf) de un término es el número de documentos en el corpus dividido por la frecuencia de documentos de un término. Generalmente se ha encontrado que el factor de idf es bastante grande y se obtienen mejores resultados si usamos log(idf). Como log es una función creciente, podemos usarla sin obstaculizar nuestros resultados.
Hemos definido tanto tf como idf, y ahora podemos combinarlos para producir la puntuación final de un término t en el documento d. Nuevamente representaremos el documento como un vector, siendo cada entrada el peso tf-idf del término correspondiente en el documento. El peso tf-idf de un término t en el documento d es simplemente la multiplicación de su tf por su idf.
Ahora que hemos construido los vectores de cada documento en función del peso tf-idf. Es hora de responder una consulta utilizando los vectores de documentos dados. En primer lugar, crearemos un vector de consulta de forma similar a la que creamos el vector de documento, es decir, en función de la puntuación tf-idf (considerando la consulta de un documento en sí). Ahora que tenemos nuestro vector de consulta listo, encontraremos todos aquellos documentos en los que está presente nuestra consulta. Ahora tomaremos el producto escalar del vector de consulta y el vector de documento en el que está presente la consulta. Cuanto mayor sea el producto escalar , más similar será el vector de consulta con el vector de documento, lo que significa que el ángulo entre el vector de documento y el vector de consulta es pequeño. Esta técnica para encontrar similitud entre consulta y documento se llama similitud coseno.