8. Datos no estructurados

8.1 Introducción

 

Colecciones no estructuradas

Datos sin tipos pre-definidos

Se almacenan como “documentos” u objetos” sin estructura uniforme

Se recuperan con apoyo de índices y modelos de “RI” para determinar su relevancia respecto a consultas del usuario

Ejemplos:

  • Correspondencia, diarios, novelas, blogs

 

Recuperación de Información (RI)

Area de las ciencias computacionales que estudia técnicas y métodos para indexar y consultar colecciones de diversos niveles de estructura

Proceso para determinar los documentos relevantes para un tema especificado por el usuario

Ejemplo:

Encontrar documentos sobre historia de los juegos olímpicos”

El problema involucra interpretar, comparar, jerarquizar,…

Comparar con recuperación de datos:

Obtención de todos los elementos en una colección que satisfacen totalmente condiciones claramente especificadas.

Ejemplo: Encontrar los nombres de todos los estudiantes de la

carrera de ISC

El problema es sencillo si se cuenta con una base de datos relacional:

select nombre from estudiantes where carrera = ‘IS’



RI cobra importancia

Se inicia con tablas de contenido e índices de libros

Las bibliotecas introdujeron índices a múltiples publicaciones, referencias cruzadas e índices jerárquicos para clasificar documentos

Desde los 40s, se inicia RI orientado a indexar y recuperar textos pero la recuperación de datos domina

En los 90s, el desarrollo de WWW hace de RI un área fundamental y acelera su evolución

RI incluye ahora modelado, indexado, clasificación, interfaces de usuario, visualización de datos textuales, multimediales e hipertextuales

Meta: Dada una consulta, obtener todos los documentos relevantes posibles y minimizar el número de documentos irrelevantes



 

El reto

El enfoque inicial: clasificar documentos

El problema: quien categoriza no coloca los documentos donde espera encontrarlos quien busca, a veces ni el mismo clasificador (ej. archivos personales, folders de correo electrónico)

Otro enfoque: “entender” el contenido y responder a consultas

Problema: El procesamiento de lenguaje natural aún no es lo suficientemente general (¿ni lo será?)

La alternativa: RI, basada en reconocimiento de patrones, muestreo estadístico, aprendizaje maquinal, probabilidad,…

La meta de RI: encontrar documentos relevantes rápidamente

RI será un área de investigación mientras los métodos existentes no sean suficientemente efectivos y eficientes simultáneamente



Medidas de efectividad de RI

Precisión (o “especificidad”)

Cobertura (o “exhaustividad”)

 

 

 

Visión Lógica de los Documentos

Es la representación de documentos y/o páginas web que forman parte de una colección (sistema de IR).

 
La forma más común de representar un documento de texto es por un sistema de términos indexados o palabras llaves.
Estos términos son extraídos con el siguiente proceso:

 
Para la lematización los "stopwords" generalmente se utilizan listas de palabras, ya sean de un lenguaje controlado (alguna especialidad) o bien de un idioma particular.
Por otro lado para realizar el “stemming” (reducir palabras de su raíz gramatical) se emplea el algoritmo de Porter, solo que hay que tener en cuenta el idioma a utilizar ya que por lo general se encuentra en inglés aunque hay versiones para español.
http://www.tartarus.org/~martin/PorterStemmer/
 

Existen 2 tipos de tareas principales en la recuperación de información:

  • Las centradas en la computadora: consiste en construir un índice eficiente, procesar las consultas del usuario con un alto rendimiento y algoritmos (modelos de recuperación) que mejoren la calidad de respuesta del sistema.
  • Las centradas en el humano: consiste principalmente en estudiar las necesidades del usuario, saber cómo afecta a la organización, operación y visualización de resultados en el sistema de recuperación.


 

8.2 Modelos de Recuperación

Modelos clásicos de RI

Booleano, vectorial y probabilístico

Diseñados para colecciones de texto

El modelo lógico de los documentos consiste de términos” o palabras que se refieren (indexan) al tema principal tratado

Algunas propiedades útiles:

  • Los términos que aparecen en casi todos los documentos no son útiles
  • Algunos términos pueden tener mayor relevancia con respecto a un documento dado, lo que se puede denotar por un “peso” del término
  • Para un término ki y un documento dj, wi,j >=0 denota la importancia del término para describir el contenido del documento
  • Para una colección con t términos, puede definirse el vector Dj = (w1,j, w2,j,… wt,j)

