====== Natural Language Processing utilizando NLTK ======
//NLTK es un paquete para el procesamiento de lenguaje natural disponible en Python//.
===== Funciones básicas del NLTK =====
Para iniciar ''nltk'' tendremos que hacer:
import nltk
==== Tratamiento de textos ====
Los textos pertenecen a la clase ''nltk.text.Text''.
from nltk.book import *
text1 # muestra el texto 1.
text1.concordance('monstrous') # busca la palabra 'monstrous'.
text1.similar('monstrous') # muestra palabras que se encuentran en contextos similares donde se está 'monstrous'.
text2.common_contexts(['very', 'monstrous']) # busca el contexto común para varias palabras.
text1.generate() # genera un texto aleatorio a partir de un texto inicial.
len(text3) # muestra el número de palabras del texto 3.
len(set(text3)) # muestra el número de palabras en el vocabulario del texto 3.
text1.count('monstrous') # cuenta el número de veces que aparece la palabra 'monstrous' en el texto 1.
text1.collocations() # devuelve una lista de collocations
==== Tratar corpus ====
Los corpus son colecciones de textos, en NLTK se nos provee de los siguientes métodos para tratar con ellos:
* ''fileids()'', devuelve el nombre de los ficheros.
* ''fileids([cat])'', devuelve los nombres de ficheros correspondientes a esas categorías.
* ''categories()'', categorías del curpos
* ''raw(e)'', devuelve el contenido de un elemento en el corpus.
* ''words(e)'', devuelve las distintas palabras de un elemento en el corpus.
* ''sents(e)'', devuelve las distintas frases en un elemento de un corpus.
* ''abspath(e)'', la ruta de ese elemento en disco.
* ''encoding(e)'', la codificación de ese elemento.
* ''readme()'', los contenidos del readme de ese corpus.
c = nltk.corpus.gutenberg
c.fileids()
Con NLTK podemos tener instalados [[ai:nlp_with_nltk#corpus_de_ejemplo|corpus de ejemplo]]. \\
Podemos convertir un elemento de un corpus a texto de la siguiente forma:
emma = nltk.Text(nltk.corpus.gutenberg.words('austen-emma.txt'))
=== Cargando tus propios corpus ===
NLTK permite cargar tus propios corpus mediante ''PlainTextCorpusReader'', este admite la ruta de la colección de textos y una expresión regular de los ficheros aceptados:
from nltk.corpus import PlaintextCorpusReader
croot = '/home/alfred/tmp/testdocs'
corps = PlaintextCorpusReader(croot, '.*')
corps.fileids()
corps.words('fortnow10.txt')
Existen otras alternativas para cargar corpus como son el ''BracketParseCorpusReader''... ([[http://nltk.sourceforge.net/corpus.html]])
==== Estadísticas con textos ====
=== FreqDist ===
Con el objeto ''FreqDist'' podemos ver cómo se distribuye la frecuencia de una palabra en el texto (cantidad de las distintas palabras en el vocabulario del texto).
fdist = FreqDist(text1)
fdist.keys() # lista del vocabulario en el texto ordenado por frecuencia
fdist.keys()[:10] # el top 10 de las palabras de un texto
fdist['man'] # devuelve cuantas veces aparece 'man' en el texto
fdist.hapaxes() # palabras que solo aparecen una vez
fdist.freq('monstrous') # frecuencia de una palabra
fdist.N() # número de palabras diferentes
fdist.max() # la palabra que aparece un número mayor de veces
fdist.items() # palabra y número de veces que aparece esta
fdist.plot() # gráfico de la distribución
fdist.plot(cumulative=True) # gráfico acumulado de la distribución
fdist.tabulate() # tabla de frecuencias
=== ConditionalFreqDist ===
Cuando un texto se divide en varias categorías (género, autor...) podríamos mantener distribuciones para cada categoría con un objeto ''ConditionalFreqDist'', el cual es una colección de distintas distribuciones de frecuencia clasificadas por su condición\categoría\tema. \\
Necesita de un conjunto de pares para hacer la distribución:
from nltk.corpus import brown
genre_word = [(genre, word) # Creación de los pares
for genre in ['news', 'romance']
for word in brown.words(categories=genre)]
cfd = nltk.ConditionalFreqDist(genre_word) # Creación de la distribución de frecuencia condicional
cfd.conditions() # news y romance, las "condiciones"
cfd['news'] # palabras de news
cfd['news']['could'] # Objeto FreqDist de la palabra 'could' en 'news'
==== Preproceso del texto ====
=== Tokenizar ===
* ''nltk.word_tokenize(s)'', separa el texto en distintos tokens a partir de espacios en blanco, saltos de línea...
* Podemos tokenizar a partir del método ''re.split(regex, text)''. Con expresiones regulares como ''r'\s+''' (para espacios en blanco, tabulaciones, saltos de línea...), ''r'\W+''' (para tokens que no contengan puntuación)...
* ''nltk.regexp_tokenize(regex, s)'' nos permite tokenizar un texto a partir de una expresión regular.
=== Limpieza ===
* ''nltk.clean_html(s)'', substrae el texto de un string en formato HTML.
=== Segmentar ===
=== Lematizar ===
NLTK permite lematizar a partir del lematizador de WordNet, este elimina los afijos si la palabra resultante está en el diccionario.
wnl = nltk.WordNetLemmatizer()
[wnl.lemmatize(t) for t in tokens]
=== Stemizar ===
NLTK provee de dos stemmers, el de Porter (''nltk.PorterStemmer'') y el de Lancaster (''nltk.LancasterStemmer''), un ejemplo de uso sería:
porter = nltk.PorterStemmer()
[porter.stem(t) for t in tokens]
=== Esquema básico ===
from urllib import urlopen
url = 'http://www.uruloki.org/felipeblog/sitges-2011/el-festival-de-sitges-2011-tira-la-casa-por-la-ventana-y-nos-deja-a-todos-anonadados'
html = urlopen(url).read()
raw = nltk.clean_html(html) # 1. Conseguimos el texto
tokens = nltk.wordpunct_tokenize(raw) # 2. Lo tokenizamos
text = nltk.Text(tokens) # 3. Lo convertimos a objeto Text
words = [w.lower() for w in text] # 4. Lo normalizamos
vocab = sorted(set(words)) # 5. Lo tratamos (p.ej. extracción de vocabulario)
===== Categorizar y taggear palabras =====
===== Clasificar textos =====
===== Extraer información del texto =====
===== Analizar estructuras gramaticales =====
===== Construir gramáticas =====
===== Analizar el significado de expresiones =====
===== Notas =====
==== Libro & ejemplos ====
Para descargarte los módulos de ejemplo y correspondientes al libro simplemente tendremos que poner:
import nltk
nltk.download()
Podremos instalar los sub-módulos que queramos. Si instalamos el del libro tendremos acceso a distintos textos haciendo...
from nltk.book import *
Podemos abrir el shell de test de traducción:
>>> babelize_shell()
NLTK Babelizer: type 'help' for a list of commands.
Babel> how long before the next flight to Alice Springs?
Babel> spanish
Babel> run
0> how long before the next flight to Alice Springs?
1> ¿cuanto tiempo antes del vuelo siguiente a Alice Springs?
2> how long before the flight following to It stakes out Springs?
3> ¿cuanto tiempo antes del vuelo siguiente a él estaca hacia fuera suelta?
4> how long before the flight following to him it stakes towards outside loosen?
5> ¿cuanto tiempo antes de que el vuelo siguiente a él que estaca hacia exterior afloje?
6> how long before the flight following to him that it stakes towards outside relaxes?
7> ¿cuanto tiempo antes del vuelo siguiente a él que estaca hacia exterior se relaja?
8> how long before the flight following to him that it stakes towards outside it relaxes?
9> ¿cuanto tiempo antes del vuelo siguiente a él que estaca hacia afuera se relaja?
=== Corpus ===
Los encontraremos en ''nltk.corpus'' si los tenemos correctamente descargados, estos son:
* ''gutenberg'': libros electrónicos del proyecto Gutenberg.
* ''webtext'': textos relacionados con internet (extractos del foro de Firefox, opiniones de vinos, el guión de //Piratas del Caribe//...)
* ''nps_chat'': conversaciones de chat.
* ''brown'', textos creados en la universidad de Brown. Se les ha agregado el método categorias.
* ''reuters'', noticas del periódico Reuters (también clasificados en categorias).
* ''inaugural'', direcciones.
* ''cess_esp'', corpus en castellano.
* ''udhr'', declaración de los derechos humanos clasificados en 300 lenguas.
=== Lexicos ===
También los encontramos en ''nltk.corpus'':
* ''stopwords'', stopwords clasificados por idiomas. Por ejemplo para acceder a las de inglés haremos: ''nltk.corups.stopwords.words('english')''.
* ''cmudict'', diccionario de pronunciación inglés.
* ''swadesh'', lista de las palabras más utilizadas en los distintos lenguajes. ''nltk.corpus.swadesh.fileids()'' devolvería los idiomas disponibles y ''nltk.corpus.swadesh.words('es')'' las palabras del castellano.
* ''wordnet'' provee de un árbol de palabras relacionadas entre ellas a partir de su significado (''synsets''), lemas (''lemmas'') y demás relaciones léxicas (''hypernym'', ''antonym'', ''entail''...) y, a la vez, de métodos para movernos por este árbol.
=== Notas ===
Funciones útiles para tratar con los recursos:
path = nltk.data.find('corpora/unicode_samples/polish-lat2.txt') # Devuelve la ruta de polish-lat2.txt
==== Regex útiles ====
^ regex ^ Explicación ^
| ''[aeiou]{2,}'' | Palabras con dos vocales seguidas |
| ''^(.*)(ing|ly|ed|ious|ies|ive|es|s|ment)$'' | Estemiza palabras en inglés, devolviendo el estema y el sufijo |
| ''<.*><.*>'' | Tres palabras seguidas donde la última sea //"bro"// |
| ''(<.*>)'' | Los adjetivos que se le agregan a //"a man"//. |