Prácticas de Tecnologías de la Información Curs 2009-2010 Departament de Tecnologia Universitat Pompeu Fabra Introducción El objetivo de estas prácticas es ir construyendo un sistema sencillo para la recuperación de información textual. Así que comenzaremos con una sencilla práctica que iremos mejorando y complicando hasta tener el buscador final. El sistema tomará un conjunto de documentos que representaran la base de información contra la cual el usuario podrá realizar sus consultas. El sistema analizará este conjunto de documentos y creará las estructuras internas necesarias para poder satisfacer las búsquedas del usuario. El sistema ofrecerá la posibilidad de responder a las consultas haciendo servir tanto el modelo de búsqueda basado en el „Page Rank‟ como el „Booleano‟. En todos los casos los resultados de las consultas serán un conjunto de documentos que, de acuerdo con el modelo usado, son relevantes para el usuario. Metodología Estas prácticas serán desarrolladas usando el lenguaje de programación Java. Para comprobar el funcionamiento de las prácticas, será necesario usar los siguientes programas: Eclipse SDK 3. 2 y Java2 SDK 1.6.2_02 (disponibles en las aulas de prácticas y/o que se pueden descargar desde Internet). Se harán en grupos de tres o dos personas (con la excepción, opcionalmente, la Práctica 0). Al final de cada práctica, será necesario entregar la parte correspondiente que será comentada y evaluada en clase y en el seminario correspondiente. Dado que la práctica va creciendo, en la siguiente entrega será necesario haber corregido los errores y defectos de diseño encontrados en la entrega anterior. Las entregas se harán en los apartados (semanas) correspondientes de la asignatura en la aplicación “moodle” que se accede desde el Campus Global/Aula Global de la UPF. Si no tienes usuario de moodle, puedes crearlo siguiendo las instrucciones en la página de inicio de “moodle”. Cada fichero de entrega tiene que identificar el grupo y número de práctica, por ejemplo: “G_nia1_nia2_pracX.zip”. En caso de error en la entrega, entonces se haría una nueva entrega con nombre “G_nia1_nia2_pracX_b.zip”. 1 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 Práctica 0 – Semanas 1,2 (7/1/2010 - 22/1/2010) Preparación para las Prácticas 1 al 5 1. Leer el enunciado de la Práctica 1 para saber más sobre el programa demo y la forma de procesar los ficheros. 2. Descargar los ficheros “progsdeejemplo.zip” y “countries.zip” de semana 1 del calendario de la asignatura en Moodle. Crear una carpeta “DemoSax2” y copiar allí el contenido del primer .zip. Crear un subcarpeta “countries” dentro de “DemoSax2” y copiar allí el contenido del segundo .zip. 3. Abrir los programas Java („DemoSax2.java‟ y „Regex.java‟) en Eclipse y familiarizarse con Eclipse si no lo conoces. Compilar y ejecutar los programas en Eclipse y ver el resultado. Comprobar que el programa está abriendo y leyendo los ficheros .xml, de forma secuencial (en el orden que se encuentran en la carpeta “countries”). Puedes probar inicialmente leyendo sólo 3 o 4 ficheros .xml. 4. Los programas („DemoSax2‟ y „Regex‟) que has probado en el punto 3 lee los ficheros de forma secuencial, pero, en estas prácticas hay que leerlos mediante el seguimiento de los “links” embebidos en los mismos (N.B. sólo hay que procesar cada fichero una vez). Escribir (en papel) un pseudo-código que adaptaría el programa “demo” para leer los ficheros de esta forma (estudiar el enunciado de la Práctica 1 para saber más sobre el programa demo y la forma de procesar los ficheros). De nuevo, puedes probar inicialmente considerando sólo 3 o 4 ficheros .xml, con enlaces mutuos. Resultado: Como resultado de esta “pre-práctica” habrás familiarizado con los programas demo., y hecho un diseño para la adaptación de la demo. para que sea un programa “crawler”. 2 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 Práctica 1 - Semana 3 (7/1/2010 - 29/1/2010) Lectura de los ficheros y las palabras usando SAX y RegEx En las prácticas siguientes vamos a usar el conjunto de documentos estructurados (XML). Se trata de un conjunto de 265 documentos, cada de los cuales describe un país, sus características geográficas, sociales, políticas, económicas, etc. Es decir, tenemos un conjunto de ficheros en formato “XML”, uno por país, con una estructura definida por el siguiente DTD: 1. <!ELEMENT country (Geography | Economy | Government | People | Defence_Forces | Communications | Header)+ > 2. <!ATTLIST country 3. name CDATA #REQUIRED > 4. <!ELEMENT Geography (#PCDATA|link)*> 5. <!ELEMENT Economy (#PCDATA|link)*> 6. <!ELEMENT Government (#PCDATA|link)*> 7. <!ELEMENT People (#PCDATA|link)*> 8. <!ELEMENT Defense_Forces (#PCDATA|link)*> 9. <!ELEMENT Communications (#PCDATA|link)*> 10. <!ELEMENT Header (#PCDATA|link)*> 11. <!ELEMENT link (#PCDATA)> 12. <!ATTLIST link 13. href CDATA #IMPLIED> Fichero countries.dtd. En el cual, para cada país, se encontrará sus datos geopolíticos. Para cualquier nombre de otro país que aparece en un documento, habrá un enlace “HREF” al fichero corresponde. Por ejemplo, si en el documento “India”, aparecen los nombres de los países “China” y “Pakistán”, entonces existirán los enlaces (link) a los ficheros correspondientes a estos países. Para realizar la práctica, se proporcionará un código básico en Java que incluye la llamada al “SAX” parser y el “RegEx” tokenizer, para leer los documentos XML. El formato del fichero de entrada que hemos definido sigue el estándar denominado XML (Extensible Markup Language). Entre otras ventajas, esto nos permite utilizar uno de los analizadores léxicos disponibles que sirve para extraer el contenido de los ficheros en formato XML. En concreto, se tendrá que usar el que se llama SAX (Simple API for XML). Este tipo de “parser” se encuentra en cualquier distribución de Java (a partir de la versión 1.3 de JDK). Para aplicarlo, se puede mirar ejemplos de uso de las siguientes clases, que también se tendrá que importar 3 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 1. org.xml.sax.HandlerBase; 2. javax.xml.parsers.SAXParser; 3. javax.xml.parsers.SAXParserFactory Este “parser” nos permitirá extraer fácilmente a los diferentes elementos que se encuentran en el documento (por ejemplo, <country>, <geography>, <link>, etc.), sus atributos y también el contenido asociado con cada uno de ellos. Su programa debe obtener los diferentes “tokens” (o palabras) de cada pais (por ejemplo: area, population, 89%.). Para poder hacerlo con el máximo de flexibilidad, usaremos la clase Regex, con la cual definimos una expresión regular que define que es un “token”. La expresión que usaremos indicará si un “token” es: (i) un conjunto de letras; (ii) un conjunto de letras y números que comienzan por una letra; (iii) un número que puede tener puntos y comas en su interior y comenzar o terminar en “$” o “%”. Esta expresión también servirá después para las prácticas 3 al 6. Por último, hacemos las siguientes observaciones: (i) al procesar el contenido del elemento <link> </link>, el programa extraerá una vez las palabras que componen el nombre del país encontrado; (ii) en el caso de que cualquier de los documentos .XML tiene un formato incorrecto, el Parser SAX debe dar el correspondiente error, indicando el nombre del documento .XML. Se requiere: Será necesario en esta práctica ser capaz de interpretar el documento XML, y separar las palabras. De esta forma se generarán dos ficheros, uno siendo el fichero “paises.txt” y el otro “palabras.txt”. En el primer fichero “paises.txt” debe haber una lista de países, y para cada país se debe indicar el número de país, su nombre y el número de enlaces (links) salientes, con el siguiente formato: 1. 2. 3. número país; nombre; número de links que salen número país; nombre; número de links que salen ... Formato del fichero paises.txt El segundo fichero, "palabras.txt", ha de contener una línea para cada una de las palabras contenida en cada uno de los documentos. Hay que indicar el documento, la palabra y el número de veces que ha salido la palabra en el documento. 1. 2. 3. número doc; palabra; número de veces que sale en doc; número doc; palabra; número de veces que sale en doc; ... Formato del fichero palabras.txt Las palabras han de ser procesadas para extraer los acentos y pasar de mayúsculas a minúsculas. Sólo consideramos como palabras (o “tokens”) a secuencias de letras entre separadores. Una secuencia no debe contener ni guiones, ni otros símbolos especiales, con la excepción de los que explicamos después. Entendemos un separador (entre “tokens”) como una secuencia de espacios, puntos, comas, punto y coma o dos puntos. Ambos ficheros deben contener un registro por línea y cada elemento tiene que estar separado por un ";" del siguiente. Para almacenar las palabras podemos utilizar la clase Hashtable de Java (java.util.Hashtable). La tabla de “hash” nos sirve para memorizar cuales son las palabras que tienen que salir en el fichero. Para cada nueva palabra que leamos podemos comprobar de forma eficiente si ésta ya 4 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 existía, y si es así incrementar el número de veces que aparece en el documento. En caso de que no exista, será necesario insertarlo en la tabla de “hash”, indicando que es la primera vez que sale. Práctica 2 – Semana 4 (29/1/2010 - 5/2/2010) PreProceso: filtro de palabras no relevantes Se trata de eliminar las palabras no relevantes (denominadas “stopwords”) de un texto de entrada, antes de guardar los términos en el índice invertido. Se proporcionará un fichero de stopword, para el idioma inglés. Los ficheros de entrada serán ficheros de texto sin estructura. Los “stop words” son palabras que se consideren poco relevantes, debido a que son poco significativas (como, por ejemplo, las preposiciones) y también porque salen en muchos documentos, y por lo tanto no sirven para distinguirlos. En el fichero “stopsIngles.txt” se encontrará una lista de “stop words” para el idioma Inglés. Antes de procesar los documentos, será necesario cargar la lista de “stop words” y después, al procesar los documentos, eliminar los “stop words” que por consiguiente no serán cargadas en la estructura invertida de datos. Resultado: Como resultado de la práctica se generarán los mismos listados que en la Práctica 1, pero sin los stopwords. Práctica 3 – Semana 5 (5/2/2010 - 12/2/2010) Indexación En la práctica 3 se trata de crear una estructura de datos invertida en Java, adecuada para almacenar los términos de un conjunto de documentos. Una vez creada la estructura, se tendrá que leer un conjunto de documentos (estructura XML), e insertar los términos e ids de documentos en la estructura. Para realizar la práctica, se proporcionará un código básico en Java que include la llamada al “SAX” parser y el “RegEx” tokenizer, para leer los documentos XML. Una vez que podemos leer uno o más documentos de texto, las estructuras de datos internas permitirá responder a las consultas que un usuario nos puede hacer, de forma que devolvemos los documentos relevantes a su consulta. Para hacerlo, seguimos los pasos a continuación: 1. Hacemos un vocabulario que contendrá todas las palabras que salen en alguno de los documentos. Creamos una tabla de “hash” donde el objeto que se guardará para cada palabra será una clase con un número de coma flotante (float) que primero representará el número de documentos dónde sale la palabra, y la lista de los documentos dónde aparece. En esta tabla pondremos todas las palabras de todos los documentos. En lo que se refiere a la representación de la lista de documentos dónde sale cada palabra, el lenguaje Java nos ofrece diferentes alternativas. Habrá que elegir la que creamos más adecuada para el problema que intentamos resolver. La lista ha de estar ordenada por el número de documento, que es equivalente a decir que los documentos sean puestos en la lista en el mismo orden en que llegan. 2. También necesitamos una estructura para almacenar alguna información respecto a los documentos, como, por ejemplo, el nombre del documento. 3. El tratamiento por documento se hará como hasta ahora, pero cuando terminamos de 5 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 procesar cada país pondremos sus palabras (menos los “stop words” que quitamos en la práctica 2) en el vocabulario. 4. De este modo, una vez procesado un país o documento, tenemos una lista de las palabras que ocurren en aquel documento. Ahora se trata de escoger estas palabras e incorporarlas al vocabulario, indicando que salen en el documento que estamos procesando. 5. Hemos visto que en el vocabulario, cada palabra lleva asociada una lista de los documentos dónde sale. Esta lista cuenta objetos de una clase: para cada documento dónde ocurre la palabra guardamos el número del documento. 6. Cuando volcamos las palabras de un documento, si la palabra aún no se encuentra en el vocabulario, habrá que añadirla, y la lista asociada de documentos tendrá entonces un único elemento, esto siendo el documento actual. Si la palabra ha aparecido anteriormente, se añade el documento a la lista de documentos de esta palabra. Ahora tenemos una estructura como la de la figura, en la cual han sido volcados los documentos y las palabras (el vocabulario) que contienen los documentos: y que nos permite resolver las consultas. Fijaros en que la lista de los documentos donde aparece una palabra tiene que estar ordenada en orden creciente de número de documento. Hay que tener esto presente cuando escogemos la estructura de datos apropiada para almacenar esta lista de documentos. Resultado: Como resultado de la práctica se hace un listado (fichero de texto) a partir de los datos cargados en la estructura invertida. Habrá, para cada palabra, la lista de documentos dónde sale. Después hay que hacer un listado de los documentos con su Id y nombre. Práctica 4 – Semana 6 (12/2/2010 - 19/2/2010) En esta práctica vamos a ampliar las estructuras de datos creadas en la práctica 4, para incluir los datos necesarios para calcular el „page rank‟ de los documentos. Esto permitirá responder a las consultas que un usuario nos puede hacer, de forma que devolvemos los documentos relevantes a su consulta, ordenadas por el „page rank‟. 6 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 Para hacerlo, seguimos los pasos a continuación: 1. Añadimos un campo numérico al vector de documentos, que contendrá el „page rank‟ correspondiente al documento, que calcularemos a continuación. 2. Añadimos otro campo numérico al vector de documentos que contendrá el número de enlaces que salen del documento correspondiente, hacia otros documentos. Para calcularlo, primero procesamos todos los documentos para guardar sus nombres. Entonces repasamos todos los documentos una segunda vez, y para cada documento, contamos el número de veces que salen, en cada documento, los nombres de los demás documentos. 3. También necesitamos un vector que contiene los identificadores de los documentos que apuntan hacia el documento correspondiente. Para rellenarlo, primero procesamos todos los documentos para guardar sus nombres. Entonces, para cada documento, repasamos a los demás documentos para identificar cuales incluyen el nombre del documento actual. 4. Por último, calculamos el „page rank‟ de cada documento, usando una simple formula iterativa, PR(A) = ( (1-d) / T ) + d [ PR(T1)/C(T1) + ….. + PR(Tn)/C(Tn) ], dónde PR(A) es el „page rank‟ de documento A, d es un constante de valor 0,15, T es el número total de páginas, PR(T1) es el „page rank‟ de documento T1, C(T1) es el número de enlaces que salen de documento T1, PR(Tn) es el „page rank‟ de documento Tn1, y C(Tn) es el número de enlaces que salen de documento Tn. Así que, el „page rank‟ de documento A es igual a la suma, ponderada por d, de los page rank de los documentos que apuntan (T1 hasta Tn) a dicho documento. Para comenzar, los „page rank‟ de todos los documentos quedan asignados a 1/T, y se fija un número máximo de iteraciones (por ejemplo 100), o un criterio de terminación cuando el cambio en los valores de los „page rank‟ es menor que un valor determinado. Ahora tenemos una estructura como la de la figura: que nos permite resolver las consultas. 7 de 8 Prácticas de Tecnologías de la Información Curso 2009 - 2010 Resultado: Como resultado de la práctica se generarán los mismos listados que en la Práctica 3, pero incluyendo además los datos calculado para cada documento: „page rank‟, „nº links que salen‟ y „links que llegan‟. Práctica 5 – Semana 7 (19/2/2010 - 26/2/2010) Part a. Respuesta a una pregunta haciendo uso del modelo de búsqueda ‘page rank’. Se trata de implementar el modelo „page rank‟ a partir de la especificación del mismo. Si se piden los documentos que contienen algunas palabras, calcular a partir de las estructuras de datos de la 4ª Práctica el „page rank‟ de cada de los documentos encontrados. La entrada ha de ser el conjunto de palabras a buscar. Hay que encontrar la lista de documentos de cada palabra y entonces cruzar estas listas para obtener el conjunto de documentos que contienen todas las palabras (AND), y al mismo tiempo calcular el „page rank‟. La salida (por pantalla) ha de ser la lista de documentos que contienen las palabras ordenadas por su „page rank‟. Part b. Respuesta a una pregunta haciendo uso del modelo de búsqueda ‘booleano’. Se trata de implementar el modelo „booleano‟ a partir de la especificación del mismo. Si se piden los documentos que contienen algunas palabras, obtener a partir de las estructuras de datos de la 3ª Práctica la lista de documentos, sin ninguna ordenación. La entrada ha de ser el conjunto de palabras a buscar. Hay que encontrar la lista de documentos de cada palabra y entonces cruzar estas listas para obtener el conjunto de documentos que contiene todas las palabras (AND) y el conjunto de documentos que contiene alguna de las palabras (OR). La salida (por pantalla) ha de ser la lista de documentos que contienen las palabras sin ninguna ordenación específica. 8 de 8