8.2.1 Clasificación

 

8.2.2 Modelo Booleano

El modelo Boleano, es un modelo de recuperación simple basado en la teoría fija y álgebra de Boolean, este modelo proporciona un grupo de trabajo que es fácil de usar por un usuario común de un sistema de IR. Además, las llamadas se especifican como expresiones de Boolean que tienen la semántica precisa.
Dado su simplicidad inherente y formalismo, el modelo de Boolean recibió la gran atención y se adoptó por muchos de los sistemas bibliográficos comerciales.

De este modelo se pueden destacar los siguientes puntos:

  • La relevancia es binaria: un documento es relevante o no lo es.
  • Consultas de una palabra: un documento es relevante si contiene la palabra.
  • Consultas AND: Los documentos deben contener todas las palabras.
  • Consultas OR: Los documentos deben contener alguna palabra.
  • Consultas A BUTNOT B: Los documentos los documentos deben ser relevantes para A pero no para B.
    ·        Ejemplo: lo mejor de Maradona
    Maradona AND Mundial
    AND (( México ’86 OR Italia ’90) BUTNOT U.S.A. ’94)
  • Es el modelo mas primitivo, sin embargo es el mas popular.

¿Por qué es malo?

  • No discrimina entre documentos más y menos relevantes.
  • Da lo mismo que un documento contenga una o cien veces las palabras de consulta.
  • Da lo mismo que cumpla una o todas las cláusulas de un OR.
  • No permite ordenar los resultados.
  • Puede resultar confuso
    Ejemplo: Necesito investigar sobre los Aztecas y los Incas
      Aztecas AND Incas
    (cuando en realidad lo que se pretendía era: Aztecas OR Incas).

¿Por qué es popular?

  • Es una de los primeros modelos que se implemento y muchos de los primeros sistemas de IR se basaron en él
  • La idea suele ser común entre los usuarios que la están usando.
  • Es la opción favorita para insertar texto en un RDBMS.
  • Es simple de formalizar y eficiente de implementar.
  • En algunos caso (usuarios expertos) puede ser adecuado.
  • Puede ser útil en combinación con otro modelo ej. Para excluir documentos.
  • Puede ser útil con buenas interfaces.

     

    Tablas posibles para el modelo booleano

    Docs (IdDoc, NombreDoc, FechaPub, …, texto)

    IndiceInv (IdDoc, Term)

    Consulta (Term)

     

    Un pre-proceso puede producir Docs (extrayendo datos de archivos) e

    IndiceInv (vía parser, lematización, eliminación de palabras vacías)

     

    Uso de SQL para el modelo booleano

    Encontrar los ids de documentos que contengan los término “casa” o “blanca”

    select distinct IdDoc from IndiceInv

    where term = ‘casa’ or term = ‘blanca’

    Recuperar el texto de los documentos…

    select texto from Docs

    where IdDoc in

    (select distinct IdDoc from IndiceInv

    where term = ‘casa’ or term = ‘blanca’)

    ¿Cómo se obtendrían los documentos que contienen “casa” y “blanca”?


    SQL para el modelo booleano

    • “AND” usando agregación y agrupación:

    select IdDoc from IndiceInv i, Consulta q

    where i.term = q.term

    group by i.IdDoc

    having count(i.term) = (select count(*) from Consulta)

    en este caso, “where” asegura que se incluyen los términos pedidos,

    group by” agrupa los términos para cada documento,

    y “having” que haya tantos términos en el documento como en la consulta

     

     

 

8.2.3 Modelo de Espacios Vectoriales

 

8.2.3.1 Introducción

Propuesto en 1975, hoy el más popular (con variantes)

También llamado solamente “modelo vectorial”

Generaliza el modelo booleano al manejar pesos no binarios para los términos de cada documento y de la consulta (query)

Determina la similitud entre la consulta y cada documento calculando el ángulo entre sus vectores

La idea principal es que dos documentos son similares si sus vectores apuntan hacia la misma dirección

Un aspecto importante es la determinación del peso de cada término, típicamente basado en su frecuencia:

  • el peso aumenta entre más ocurre en un documento dado
  • el peso disminuye entre más aparece en los demás documentos

 

8.2.3.2 Algoritmo

Uso de frecuencia inversa (TFIDF)

