Retokenizando con spaCy

Para los que no están en contexto, spaCy es una librería de Python que provee funciones de PLN (procesamiento de lenguage natural, “NLP” en inglés) de una forma por demás fácil en comparación con, por ejemplo, NLTK.

Aunque conocía de su existencia, no había trabajado con spaCy hasta ahora que lo probé en el proyecto que tengo entre manos en el trabajo. Me era más familiar NLTK a pesar de haberlo usando en su mayoría en la versión 1 (van en la 3.5 al momento de escribir esto), pero para varias tareas spaCy es mucho más “directo”. Digamos que NLTK te da mucho poder, pero hay que ser mucho más específico al momento de manejarlo. En cambio, spaCy realiza muchas más acciones con menos interacción, lo cual puede ser bueno o extremo dependiendo del objetivo.

Lo interesante aquí para mí es nlp.pipeline. Una simple función, que por lo general la llaman nlp (pero uno puede definir el nombre),  aplica una serie de algoritmos de análisis y reconocimiento, pero antes realiza el proceso de “tokenizar” el texto, es decir, dividirlo en entidades llamadas “tokens”, que son secuencias de caracteres agrupados en unidades semánticas. Es fácil irse con la finta de que todos los tokens son palabras, pero no es así. Existen además diferentes maneras de tokenizar, y dependiendo de la usada es el resultado que se tendrá. Por ejemplo, una de las maneras más fácil de tokenizar es agrupando caracteres en un texto separado por espacios, como este post, por ejemplo. Obviamente una tokenización así no serviría en idiomas como el japonés, donde las palabras no están separadas por espacios, pero ésa es otra historia. También es necesario destacar que separar por espacios tampoco es una forma ideal de tokenizar, incluso lenguajes como inglés, pero en sí no se puede dar una respuesta correcta sin saber cuál es el objetivo final. De eso depende la forma de crear tokens.

En el caso del análisis que estaba realizando (en inglés), requería manejar palabras como “well-known”, “state-of-the-art”, es decir, palabras compuestas por múltiples otras palabras, unidas por un guión (entre otros casos que no necesito nombrar), como un token. El problema es que el tokenizer de spaCy separa las palabras también por guiones, y estos a su vez forman tokens. Por ejemplo:

“well-known”

es tokenizado como

“well”, “-“, “known”

Cada elemento es un token, así que contiene más que el simple texto: su función gramatical, su forma base, entre otras cosas, todo gracias a que spaCy ejecuta las funciones de reconocimiento y análisis después de la tokenización, pero todo sucede dentro del mismo pipeline. Además, como cada token es identificado por separado, casos como el de “state-of-the-art” deben ser tratados ya que la palabra completa es un adjetivo, pero “art” por sí mismo es correctamente identificado como sustantivo. Algo se tiene que hacer.

Continue reading “Retokenizando con spaCy”

Concepto de similaridad y modelo de espacio vectorial

¿Cómo definimos la similaridad entre 2 cosas?

Es fácil decir que una persona se parece a otra, pero ¿con base en qué lo aseguramos? Color de piel, ojos, rasgos en común, tipo de peinado, forma de la cara, etc., son algunos de los factores que nos ayudan a decidir si una persona es similar a otra. Pero, ¿cómo llevamos esto a palabras?

Cuando decimos que una palabra “se parece” a otra, podemos enforcarnos en 2 aspectos: sintáctico y semántico. Por ello, necesitamos encontrar en cada caso factores que nos ayuden a determinar qué tan similares o diferentes son 2 palabras. Por el momento, aquí nos enfocaremos al aspecto sintáctico.

Continue reading “Concepto de similaridad y modelo de espacio vectorial”

Índice invertido, búsqueda booleana y vector de términos

Ya tenía un buen rato de no publicar nada aquí. Es un tema al que le quiero dar mucho más seguimiento, así que de lleno al tema.

En la entrega anterior vimos stemming, el cual es un paso importante en el preproceso de documentos, ya que nos permite trabajar con las raíces de las palabras y no con sus derivaciones, reduciendo el número de vocablos con el que tenemos que trabajar y al mismo tiempo “juntando” palabras que posiblemente tengan alguna relación (como “caminar” y “caminante”). Ahora es momento de usarlo para crear un índice que nos ayude a encontrar documentos fácilmente.

