Tutorial de NLP con Python NLTK (ejemplos simples)
En esta publicación, hablaremos sobre el procesamiento del lenguaje natural (NLP del inglés Natural Language Processing) usando Python. Este tutorial de NLP usará la librería de Python NLTK. NLTK es una popular librería de Python que se utiliza para NLP.
Entonces, ¿qué es NLP? y ¿cuáles son los beneficios de aprender NLP?
Tabla de contenidos
¿Qúe es NLP?
En pocas palabras, el procesamiento del lenguaje natural (NLP) consiste en desarrollar aplicaciones y servicios que puedan comprender los idiomas humanos.
Estamos hablando de ejemplos prácticos de procesamiento del lenguaje natural (NLP), como el reconocimiento de voz, la traducción del habla, la comprensión de oraciones completas, la comprensión de sinónimos de palabras coincidentes y la escritura de oraciones y párrafos completos gramaticalmente correctos.
Esto no es todo, puedes pensar en las implementaciones industriales sobre estas ideas y sus beneficios.
Beneficios del NLP
Como todos ya sabes sabes, hay millones de gigabytes diarios generados por blogs, sitios web sociales y páginas web.
Hay muchas empresas que reúnen todos estos datos para comprender a los usuarios y sus pasiones y dar estos informes a las empresas para ajustar sus planes.
Estos datos podrían mostrar que la gente de Brasil está contenta con el producto A, que podría ser una película o cualquier cosa, mientras que la gente de EE. UU. está contenta con el producto B. Y esto podría ser instantáneo (resultado en tiempo real). Al igual que los motores de búsqueda, dan los resultados adecuados a las personas adecuadas en el momento adecuado.
Sabes ademas que los motores de búsqueda no son la única implementación del NLP; hay muchas implementaciones increíbles por ahí.
Implementaciones del NLP
Estas son algunas de las implementaciones exitosas del procesamiento de lenguaje natural (NLP):
- Motores de búsqueda como Google, Yahoo, etc. El motor de búsqueda de Google entiende que eres un técnico, por lo que te muestra resultados relacionados a ti.
- Los feeds de los sitios web sociales como la fuente de noticias de Facebook. El algoritmo de feed de noticias entiende tus intereses mediante el procesamiento de lenguaje natural y muestra anuncios y publicaciones relacionadas con mayor probabilidad que otras publicaciones.
- Motores de voz como Apple Siri.
- Filtros de spam como filtros de spam de Google. No se trata solo del filtro de spam habitual, ahora los filtros de spam entienden qué hay dentro del contenido del correo electrónico y ver si es un correo no deseado o no.
Librerías NLP
Hay muchas librerías de NLP de código abierto y éstas son algunas de ellas:
- Natural language toolkit (NLTK).
- Apache OpenNLP.
- Stanford NLP suite.
- Gate NLP library.
Natural language toolkit (NLTK) es la biblioteca más popular para el procesamiento del lenguaje natural (NLP) que fue escrita en Python y tiene una gran comunidad detrás.
NLTK también es muy fácil de aprender; en realidad, es la biblioteca de procesamiento de lenguaje natural (NLP) más fácil que usará.
En este tutorial de NLP, usaremos la biblioteca Python NLTK.
Antes de comenzar a instalar NLTK, supongo que conoces algunos aspectos básicos de Python para comenzar.
Instalar NLTK
Si está usando Windows o Linux o Mac, puede instalar NLTK usando pip:
$ pip install nltk
Puedes usar NLTK en Python 2.7, 3.4 y 3.5 en el momento de escribir esta publicación.
Alternativamente, puedes instalarlo desde la fuente desde este tar.
Para verificar si la librería NLTK se ha instalado correctamente, puedes abrir la terminal de Python y escribir lo siguiente:
Import nltk
Si todo va bien, eso significa que has instalado correctamente la librería NLTK.
Una vez que instalada la librería NLTK, debes instalar los paquetes NLTK ejecutando el siguiente código:
import nltk nltk.download()
Esto mostrará el descargador NLTK para elegir qué paquetes deben instalarse.
Puedes instalar todos los paquetes ya que sus tamaños son pequeños por lo que no habrá problema. Ahora comencemos el show.
Tokenizar un texto usando Python
Primero, tomaremos el contenido de una página web y luego analizaremos el texto para ver de qué se trata la página.
Utilizaremos el módulo urllib
para rastrear la página web:
import urllib.request response = urllib.request.urlopen('http://php.net/') html = response.read() print (html)
Como puedes ver en la salida impresa, el resultado contiene muchas etiquetas HTML que deben limpiarse.puedes ver en la salida impresa, el resultado contiene muchas etiquetas HTML que deben limpiarse.
Podemos usar BeautifulSoup para limpiar el texto capturado de esta manera:
from bs4 import BeautifulSoup import urllib.request response = urllib.request.urlopen('http://php.net/') html = response.read() soup = BeautifulSoup(html,"html5lib") text = soup.get_text(strip=True) print (text)
Ahora tenemos el texto limpio de la página web rastreada.
Impresionante, ¿verdad?
Finalmente, convirtamos ese texto en tokens dividiendo el texto de esta manera:
from bs4 import BeautifulSoup import urllib.request response = urllib.request.urlopen('http://php.net/') html = response.read() soup = BeautifulSoup(html,"html5lib") text = soup.get_text(strip=True) tokens = [t for t in text.split()] print (tokens)
Contar la frecuencia de palabras
El texto está mucho mejor ahora. Calculemos la distribución de frecuencia de esos tokens usando Python NLTK.
Hay una función en NLTK llamada FreqDist()
hace el trabajo:
from bs4 import BeautifulSoup import urllib.request import nltk response = urllib.request.urlopen('http://php.net/') html = response.read() soup = BeautifulSoup(html,"html5lib") text = soup.get_text(strip=True) tokens = [t for t in text.split()] freq = nltk.FreqDist(tokens) for key,val in freq.items(): print (str(key) + ':' + str(val))
Si buscas el resultado, verás que el token más frecuente es PHP.
Puedes elaborar un gráfico para esos tokens usando una función como esta:
freq.plot(20, cumulative=False)
Desde el gráfico, puedes estar seguro de que este artículo está hablando de PHP.
¡Estupendo!
Hay algunas palabras como The, Of, a, an, y así sucesivamente. Estas palabras son palabras de parada (stop words).
En general, se deben eliminar las palabras de parada para evitar que afecten a nuestros resultados.
Eliminar palabras de parada con NLTK
NLTK contiene listas de palabras prohibidas para la mayoría de los idiomas. Para obtener las palabras de parada en inglés, puedes usar este código:
from nltk.corpus import stopwords stopwords.words('english')
Ahora, modifiquemos nuestro código y limpiemos los tokens antes de trazar el gráfico.
Primero, haremos una copia de la lista, luego iteraremos sobre los tokens y eliminaremos las palabras de parada:
clean_tokens = tokens[:] sr = stopwords.words('english') for token in tokens: if token in stopwords.words('english'): clean_tokens.remove(token)
Puede revisar las funciones de la lista de Python para saber cómo procesar listas
Así que el código final debería ser así:
from bs4 import BeautifulSoup import urllib.request import nltk from nltk.corpus import stopwords response = urllib.request.urlopen('http://php.net/') html = response.read() soup = BeautifulSoup(html,"html5lib") text = soup.get_text(strip=True) tokens = [t for t in text.split()] clean_tokens = tokens[:] sr = stopwords.words('english') for token in tokens: if token in stopwords.words('english'): clean_tokens.remove(token) freq = nltk.FreqDist(clean_tokens) for key,val in freq.items(): print (str(key) + ':' + str(val))
Si revisas el gráfico ahora, verás es mejor que antes ya que no hay palabras de parada en el conteo.
freq.plot(20,cumulative=False)
Tokenizar texto usando NLTK
Vimos cómo dividir el texto en tokens utilizando la función split
; ahora veremos cómo convertir el texto en tokens con NLTK.
Tokenizar el texto es importante ya que el texto no se puede procesar sin tokenizarlo. El proceso de tokenización significa dividir partes más grandes en partes pequeñas.
Puedes convertir párrafos en oraciones y confeccionar frases en palabras según tus necesidades. NLTK contiene un tokenizador de frase y un tokenizador de palabra.
Supongamos que tenemos un texto de muestra como el siguiente:
Hello Adam, how are you? I hope everything is going well. Today is a good day, see you dude.
Para tokenizar este texto en oraciones, usaremos sent_tokenize()
:
from nltk.tokenize import sent_tokenize mytext = "Hello Adam, how are you? I hope everything is going well. Today is a good day, see you dude." print(sent_tokenize(mytext))
La salida es la siguiente:
['Hello Adam, how are you?', 'I hope everything is going well.', 'Today is a good day, see you dude.']
Puede decir que es es un trabajo fácil y no necesito usar el tokenizador NLTK, pues, puedo dividir oraciones usando expresiones regulares ya que cada oración es precedida por punto y espacio.
Bueno, mira el siguiente texto:
Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude.
Uh! La palabra Mr. es una palabra en sí misma. Bien, probemos NLTK:
from nltk.tokenize import sent_tokenize mytext = "Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude." print(sent_tokenize(mytext))
The output looks like this:
['Hello Mr. Adam, how are you?', 'I hope everything is going well.', 'Today is a good day, see you dude.']
¡Estupendo! Funciona como por encanto.
OK, intentemos con el tokenizador de palabras para ver cómo funcionará.
from nltk.tokenize import word_tokenize mytext = "Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude." print(word_tokenize(mytext))
La salida es:
['Hello', 'Mr.', 'Adam', ',', 'how', 'are', 'you', '?', 'I', 'hope', 'everything', 'is', 'going', 'well', '.', 'Today', 'is', 'a', 'good', 'day', ',', 'see', 'you', 'dude', '.']
La palabra Mr. es una palabra como se esperaba.
NLTK usa PunktSentenceTokenizer
, que es parte del módulo nltk.tokenize.punkt
.
Este tokenizer se entrenó bien para trabajar con muchos idiomas.
Tokenizar textos que no están en inglés
Para tokenizar otros idiomas, puedes especificar el idioma de esta manera:
from nltk.tokenize import sent_tokenize mytext = "Bonjour M. Adam, comment allez-vous? J'espère que tout va bien. Aujourd'hui est un bon jour." print(sent_tokenize(mytext,"french"))
El resultado se verá así:
['Bonjour M. Adam, comment allez-vous?', "J'espère que tout va bien.", "Aujourd'hui est un bon jour."]
Lo estamos haciendo bien.
Obtener sinónimos de WordNet
Si recuerdas, instalamos paquetes NLTK usando nltk.download()
. Uno de los paquetes fue WordNet.
WordNet es una base de datos creada para el procesamiento del lenguaje natural. Incluye grupos de sinónimos y una breve definición.
Puedes obtener estas definiciones y ejemplos para una palabra dada como esta:
from nltk.corpus import wordnet syn = wordnet.synsets("pain") print(syn[0].definition()) print(syn[0].examples())
El resultado es:
a symptom of some physical hurt or disorder ['the patient developed severe pain and distension']
WordNet incluye un montón de definiciones:
from nltk.corpus import wordnet syn = wordnet.synsets("NLP") print(syn[0].definition()) syn = wordnet.synsets("Python") print(syn[0].definition())
El resultado es:
the branch of information science that deals with natural language information large Old World boas
Puedes usar WordNet para obtener palabras como esta:
from nltk.corpus import wordnet synonyms = [] for syn in wordnet.synsets('Computer'): for lemma in syn.lemmas(): synonyms.append(lemma.name()) print(synonyms)
El resultado es:
['computer', 'computing_machine', 'computing_device', 'data_processor', 'electronic_computer', 'information_processing_system', 'calculator', 'reckoner', 'figurer', 'estimator', 'computer']
¡Buenísimo!
Obtener antónimos de WordNet
Puedes obtener los antónimos de las palabras de la misma manera. Antes de agregarlos a la matriz, todo lo que tienes que hacer es verificar si cada lema es un antónimo o no.
from nltk.corpus import wordnet antonyms = [] for syn in wordnet.synsets("small"): for l in syn.lemmas(): if l.antonyms(): antonyms.append(l.antonyms()[0].name()) print(antonyms)
El resultado es:
['large', 'big', 'big']
Este es el poder de NLTK en el procesamiento del lenguaje natural.
Derivación regresiva con NLTK (Word Stemming)
La derivación regresiva significa eliminar afijos de las palabras y encontrar la palabra raíz. Ej: La raíz de la palabra trabajando = > trabajo.
Los motores de búsqueda utilizan esta técnica al indexar páginas, puesto que muchas personas escriben versiones diferentes para la misma palabra y todas derivan de la palabra raíz.
Existen muchos algoritmos para la derivación regresiva, pero el algoritmo más utilizado es el algoritmo Porter de derivación regresiva.
NLTK tiene una clase llamada PorterStemmer
que usa el algoritmo de derivación regresiva Porter.
from nltk.stem import PorterStemmer stemmer = PorterStemmer() print(stemmer.stem('working'))
El resultado es:
work
Bastante claro.
Hay algunos otros algoritmos de derivación regresiva como el algoritmo de derivación regresiva de Lancaster.
La salida de este algoritmo muestra resultados un poco diferentes para pocas palabras. Puedes probar ambos para ver el resultado.
Derivación regresiva de palabras no inglesas
SnowballStemmer contiene 13 idiomas además del inglés.
Los idiomas admitidos son:
from nltk.stem import SnowballStemmer print(SnowballStemmer.languages)
'danish', 'dutch', 'english', 'finnish', 'french', 'german', 'hungarian', 'italian', 'norwegian', 'porter', 'portuguese', 'romanian', 'russian', 'spanish', 'swedish'
Puedes usar la función stem
de la clase SnowballStemmer para derivar palabras no inglesas:
from nltk.stem import SnowballStemmer french_stemmer = SnowballStemmer('french') print(french_stemmer.stem("French word"))
Los franceses pueden contarnos sobre los resultados :).
Palabras lematizadoras usando WordNet (Lemmatize Words)
Lematizar palabras es similar a la derivación regresiva; pero, la diferencia es el que la lematización es el mundo real.
A diferencia de la derivación regresiva, cuando intentas derivar algunas palabras, dará como resultado algo como esto:
from nltk.stem import PorterStemmer stemmer = PorterStemmer() print(stemmer.stem('increases'))
El resultado es:
increas
Ahora, si tratamos de lematizar la misma palabra usando NLTK WordNet, el resultado es el correcto:
from nltk.stem import WordNetLemmatizer lemmatizer = WordNetLemmatizer() print(lemmatizer.lemmatize('increases'))
El resultado es:
increase
El resultado puede terminar con un sinónimo o una palabra diferente, pero con el mismo significado.
A veces, si tratas de lematizar una palabra como la palabra playing, terminarás con la misma palabra.
Esto se debe a que la parte del habla predeterminada son sustantivos. Para obtener verbos, debes especificar así:
from nltk.stem import WordNetLemmatizer lemmatizer = WordNetLemmatizer() print(lemmatizer.lemmatize('playing', pos="v"))
El resultado es:
play
En realidad, este es un muy buen nivel de compresión de texto, terminas con una compresión del 50% al 60%.
El resultado podría ser un verbo, sustantivo, adjetivo o adverbio:
from nltk.stem import WordNetLemmatizer lemmatizer = WordNetLemmatizer() print(lemmatizer.lemmatize('playing', pos="v")) print(lemmatizer.lemmatize('playing', pos="n")) print(lemmatizer.lemmatize('playing', pos="a")) print(lemmatizer.lemmatize('playing', pos="r"))
El resultado es:
play playing playing playing
Diferencia de derivación regresiva y lematización
Bien, vamos a intentar a derivar y lematizar algunas palabras:
from nltk.stem import WordNetLemmatizer from nltk.stem import PorterStemmer stemmer = PorterStemmer() lemmatizer = WordNetLemmatizer() print(stemmer.stem('stones')) print(stemmer.stem('speaking')) print(stemmer.stem('bedroom')) print(stemmer.stem('jokes')) print(stemmer.stem('lisa')) print(stemmer.stem('purple')) print('----------------------') print(lemmatizer.lemmatize('stones')) print(lemmatizer.lemmatize('speaking')) print(lemmatizer.lemmatize('bedroom')) print(lemmatizer.lemmatize('jokes')) print(lemmatizer.lemmatize('lisa')) print(lemmatizer.lemmatize('purple'))
El resultado es:
stone speak bedroom joke lisa purpl ---------------------- stone speaking bedroom joke lisa purple
La derivación funciona con palabras sin conocer su contexto y es por eso que la raíz tiene una precisión menor, pero, es más rápida que la lematización.
En mi opinión, la lematización es mejor que la derivación. Word lemmatizing devuelve una palabra real, incluso si no es la misma palabra, podría ser un sinónimo, pero al menos es una palabra real.
A veces no te importa este nivel de precisión y todo lo que necesitas es velocidad, en este caso, la derivación es mejor.
Todos los pasos que discutimos en este tutorial de NLP fueron preprocesamiento de texto. En publicaciones futuras, discutiremos el análisis de texto usando Python NLTK.
Hice todo lo posible para que el artículo sea lo más sencillo y simple posible. Espero que le sea útil.
Sigue regresando. Gracias.
Fundadora de LikeGeeks. Estoy trabajando como administrador de sistemas Linux desde 2010. Soy responsable de mantener, proteger y solucionar problemas de servidores Linux para múltiples clientes de todo el mundo. Me encanta escribir guiones de shell y Python para automatizar mi trabajo.
Hola Te funciona bien la librería en español? Simule tu código y no me funciona
from nltk.stem import PorterStemmer
stemmer = PorterStemmer()
print(stemmer.stem(‘trabajando’))
gracias.
No revisé el texto en español.
Pruébalo y cuéntanos los resultados.
Gracias,
En español no funciona.
Quizás deberíamos buscar una alternativa.