Considerando

n = número de términos distintos en una colección

tfij = número de ocurrencias en el documento i del término tj

dfj = número de documentos que contienen tj

idfj = log(d/dfj) = frecuencia inversa de documentos, donde d es el número total de documentos

entonces cada vector tiene n componentes

para una gran colección de documentos pequeños, los vectores contendrán muchos ceros

un cálculo del peso para el j-ésimo elemento del documento di es:

 

la similitud entre una consulta Q y un documento Di puede definirse

como el producto de los dos vectores:

 


En 1988 Salton y Buckley proponen modificaciones a las medidas originales, sugiriendo la siguiente fórmula para el cálculo de pesos del término j en el documento i. Esta variación se debió al argumento de que un match de un término con una frecuencia muy alta puede distorcionar a los demás matches entre el query y el documento.

 

Similarity Measures

Para medir la similitud entre los vectores formados por el query y cada documento existen muchas formulas, siendo la del coseno la más popular, ya que de una manera simple calcula el ángulo entre ambos vectores.

 

Conceptos Iniciales:

Teoría de Vectores

 

 

Tablas posibles para el modelo vectorial

Docs (IdDoc, NombreDoc, FechaPub, …, texto)

IndiceInv (IdDoc, Term, tf)

Terms (term, idf)

Consulta (term, tf)

Un pre-proceso puede producir Docs (extrayendo datos de archivos) e

IndiceInv (vía parser, lematización, eliminación de palabras vacías)

Terms puede producirse mediante:

insert into terms

select term, log(N/count(*))

from IndiceInv

group by term

donde N es el número total de documentos y se conoce o se puede obtener previamente (select count(*) from Docs)

Consulta es solamente una representación tabular de la petición del usuario para facilitar el cálculo del índice de similitud

 

 

SQL para espacios vectoriales usando TFIDF

select i.IdDoc, sum(q.tf * t.idf * i.tf * t.idf)

from consulta q, IndiceInv i, Terms t

where q.term = t.term

and i.term = t.term

group by i.IdDoc

order by 2 desc

• “where” garantiza que se incluyen sólo terminos de la consulta,

“order by”, que se ordenan según el coeficiente de similitud

 

 

Cálculo del coseno del ángulo

Tablas intermedias:

pesos_docs(IdDoc, peso)

peso_q(peso)

 

Generación de tablas intermedias:

insert into pesos_docs

select IdDoc, sqrt(sum(i.tf * t.idf * i.tf * t.idf))

from IndiceInv i, Terms t

where i.term = t.term

group by IdDoc

 

insert into peso_q

select sqrt(sum(q.tf * t.idf * q.tf * t.idf ))

from consulta q, Terms t

where q.term = t.term


Cálculo del coseno del ángulo

select i.IdDoc, sum(q.tf * t.idf * i.tf * t.idf) / (dw.peso * qw.peso)

from consulta q, IndiceInv i, terms t,

pesos_docs dw, peso_q qw

where q.term = t.term AND

i.term = t.term AND

i.IdDoc = dw.IdDoc

group by i.IdDoc, dw.peso, qw.peso

order by 2 desc


 

 

8.2.3.3 Herramientas

Producto

Lenguaje

Modelos

Indexamiento

API desarrollo

Licencia

Managing Gigabytes

C/C++, envoltura Java

Vectorial

Propietario

Ninguno

Open Source

Xapian

C/C++

Probabilístico

Propietario

Limitado

Open Source

Lucene

Java

Vectorial

Propietario

Abierto y extendible

Open Source

MySQL FullText

C/C++ Java

(SMART)

Vectorial

Propietario ISAM

SQL

Open Source

Egothor

Java

Booleano Extendido

Propietario

Ninguno

Open Source

MySQL Fulltext

Creación de tabla y utilización de Match

mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
-> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
-> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
-> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
-> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
-> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

Mostrar los resultados incluyendo la relevancia de cada uno

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
| 1 | 0.64840710366884 |
| 2 | 0 |
| 3 | 0.66266459031789 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

Ejemplo que recupera los resultados y sus scores de similitud.

mysql> SELECT id, body, MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root') AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
| 6 | When configured properly, MySQL ... | 1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

Con la versión 4.0.1 se pueden hacer búsquedas a texto completo incluyendo operadores booleanos.

mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title | body |
+----+------------------------------+-------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 2 | How To Use MySQL Efficiently | After you went through a ... |
| 3 | Optimising MySQL | In this tutorial we will show ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

 

Lucene

Características

 

  • Concurrencia
  • Diferentes "ports": Perl, Python, C++, .Net, Ruby
  • Scoring

Diferentes tipos de Fields

Field method type
Analyzed
Indexed
Stored
Usage
Field.Keyword(String, String)
Field.Keyword(String, Date)
X
X
Telephone and Social Security numbers, URLs, personal names
Dates
Field.Unindexed(String,String)
X
Document type (pdf, html, etc), if not used as a search criteria
Field.Unstored(String, String)
X
X
Document titles and content
Field.Text(String, String)
X
X
X
Document titles and content
Field.Text(String, Reader)
X
X
Document titles and content

 

Core Classes

  • IndexWriter: crea el índice y agrega documentos a éste
  • Directory: la ubicación del índice, se puede tener un FSDirectory o un RAMDirectory, dependiendo si se desea tener dicho índice en disco o en memoria
  • Analyzer: proceso que analiza y limpia el texto (stop words, stemming) antes de que sea indexado
  • Document: una colección de Fields
  • Field: pareja de un nombre y valor, con que sirven para identificar las distintas partes de un documento; estas parejas pueden ser tan simples como "id" y "234" o bien tan complejas como texto completo "contenido" y "Había una vez...."
  • IndexSearcher: abre y emplea el índice en read-only para realizar las búsquedas
  • Term: unidad básica de búsqueda (son creados por el indexer)
  • Query: distintas subclases para crear queries, BooleanQuery, PhraseQuery, RangeQuery, etc.
  • TermQuery: un Term asociado a un query el cual puede poseer un nivel de "boost" para darle mayor peso sobre otros términos
  • Hits: contenedor de apuntadores hacia los resultados ranqueados de una búsqueda

 

Ejemplo de programación con Lucene

   1:/*
   2: *  Copyright (C) 2003  <Interactive and Cooperative Technologies Laboratory>
   3: *  This program is free software; you can redistribute it and/or modify
   4: *  it under the terms of the GNU General Public License as published by
   5: *  the Free Software Foundation; either version 2 of the License, or
   6: *  (at your option) any later version.
   7: *  This program is distributed in the hope that it will be useful,
   8: *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   9: *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10: *  GNU General Public License for more details.
  11: *  You should have received a copy of the GNU General Public License
  12: *  along with this program; if not, write to the Free Software
  13: *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14: *  Copyright (C) 2003 UDLA-P
  15: */
  16:/**
  17: *@(#)JUIRDBC.java    Date Author Changes 2003 Carlos Proal Created
  18: */
  19:
  20:
  21:
  22:import org.apache.lucene.index.*;