Continue reading “Índice invertido, búsqueda booleana y vector de términos”

Stemming

Al momento de extraer las palabras para trabajar con ellas (como con TF-IDF), y después de quitar las que no nos sirven, ya podemos comenzar a trabajar en la creación de un índice. Sin embargo, podemos todavía aplicar una tarea más a esas palabras con objeto de reducir su número, y al mismo tiempo, de “juntar” las que tienen la misma raíz.

De eso se trata el stemming: tomamos una palabra y obtenemos su stem, que en español sería el equivalente al lexema de la palabra; es decir: la parte de ella que no cambia y contiene el significado esencial. Por ejemplo, si tenemos las palabras “niño”, “niña”, “niños”, “niñas”, el lexema de todas ellas es “niñ”. Entonces, al momento de filtrar las palabras y luego contarlas, en vez de tener algo como:

niño    6

niña   13

niños 16

niñas 4

… es recomendable hacer stemming y obtener el lexema de las palabras. Nos quedaría así:

niñ 39

“Agrupamos” muchos conceptos en uno solo. Ya en una aplicación como un motor de búsqueda, al momento de que el usuario busca algo, aplicamos stemming también en la búsqueda. Así. algo como:

“¿Cuántos niños hay en Guadalajara?”

se traduciría en:

niñ guadalajar

(después de quitar las stopwords, los signos y hacer stemming) que es lo que a final de cuentas usaría un motor de búsqueda tradicional.

No necesariamente todos los motores de búsqueda hacen stemming; todo depende de cuál sea la finalidad del mismo. Por ejemplo, uno que tome en cuenta las conjugaciones de los verbos usaría las palabras completas en vez de sintetizarlas usado lexemas (lo cual tendría sentido para el objetivo que persigue). No obstante, en los motores de búsqueda tradicionales (que trabajan con modelos matemáticos) el stemming es un paso cotidiano que se realiza previo a la creación de un índice (que ya detallaré en otro post).

Stop Words: palabras que no dicen mucho

Cuando hablé sobre TF-IDF, mencioné que el proceso había que repetirse para cada palabra en cada documento, pero obviamente esto no es cierto. En muchos idiomas (porque no puedo asegurar que en todos) existen palabras que son muy comunes, que pueden aparecen en casi cualquier lugar y, por tanto, que no reflejan o contienen información para poder separar un documento de entre un conjunto. A esas palabras se les llama stop words (palabras vacías), y, para poder representar de forma matemática un documento de forma más exacta, hay que filtrarlas.

¿Qué palabras son stop words?

  • Preposiciones
  • Conjunciones y disyunciones
  • Verbos copulativos
  • Palabras que, estadísticamente, son muy comunes.

Si no pasamos el documento por la coladera de stop words, al momento de realizar una búsqueda esas palabras van a crear “ruido”. Se trata de identificar vocablos que sean incomunes, que nos puedan decir más sobre el documento (en qué se enfoca, en que se diferencia de los otros); si dejamos palabras como “de”, “y”, “es”, “que”, podemos casi afirmar que aparecerán en cada documento, haciendo más difícil encontrar la información que se requiere.

¿Dónde consigo una lista de stop words en español?

Una rápida búsqueda en Google revela algunos sitios que ofrecen sus listas. Generalmente funcionan, pero siempre es bueno darles una revisada, y sobre todo, afinar la lista de acuerdo a los documentos que vayamos a analizar. Lo anterior aplica cuando vamos a realizar una búsqueda en un conjunto  determinado (o una búsqueda vertical en la red), ya que, por ejemplo, puede ser que la palabra “xyz” sea muy recurrente en ellos y sea necesario filtrarla.

Aquí dejo un par de ligas. Para encontrar más, ya saben dónde 😀

http://snowball.tartarus.org/algorithms/spanish/stop.txt

http://www.elwebmaster.com/referencia/stopwords-en-espanol

TF-IDF: pesando las palabras

En el área de recuperación de información, la idea es obtener una serie de documentos considerados relevantes con respecto a ciertas palabras o expresiones. En términos generales, la idea es encontrar los documentos que más se acerquen a una búsqueda realizada con palabras clave o con expresiones más complicadas (como lenguaje natual propiamente). Ejemplo: una búsqueda en Google. Ponemos lo que estamos buscando y Google muestra una serie de resultados que calcula como importantes para esa búsqueda.

