|
En el post anterior hemos visto como indexar una colección de documentos con Terrier. En este veremos como acceder a ese índice para buscar documentos en él. También le echaremos un vistazo a la interfaz gráfica de Terrier y veremos como extraer datos del índice como la frecuencia de las palabras por documento o la frecuencia total de una palabra en la colección.
Para ejecutar los ejemplos que veremos a continuación he utilizado una colección de 66345 páginas web extraidas del dominio uk de EUROGOV. EUROGOV es una colección de documentos compuesta por unos 3 millones y medio de páginas web pertenecientes a las webs de instituciones gubernamentales europeas, que se usa en WebCLEF para hacer experimentos sobre recuperación de información web multilingüe. La indexación de esta extracto de EUROGOV con Terrier me ha llevado algo menos de una hora utilizando el código de adjunté al post anterior.
API de recuperación y consulta al índice
De la misma forma que tenemos una serie de clases para las tareas de indexación, existen varias clases que nos permiten consultar el índice, ya sea para recuperar documentos, como si de un buscador se tratase, o para extraer información más concreta sobre las palabras y documentos que contiene nuestra colección.
Recuperación de documentos con Terrier
La opción de consulta más sencilla es simplemente la de recuperar documentos de la colección a partir de una consulta dada. El lenguaje de consultas que tiene Terrier es bastante potente, y aunque no nos vamos a meter con él aquí, si diremos que permite construir consultas con operadores booleanos, asignar valores de empuje a uno o varios términos dentro de la consulta, recuperar por palabras que aparezcan en la misma frase y/o utilizar criterios de proximidad entre palabras.
El código necesario para implementar una búsqueda sencilla sobre Terrier no ocupa más allá de unas cuantas líneas, y lo podeis ver con los comentarios correspondientes en la siguiente clase de Java: OjOSearcher.java, todo el código está comentado y se explica que hace cada cosa.
El elemento más importantes que se utiliza en la clase OjOSearcher es la clase Manager, que se encarga de procesar a alto nivel todas las operaciones que se realizan sobre la consulta. Estas operaciones son las siguientes:
- Preprocesamiento: Donde fundamentalmente se eliminan palabras vacías y se lematizan palabras.
- Matching: Donde se recuperan los documentos relevantes a partir de la función de ranking dada.
- Postprocesamiento: Donde se modifican los resultados a partir de mecanismos de reformulación como por ejemplo expansión de consultas.
- Postfiltrado: Donde se aplican filtros a los documentos recuperados en función a diferentes criterios como idioma o fecha, por poner algún ejemplo.
La clase OjOSearcher implementa la búsqueda con Terrier a muy alto nivel, por lo que no es útil para estudiar el funcionamiento interno de la plataforma, no obstante si lo que queremos es hacer un par de pruebas de recuperación, con esta clase tenemos más que suficiente.
El uso de la interfaz gráfica de Terrier
Llegados a este punto y una vez hemos entendido como funcionan los mecanismos de indexación y búsqueda de documentos en Terrier podemos echarle un vistazo a la aplicación gráfica que viene con Terrier y que nos permite realizar estas tareas de forma un poco más comoda, aunque con menos control sobre lo que hacemos.
Más de uno se estará acordando de toda mi familia por esperar hasta este punto para hablar de la interfaz gráfica, ya que casi todo lo que hemos visto hasta ahora se puede hacer con ella, pero no os enfadeis, sólo intento que trabajemos con el mínimo de cajar negras posibles
Para ejecutar Desktop Terrier, que así es como se llama la aplicación, debemos dirigirnos al directorio bin que tenemos dentro de la carpeta donde hemos descomprimido Terrier. Existen dos scripts, uno para Linux y otro para Windows, y una vez los ejecutamos nos encontramos con lo siguiente:

Si pulsamos sobre Select Folder podremos seleccionar el directorio que contiene los documentos que forman parte de la colección que queremos indexar (recordad que los formatos pueden ser HTML, PDF, WORD y/o texto plano)
Una vez seleccionada la carpeta donde están los documentos, tan solo deberemos pulsar Create Index para que comience el proceso de indexación, el cual tardará más o menos tiempo dependiendo del tamaño de la colección. Tened en cuenta que si la colección es muy grande necesitareis más memoria para la máquina virtual de Java, lo cual se puede modificar dentro del mismo script que hemos utilizado para lanzar la aplicación (al final del archivo, para ser más concretos).
Una vez se haya completado el proceso de indexación de la colección podemos realizar búsquedas sobre ella seleccionando la pestaña Search e introduciendo cualquier consulta en la caja de búsquedas, tal y como se ve en la imagen siguiente:

Este interfaz gráfico es útil si nuestra colección no tiene características especiales. Podemos parametrizar el proceso de indexación y consulta mediante el archivo terrer.properties. Ahora bien, como se puede ver por la sencillez del interfaz, si necesitamos hacer algo especial tendremos que programarlo nosotros mismos. Por esta razón he considerado útil explicar primero la indexación y búsqueda a través del API de Terrier y luego el interfaz gráfico.
Consultas al índice de Terrier
Hasta ahora hemos visto el funcionamiento más básico de Terrier, indexar y buscar. Ahora bien, existen muchas otras funcionalidades, a las que no se puede acceder mediente el interfaz gráfico, y que son en mi opinión las que más utilidad pueden tener para un SEO.
Las consultas sobre la información contenida en el índice son mucho más interesantes si lo que queremos en sacar estadísticas de la estructura de la colección. Como ya mencionamos en el post anterior, Terrier utiliza cuatro estructuras de datos para almacenar toda la información sobre la colección, Lexicon, DirectIndex, Document Index y InvertedIndex. El acceso a cada una de estas estructuras de datos es bastante sencillo ya sea de forma secuencial o accediendo a puntos concretos del índice.
La mejor forma de ver como funcionan estos índices es con algunos ejemplos.
Como extraer la frecuencia de aparición de una palabra en la colección
Supongamos que nos interesa saber cual es la frecuencia de aparición de una palabra determinada en nuestra colección. Para conseguir nuestro objetivo necesitamos utilizar la clase Léxicon, la cual nos proporciona un acceso random (no secuencial) al vocabulario que forma parte de la colección y una serie de métodos con los cuales extraer la información que nos interesa. Como el código de este ejemplo es muy breve lo pegaré aquí directamente.
Lo primero que debemos hacer es instanciar la clase Lexicon y decirle donde se encuentra el fichero que contiene el vocabulario de la colección, el cual se ha generado durante el proceso de la colección, esto lo haremos de la forma siguiente:
Lexicon lex = new Lexicon(”/home/jose/terrier/var/index/data.lex”);
donde /home/jose/terrier/var/index/data.lex es la ruta hasta el fichero que contiene el vocabulario que se ha extraido durante el proceso de indexación de la colección. Notesé que la extensión .lex es la que nos permite indentificar el fichero que contiene el lexicon ó vocabulario de la colección.
A continuación, gracias a los métodos que ofrece la clase Lexicon podemos buscar un término en el vocabulario usando findTerm(”aqui va el término que queremos buscar”):
lex.findTerm(”blair”);//El término que se busca es blair
y extraer su frecuencia de aparición en la colección usando getTF():
int frecuencia = lex.getTF();
de forma que la variable frecuencia contiene la frecuencia de aparición de “blair” en la colección. Más sencillo imposible
Frecuencia de una palabra por documento
Ahora veamos como extraer la frecuencia de esa misma palabra en cada uno de los documentos en los que aparece. Para obtener estos datos vamos a necesitar acceder a varias de las estructuras de datos que forman parte del índice. En concreto necesitamos acceder a Lexicon, InvertedIndex y DocumentIndex.
El primer paso es conocer en que documentos aparece el término que queremos buscar, para hacer esto lo mejor es usar InvertedIndex, ya que un indice invertido es precisamente una estrucutra típica en IR que almacena información sobre que documentos contienen un término determinado. Se llama índice inverso por que es lo contrario de un índice directo que contenga los términos que aparecen en cada documento, el cual en el caso de Terreir se corresponde con la clase DirectIndex.
Quizás se vea de forma más clara si decimos que un índice directo contiene una entrada como la siguiente para todos los documentos que pertenecen a la colección:
documento{Lista de términos que aparecen en ese documento}
Mientras que un índice inverso contiene una entrada como la siguiente para todas las palabras que aparecen los documentos que pertenecen a la colección:
término{Lista de documentos que contienen ese término}
Los ficheros que contienen estas estructuras de datos en Terrier usan las siguientes extensiones: .if para el índice inverso y .df para el índice directo.
Para obtener los documentos que contienen un término en concreto necesitamos en primer lugar conocer el identificador del término que queremos buscar, esto se consigue facilmente con lo que hemos visto en el ejemplo anterior:
Lexicon lex = new Lexicon(”/home/jose/terrier/var/index/data.lex”);//Instanciamos el Lexicon
lex.findTerm(”blair”);//buscamos el término
int idTerm = getTermId();//Guardamos su id (que es un valor numérico de tipo integer) en la variable id
Una vez tenemos el identificador del término, obtenemos los documentos en los que parece se forma muy sencilla:
InvertedIndex ivi = new InvertedIndex(lex);//Instanciamos un índice inverso, para lo cual necesitamos usar el objeto lexicon que hemos instanciado antes.
int[][] docs = ivi.getDocuments(idTerm);//Almaceno los datos correspondientes a los documentos en un array bidimensional.
Los datos que contiene este array bidimensional son las ids de cada documento y junto con la frecuencia del término en cada documento.
Una vez hecho esto imprimir por pantalla los datos documento/frecuencia para un término dado se reduce a recorrer el array docs donde hemos guardado esta información:
for(int i=0;i[simbolo-de-menor-que]docs[0].length;i++)
{
int docid = docs[0][i];
int termfreq = docs[1][i];
System.out.println(docid + ” ” + termfreq);
}
Esto imprimirá un lista con los ids de los documentos en los que aparece un término y su frecuencia en ellos. si lo que queremos es imprimir directamente el nombre de los documentos, necesitaremos hacer un acceso random utilizando la clase DocumentIndex y recuperar el nombre de los documentos a través de su id con el método getDocumentNumber():
DocumentIndex idoc = new DocumentIndex(”/home/jose/terrier-efe/var/index/data.docid”);
for(int i=0;i[simbolo-de-menor-que]docs[0].length;i++)
{
int docid = docs[0][i];
int termfreq = docs[1][i];
System.out.println(docid + ” ” + idoc.getDocumentNumber(docid) + ” ” + termfreq);
}
Como se puede ver a través del API de la clase DocumentIndex, extraer la longitud de un documento (es decir, el número de palabras que tiene), o el número de documentos que componen la colección es totalmente trivial, y se trata simplemente de llamar a los métodos correspondientes un vez hemos instanciado un DocumentIndex.
Por último recordar que siempre es importante utilizar los métodos close() de cada que cada implementación de las estructuras de datos nos ofrecen, de cara a liberar recursos y que nuestro porgrama sea más eficiente
Y ahora qué
A partir de las operaciones básicas que hemos visto hasta aquí podemos conocer cual es la estructura léxica básica de la colección con la que estamos trabajando y tenemos los datos necesarios para saber desde cuales son los términos más frecuentes, hasta calcular estadísticas más avanzadas a partir de los datos de frecuencia de términos, número de documentos o longitud de documentos.
Lo que hemos visto hasta ahora son tan solo algunos de los ejemplos más básicos de como extraer la información que contiene el índice de Terrier. Conocer la frecuencia de las palabras y la longitud de los documentos es útil y nos puede dar algunas pistas sobre las características de nuestra colección, pero no es suficiente si queremos realizar un estudio más detallado.
Por este motivo en el próximo post sobre Terrier veremos algunas de las características más avanzadas de Terrier, que nos permitirán obtener estadísticas más precisas sobre la importancia real de los términos en la colección. Aprendermos como ponderar los términos de una colección estudiando algunas distribuciones probabilísticas y veremos como las matemáticas pueden ser también una herramienta de gran utilidad para los SEOs y como Terrier nos aporta muchas facilidades también en este aspecto.

 |