23:import org.apache.lucene.analysis.standard.*;
24:import org.apache.lucene.document.*;
25:import org.apache.lucene.search.*;
26:import org.apache.lucene.queryParser.QueryParser;
27:import org.apache.lucene.analysis.Analyzer;
28: 29:import java.io.*;
30:import java.util.*;
31: 32:/** 33: * Class to serve between applications and index files to use retrieval models 34: * with or without Hermes easier 35: * 36: *@author carlos 37: *@created April 16, 2003 38: */ 39:public class JUIRDBC { 40: 41: private String indexfile;
42: private boolean store;
43: 44: 45: 46: /** 47: * Constructor for the JUIRDBC object 48: * 49: *@param indexfile Index file to store/retrieve terms information 50: *@param store true store full documents too, false just store terms 51: */ 52: public JUIRDBC(String indexfile, boolean store) { 53: this.indexfile = indexfile;
54: this.store = store;
55: 56: } 57: 58: 59: /** 60: * Gets from the index file the information requiered for Hermes in the 61: * ExtendedBoolean and Vectorial Models The Document objects returned 62: * contain: resource id of the document containing a term the term itself 63: * tf, term frequency in the document maxtf=1, because we cant determine 64: * this directly idf, inverse frequency of the term related to the 65: * collection* 66: * 67: *@param terms vector containing the query terms 68: *@return vector of mx.udlap.ict.u_dl_a.irserver.dcollections.doctype.Document 69: * objects 70: */ 71: public Vector getFromCollectionTfIdf(Vector terms) { 72: ArrayList vector = new ArrayList();
73: try { 74: IndexReader ireader = IndexReader.open(indexfile);
75: for (int i = 0; i < terms.size(); i++) { 76: TermDocs tdocs = ireader.termDocs(new Term("contents", (String) terms.elementAt(i)));
77: while (tdocs.next()) { 78: mx.udlap.ict.u_dl_a.irserver.dcollections.doctype.Document document =
new
mx.udlap.ict.u_dl_a.irserver.dcollections.doctype.Document("" + ireader.document(tdocs.doc()).get("id"), (String) terms.elementAt(i),
"" + tdocs.freq(), "" + 1,
"
" + Math.log(ireader.numDocs() / ireader.docFreq(new Term("contents", (String) terms.elementAt(i)))));
79: vector.add(document);
80: 81: } 82: 83: } 84: ireader.close();
85: } catch (Exception e) { 86: e.printStackTrace();
87: } 88: System.out.println("Vector de documentos size= " + vector.size());
89: Collections.sort(vector);
90: return new Vector(vector);
91: } 92: 93: 94: /** 95: * Gets a lucene Document of the specified id, A document contain the some 96: * section, identifies by a name This means that even we chose not to store 97: * the document we will have a result 98: * 99: *@param id Unique identifier of the resource 100: *@return org.apache.lucene.document.Document value, null 101: * if resource doesnt exist 102: *@exception IOException Exception 103: */ 104: public org.apache.lucene.document.Document getResource(String id) throws IOException { 105: IndexReader ireader = IndexReader.open(indexfile);
106: TermDocs tdocs = ireader.termDocs(new Term("id", id));
107: 108: if (tdocs.next()) { 109: return ireader.document(tdocs.doc());
110: } 111: 112: return null;
113: } 114: 115: 116: /** 117: * Gets a list of all the resources(ids) in current index 118: * 119: *@return vector containing ids 120: *@exception IOException Exception 121: */ 122: public Vector getListResources() throws IOException { 123: Vector vector = new Vector();
124: IndexReader r = IndexReader.open(indexfile);
125: 126: int num = r.numDocs();
127: for (int i = 0; i < num; i++) { 128: if (!r.isDeleted(i)) { 129: org.apache.lucene.document.Document d = r.document(i);
130: vector.add(d.get("id"));
131: 132: } 133: } 134: TermEnum te = r.terms();
135: int w = 0;
136: while (te.next()) { 137: w++;
138: } 139: System.out.println(w);
140: r.close();
141: return vector;
142: } 143: 144: 145: /** 146: * Establish connection with a index service Currently just initialize the 147: * file because there is no such service 148: * 149: *@exception IOException Description of Exception 150: */ 151: public void openConnection() throws IOException { 152: if (IndexReader.indexExists(indexfile) == false) { 153: IndexWriter writer = new IndexWriter(indexfile, new StandardAnalyzer(), true);
154: writer.close();
155: } 156: } 157: 158: 159: /** 160: * Termines communication with index service 161: * 162: *@exception IOException Exception 163: */ 164: public void closeConnection() throws IOException { } 165: 166: 167: 168: /** 169: * Adds a resource (or terms of) to the index file 170: * 171: *@param id Unique identifier of the resource 172: *@param file Resource/document to be added 173: *@exception IOException Exception 174: */ 175: public void addResource(String id, File file) throws IOException { 176: 177: IndexWriter writer = new IndexWriter(indexfile, new StandardAnalyzer(), false);
178: writer.addDocument(fileToDocument(id, file));
179: writer.optimize();
180: writer.close();
181: 182: } 183: 184: 185: /** 186: * Removes a resource (and/or its terms) from the index file 187: * 188: *@param id id of document to be deleted 189: *@exception IOException Exception 190: */ 191: public void deleteResource(String id) throws IOException { 192: IndexReader ireader = IndexReader.open(indexfile);
193: TermDocs tdocs = ireader.termDocs(new Term("id", id));
194: 195: if (tdocs.next()) { 196: ireader.delete(tdocs.doc());
197: } 198: 199: ireader.close();
200: 201: } 202: 203: 204: /** 205: * Search a query with lucene 206: * 207: *@param line string of terms to be searched 208: *@return lucene hits 209: *@exception Exception Exception 210: */ 211: public Hits search(String line) throws Exception { 212: Searcher searcher = new IndexSearcher(indexfile);
213: Analyzer analyzer = new StandardAnalyzer();
214: 215: Query query = QueryParser.parse(line, "contents", analyzer);
216: System.out.println("Searching for: " + query.toString());
217: 218: return searcher.search(query);
219: } 220: 221: /** 222: * Search a query with lucene specifying the file to search 223: * just to show the PhraseQuery feature 224: * 225: *@param line string of terms to be searched 226: *@return lucene hits 227: *@exception Exception Exception 228: */ 229: public Hits search(String filename, String line) throws Exception { 230: Searcher searcher = new IndexSearcher(indexfile);
231: Analyzer analyzer = new StandardAnalyzer();
232: 233: Query query = QueryParser.parse(line, "contents", analyzer);
234: PhraseQuery phrasequery=new PhraseQuery();
235: phrasequery.add(new Term("path",filename));
236: BooleanQuery bquery=new BooleanQuery();
237: bquery.add(query,true,false);
238: bquery.add(phrasequery,true,false);
239: System.out.println("Searching for: " + bquery.toString());
240: 241: return searcher.search(bquery);
242: } 243: 244: 245: /** 246: * Converts a file to Lucene's specification of Document The document 247: * contains two fields: id - the document id contents - file content 248: * 249: *@param id identifier of current document 250: *@param f file to be added 251: *@return Document Value 252: *@exception java.io.FileNotFoundException Exception 253: */ 254: private org.apache.lucene.document.Document fileToDocument(String id, File f)
255: throws java.io.FileNotFoundException { 256: 257: // make a new, empty document 258: org.apache.lucene.document.Document doc = new org.apache.lucene.document.Document();
259: 260: doc.add(Field.Keyword("id", id));
261: // Add the path of the file as a field named "path". Use a Text field, so 262: // that the index stores the path, and so that the path is searchable 263: doc.add(Field.Keyword("path", f.getName()));
264: 265: // Add the last modified date of the file a field named "modified". Use a 266: // Keyword field, so that it's searchable, but so that no attempt is made 267: // to tokenize the field into words. 268: doc.add(Field.Keyword("modified",
269: DateField.timeToString(f.lastModified())));
270: 271: // Add the contents of the file a field named "contents". Use a Text 272: // field, specifying a Reader, so that the text of the file is tokenized. 273: // ?? why doesn't FileReader work here ?? 274: FileInputStream is = new FileInputStream(f);
275: Reader reader = new BufferedReader(new InputStreamReader(is));
276: try { 277: char[] documento = new char[new Long(f.length()).intValue()];
278: FileReader freader = new FileReader(f);
279: freader.read(documento, 0, new Long(f.length()).intValue());
280: if (store) { 281: doc.add(Field.Text("contents", new String(documento)));
282: } else { 283: doc.add(Field.Text("contents", reader));
284: } 285: 286: } catch (Exception e) { 287: } 288: // return the document 289: return doc;
290: } 291: 292: 293: public static void main(String args[])
294: { 295: if(args.length<1)
296: { 297: System.err.println("Falta incluir la busqueda entre comillas, ej \"xml arbol xsl fo\"");
298: return;
299: } 300:
301: try 302: { 303: File dir=new File("lucene.idx");
304: if(dir.exists())
305: { 306: File files[]=dir.listFiles();
307: for(int j=0;j<files.length;j++)
308: files[j].delete();
309: } 310: 311: JUIRDBC lucene=new JUIRDBC("lucene.idx",true);
312: lucene.openConnection();
313: lucene.addResource("syllabus",new File("/home/digital/html/ict-pr2005/is346/syllabus.html"));
314: lucene.addResource("01",new File("/home/digital/html/ict-pr2005/is346/admon01.html"));
315: lucene.addResource("02",new File("/home/digital/html/ict-pr2005/is346/admon02.html"));
316: lucene.addResource("03",new File("/home/digital/html/ict-pr2005/is346/admon03.html"));
317: lucene.addResource("04",new File("/home/digital/html/ict-pr2005/is346/admon04.html"));
318: lucene.addResource("05",new File("/home/digital/html/ict-pr2005/is346/admon05.html"));
319: lucene.addResource("05_hibernate",new File("/home/digital/html/ict-pr2005/is346/admon05_hibernate.html"));
320: lucene.addResource("05_ejb",new File("/home/digital/html/ict-pr2005/is346/admon05_ejb.html"));
321: lucene.addResource("05_ldap",new File("/home/digital/html/ict-pr2005/is346/admon05_ldap.html"));
322: lucene.addResource("06",new File("/home/digital/html/ict-pr2005/is346/admon06.html"));
323: lucene.addResource("07",new File("/home/digital/html/ict-pr2005/is346/admon07.html"));
324: lucene.addResource("08",new File("/home/digital/html/ict-pr2005/is346/admon08.html"));
325: lucene.addResource("09",new File("/home/digital/html/ict-pr2005/is346/admon09.html"));
326: lucene.addResource("10",new File("/home/digital/html/ict-pr2005/is346/admon10.html"));
327: lucene.addResource("11",new File("/home/digital/html/ict-pr2005/is346/admon11.html"));
328:
329: if(args.length=1)
330: Hits hits=lucene.search(args[0],args[1]);
331: for(int i=0;i<hits.length();i++)
332: { 333: Document doc=hits.doc(i);
334: System.out.println(hits.score(i)+" "+hits.id(i)+" "+doc.getField("id")+" "+doc.getField("path"));
335:
336: } 337: lucene.closeConnection();
338: 339: }catch(Exception e)
340: { e.printStackTrace(); } 341: 342: } 343: 344: 345:}

 