Es evidente que no existe una sola forma de encontrar los documentos, y más que encontrarlos, de asignarles un orden. Es muy fácil tener una colección de documentos y hacer una especie de consulta SQL donde regresemos solamente los documentos que contienen al menos una de las palabras buscadas, pero esto solo nos va a regresar los documentos en el orden que la base de datos los encuentra (o en el que le asignemos en el SELECT). Esta forma de búsqueda es la más simple de todas: búsqueda binaria. Pero, ¿se imaginan que ésta fuera la técnica que Google usara? ¿Cuántos documentos no tendríamos que revisar hasta encontrar (si es que lo hacemos) uno que en verdad contiene la información que se desea encontrar?

ejresgoogle

Google reporta 850,000 resultados para la búsqueda “Vacaciones en Cancún”, pero en la realidad solo muestra hasta el número 1,000. No obstante, son pocas y contadas las veces en las que revisamos más de 100 documentos. El orden importa, y es justamente lo que la recuperación de información trata de resolver.

Una búsqueda binaria no analiza más allá de si un documento contiene o no una o varias palabras; por tanto, así como regresa documentos en los que la palabra X aparece 1 vez, también regresa otros donde aparece 100 veces, por poner un ejemplo. ¿Cuál documento es entonces más importante?

La asignación de orden  se puede realizar de distintas maneras: fecha, autor, número total de palabras en el documento, etc. Entre las muchas formas de llevar a cabo esta tarea, existe la de asignarle peso a las palabras, es decir, de tratar de calcular qué palabras son más relevantes en un texto, y con base en eso decidir cuál documento es más probable que contenga la información buscada.

Continue reading “TF-IDF: pesando las palabras”

Procesamiento de lenguaje natural: ¿qué es?

El procesamiento de lenguaje natural es una rama de la inteligencia artificial que, explicado de la forma más simple, se dedica a tratar de hacer comprender a la computadora el lenguaje que nosotros, los humanos, usamos, sea español, inglés, japonés, klingon, etc.

Una vez que la computadora entienda el lenguaje natural, podemos realizar muchas tareas de forma más simple. Por ejemplo: imaginen que tienen que leer una serie de artículos en el periódico, todos ellos muy largos. Como en todo escrito, hay partes que son más importantes que otras; con procesamiento de lenguaje natural podríamos hacer que la computadora “leyera” esos artículos por nosotros y nos mostrara un resumen de cada uno, haciendo la lectura mucho más simple, menos tediosa y, sobre todo, conteniendo los puntos más importantes de cada escrito.

Lo anterior es solo por poner un ejemplo; sabemos de antemano que empresas como Google, Yahoo y Microsoft usan procesamiento de lenguaje natural para poder encontrar rápidamente documentos relevantes a una consulta generada en sus motores de búsqueda, siendo Google el que lleva la delantera. Así también, nos encontramos con programas de traducción automática, los cuales reciben un texto en un idioma X, lo analizan, y producen una respuesta el mismo escrito en otro idioma Y sin ayuda de traductores humanos.

Usos hay muchos, técnicas para hacer cada tarea, también, pero como en toda área de la IA actual, quedan todavía muchos problemas por analizar, por atacar, por mejorar la respuesta que ofrecen, por mejorar la velocidad y el performance de sus algoritmos… en fin, hay mucho trabajo que realizar.

Pueden leer un poco más en este documento que creé para las pláticas que di en México en abril de este año: Un vistazo al procesamiento de lenguaje natural

Cuando llegué a Japón, en mi vida había pensado, o siquiera conocido, sobre procesamiento de lenguaje natural; de hecho, yo llegué aquí con la idea de trabajar principalmente en procesamiento de imágenes, pero ya ven las vueltas que da el destino 爆笑 Toda mi investigación (lo poco que hice por acá) es respecto a características del idioma japonés y de cómo se pueden analizar al momento de traducir a español, tratando de enfocarme en el modo subjuntivo de este último. Por ahí trabajé también un poco con analizas de citas de texto (modo directo o indirecto), pero de todo esto ya hablaré con más calma en futuros posts. Solamente no quería comenzar a divagar escribiendo sobre temas más técnicos sin antes presentar, aunque sea de forma breve, la base de todos ellos.