Recherche d’Information Master IP TME 1. Indexation Au cours de ce TME, le travail à réaliser est alors de produire un package indexation permettant l’indexation efficace de différentes collections. Ce module d’indexation devra être capable de traiter les collections de documents présentées dans la section suivante, mais pourra être suffisamment générique pour pouvoir être simplement étendu à d’autres ensembles de données. Dans la suite, nous détaillons le corpus mis à votre disposition pour tester les différents modules de votre plateforme d’expérimentation et proposons un exemple d’architecture pour ce module d’indexation. Vous êtes libres d’en proposer une autre. Vous pouvez utiliser le language de programmation dans lequel vous êtes le plus à l’aise - le projet peut être réalisé avec la même facilité (ou difficulté) en Java et Python - et demandera un peu plus de travail en C++ (a priori). 1 Collections de Documents Un jeu de données est mis à votre disposition (Wikipedia, 2.648.940 documents), et est composé de trois répertoires : • documents: Les documents de la collection • queries: Les questions • qrels: Les jugements de pertinence pour les questions Chaque fichier dans documents comporte un ensemble de documents de la collection. Afin d’en faciliter le traitement, chaque ligne est préfixée par une balise (une lettre) dont les significations sont les suivantes : • La balise I repère le début d’un document en en donnant l’identifiant (important car utilisé par les jugements de pertinence des requêtes test); • La balise T donne le titre du document - utile pour afficher une liste de résultats; 1 Master M2 - IP Recherche d’Information - TME 1. Indexation • La balise L donne les liens vers d’autres documents (liste d’identifiants séparés par des espaces). Cela sera utile lors de l’utilisation d’algorithmes utilisant les liens entres articles ; • La balise C donne le contenu Les fichiers de question et de jugements de pertinence seront décrits dans un TME ultérieur. Dans ce TME, vous allez : • Écrire un lecteur (parser) qui permet de lire les fichiers contenant les documents et de renvoyer ceux-ci un par un ; • Écrire l’ensemble des pré-traitements qui permettent de transformer un texte en un ensemble de mots ; • À partir des deux premiers composants, écrire un programme qui permet de construire un index sur le disque. Cet index sera utilisé lors des TPs ultérieurs. 2 Lecture des documents Dans un premier temps, il s’agit de construire un lecteur (Parser) de documents, qui permet d’extraire les documents d’un fichier correspondant à une collection. Chaque Parser est spécifique au type de données qu’il a à traiter et contiendra au minimum une méthode, nextDocument, qui retourne le prochain document dans le fichier. Un document est un objet qui contient un identifiant (chaîne de caractères), un titre, un ensemble de liens vers d’autres documents (identifiants), et un texte. 3 Pré-traitement des documents Afin de segmenter les documents, la méthode la plus simple est de chercher les suites de caractères alphabétiques contigües. En Java, il existe une classe StringTokenizer qui permet d’effectuer ce travail. Pour normaliser, vous pouvez utiliser n’importe quel stemmer (ou écrire le votre...). Le projet "Snowball" contient des stemmer en Java, C et python: http://snowball.tartarus.org/download.php En Python, vous pouvez utiliser le stemmer du projet "nltk" (qui contient également un segmenteur): http://www.nltk.org 4 Indexation des documents Afin de mener à bien les TMEs suivants, les structures de données suivantes sont nécessaires : • Un index "direct" pour chaque document, qui contient le titre du document et l’ensemble des termes apparaissant dans le document ainsi que leurs fréquences associées ; 2 Master M2 - IP Recherche d’Information - TME 1. Indexation • Un index "inversé" qui pour chaque terme associe une liste de couples (document, fréquence) ; • Un dictionnaire qui associe à chaque terme un entier et une position dans l’index "inversé"; • Un dictionnaire qui associe à chaque document (identifiant) un entier et une position dans l’index "direct"; Attention à bien prévoir le fait que nous souhaitons ultérieurement accéder à ces données. Il faut savoir : • Retrouver l’identifiant d’un fichier sachant son numéro (et vice-versa) ; • Retrouver l’identifiant d’un terme sachant son numéro (et vice-versa) ; • Retrouver l’ensemble des occurrences (documents + fréquences) d’un terme étant donné son numéro ; • Retrouver l’ensemble des occurrences (terms + fréquences) étant donné un numéro de document ; Nous supposerons que les deux premières structures peuvent tenir en mémoire (ce qui n’est pas le cas pour de très grandes collections). Il s’agit simplement de savoir les lire et écrire sur disque. Pour la construction des deux suivantes, le plus simple est de procéder en deux temps : 1. Construire l’index "direct" lors de la première lecture (en même temps que les deux dictionnaires) ; 2. Construire l’index "indirect" lors d’une deuxième lecture. En Java, la classe RandomAccessFile permet d’accéder à un fichier de manière directe (en donnant la position dans le fichier). En Python, il faut utiliser le mode binaire pour pouvoir travailler de la sorte, avec open("fichier.dat", "ab+"). Vous pouvez utiliser mmap qui permet d’utiliser un tableau qui est stocké directement sur le disque (pour la lecture). 3