Uso de vectores para encontrar similitudes con Lucene (fragmento cap.5 Lucene in Action)

8.2.5 Modelo Booleano Extendido

 

8.2.5 Modelo LSI (Latent Semantic Indexing)

La meta es calcular la similitud query-documento haciendo matching entre conteptos en vez de términos

La manipulación de matrices es empleada para identificar los "key concepts"

Singular value decomposition (SVD) es usada para reordenar el espacio de términos-documentos para reflejar los patrones asociacitivos más importantes e ignorar las pequeñas y menos importantes diferencias (Deerwester, JASIS, 1990).

Calcular la matriz, X
- Calcular la SVD de X
- Lo anterior resultará en 3 matrices
- X = T S D
- S, contiene |D| singular values donde |D| es el número de documentos
- Escoger los k más representativos para formar S'. Esta es la parte interesante ya que escogiendo todo |D| resultaría en la matriz original, mientras que escoger valores menores resultará en un "fuzzier matrix".
- Eliminar las columnas correspondientes de T y D para formar T' y D'.
- Ahora calcular X' = T' S' D'?

 

Empleando la nueva X'
- Comparar 2 términos
- Tomar el producto punto de 2 vectores (renglón) de X'
- Comparar 2 documentos
- Tomar el producto punto de 2 vectores (columna) de X'
- Comparando un query con un documento
- Se necesita hacer que el query parezca otro documento, esto se puede hacer mapeando el queru en un espacio bidimensional: (qT)(T')(S')-1

 

Las operaciones de SVD pueden hacerse con paquetes matriciales como JAMA o el package javax.vecmath

 

8.3 Estrategias para mejorar RI

Se han propuesto mecanismos que mejoran la recuperación de los modelos “clásicos”

Funcionan agregando o eliminando términos de la consulta original o limitando el espacio de búsqueda

Cada estrategia puede operar con distintos modelos (como “utilerías”) y su desempeño es altamente variable dependiendo de la naturaleza de la colección (heurísticas)



Algunas estrategias:

Retroalimentación de relevancia

Los t términos más pesados de los n documentos más relevantes se agregan a la consulta original para formar una nueva consulta

Pre-clasificación (clustering)

La colección se organiza en grupos y la consulta se compara solamente con los grupos que se consideran relevantes

Recuperación en pasajes

La consulta se aplica solo a porciones (pasajes) de los documentos que se consideran lo más relevante

Identificación de frases (parsing)

Se aplican reglas o listas de frases conocidas que se tratan como términos (“New York”, “Ciudad Juárez”, etc.)

• N-gramas

La consulta se divide en secuencias de caracteres y se usan en lugar de los términos originales—resistentes a errores de OCR e independientes del idioma

Tesauros

Se usan términos relacionados para búsquedas semánticas

Redes semánticas

Se generan jerarquías de conceptos para enriquecer los términos de búsqueda

Análisis de regresión

Se usan técnicas estadísticas para identificar las variables (parámetros) que hacen que un documento sea relevante y luego se usan para buscar otros documentos relevantes


8.4 Aplicaciones "ready to use"