Breaking

Post Top Ad

Your Ad Spot

viernes, 14 de junio de 2019

Python para NLP: Introducción a la biblioteca StanfordCoreNLP

Este es el noveno artículo de mi serie de artículos sobre Python para la PNL. En el artículo anterior , vimos cómo se puede usar la biblioteca de patrones de Python para realizar una variedad de tareas de PNL que van desde la tokenización hasta el etiquetado de POS, y la clasificación de texto para el análisis de sentimientos. Antes de eso, exploramos la biblioteca TextBlob para realizar tareas similares de procesamiento de lenguaje natural.
En este artículo, exploraremos la biblioteca StanfordCoreNLP , que es otra biblioteca extremadamente útil para el procesamiento de lenguaje natural. Veremos diferentes características de StanfordCoreNLP con la ayuda de ejemplos. Entonces, antes de perder más tiempo, comencemos.

Configurando el medio ambiente

El proceso de instalación de StanfordCoreNLP no es tan sencillo como las otras bibliotecas de Python. De hecho, StanfordCoreNLP es una biblioteca que realmente está escrita en Java. Por lo tanto, asegúrese de tener Java instalado en su sistema. Puede descargar la última versión de Javalibremente.
Una vez que haya instalado Java, debe descargar los archivos JAR para las bibliotecas StanfordCoreNLP. El archivo JAR contiene modelos que se utilizan para realizar diferentes tareas de PNL. Para descargar los archivos JAR para los modelos en inglés, descargue y descomprima la carpeta ubicada en el sitio web oficial de StanfordCoreNLP .
Lo siguiente que debe hacer es ejecutar el servidor que atenderá las solicitudes enviadas por el contenedor de Python a la biblioteca StanfordCoreNLP. Navegue hasta la ruta donde descomprimió la carpeta de archivos JAR. Navegue dentro de la carpeta y ejecute el siguiente comando en el símbolo del sistema:
$ java -mx6g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -timeout 10000
El comando anterior inicia el servidor StanfordCoreNLP. El parámetro -mx6gespecifica que la memoria utilizada por el servidor no debe exceder los 6 gigabytes. Es importante mencionar que debe estar ejecutando un sistema de 64 bits para tener un montón tan grande como 6GB. Si está ejecutando un sistema de 32 bits, es posible que deba reducir el tamaño de la memoria dedicada al servidor.
Una vez que ejecute el comando anterior, debería ver el siguiente resultado:
[main] INFO CoreNLP - --- StanfordCoreNLPServer#main() called ---
[main] INFO CoreNLP - setting default constituency parser
[main] INFO CoreNLP - warning: cannot find edu/stanford/nlp/models/srparser/englishSR.ser.gz
[main] INFO CoreNLP - using: edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz instead
[main] INFO CoreNLP - to use shift reduce parser download English models jar from:
[main] INFO CoreNLP - http://stanfordnlp.github.io/CoreNLP/download.html
[main] INFO CoreNLP -     Threads: 8
[main] INFO CoreNLP - Starting server...
[main] INFO CoreNLP - StanfordCoreNLPServer listening at /0:0:0:0:0:0:0:0:9000
El servidor se está ejecutando en el puerto 9000.
Ahora el paso final es instalar el contenedor de Python para la biblioteca StanfordCoreNLP. El envoltorio que usaremos es pycorenlpEl siguiente script descarga la biblioteca de envoltura:
$ pip install pycorenlp
Ahora estamos listos para conectarnos al servidor StanfordCoreNLP y realizar las tareas NLP deseadas.
Para conectarnos al servidor, debemos pasar la dirección del servidor StanfordCoreNLP que inicializamos antes a la StanfordCoreNLPclase del pycorenlpmódulo. El objeto devuelto se puede usar para realizar tareas de PNL. Mira el siguiente script:
from pycorenlp import StanfordCoreNLP

nlp_wrapper = StanfordCoreNLP('http://localhost:9000')  

Realización de tareas de PNL

En esta sección, exploraremos brevemente el uso de la biblioteca StanfordCoreNLP para realizar tareas comunes de PNL.

Lemmatización, etiquetado POS y reconocimiento de la entidad nombrada

Las tareas de PNL más básicas son la lematización, las partes de etiquetado de voz y el reconocimiento de entidades con nombre. La biblioteca StanfordCoreNLP admite la funcionalidad de canalización que se puede utilizar para realizar estas tareas de forma estructurada.
En el siguiente guión, crearemos un anotador que primero divide un documento en oraciones y luego divide las oraciones en palabras o tokens. Las palabras se anotan con el POS y las etiquetas de reconocimiento de la entidad con nombre.
doc = "Ronaldo has moved from Real Madrid to Juventus. While messi still plays for Barcelona"  
annot_doc = nlp_wrapper.annotate(doc,  
    properties={
        'annotators': 'ner, pos',
        'outputFormat': 'json',
        'timeout': 1000,
    })
En el guión anterior tenemos un documento con dos oraciones. Usamos el annotatemétodo del objeto contenedor StanfordCoreNLP que inicializamos anteriormente. El método toma tres parámetros. El annotatorparámetro toma el tipo de anotación que queremos realizar en el texto. Pasamos 'ner, pos'como el valor para el annotatorparámetro que especifica que queremos anotar nuestro documento para las etiquetas POS y las entidades nombradas.
La outputFormatvariable define el formato en el que desea el texto anotado. Los valores posibles son jsonpara objetos JSON, xmlpara formato XML, textpara texto plano y serializepara datos serializados.
El parámetro final es el tiempo de espera en milisegundos, que define el tiempo que el contenedor debe esperar la respuesta del servidor antes de que se agote el tiempo de espera.
En la salida, debería ver un objeto JSON de la siguiente manera:
{'sentences': [{'index': 0, 'entitymentions': [{'docTokenBegin': 0, 'docTokenEnd': 1, 'tokenBegin': 0, 'tokenEnd': 1, 'text': 'Ronaldo', 'characterOffsetBegin': 0, 'characterOffsetEnd': 7, 'ner': 'PERSON'}, {'docTokenBegin': 4, 'docTokenEnd': 6, 'tokenBegin': 4, 'tokenEnd': 6, 'text': 'Real Madrid', 'characterOffsetBegin': 23, 'characterOffsetEnd': 34, 'ner': 'ORGANIZATION'}, {'docTokenBegin': 7, 'docTokenEnd': 8, 'tokenBegin': 7, 'tokenEnd': 8, 'text': 'Juventus', 'characterOffsetBegin': 38, 'characterOffsetEnd': 46, 'ner': 'ORGANIZATION'}], 'tokens': [{'index': 1, 'word': 'Ronaldo', 'originalText': 'Ronaldo', 'lemma': 'Ronaldo', 'characterOffsetBegin': 0, 'characterOffsetEnd': 7, 'pos': 'NNP', 'ner': 'PERSON', 'before': '', 'after': ' '}, {'index': 2, 'word': 'has', 'originalText': 'has', 'lemma': 'have', 'characterOffsetBegin': 8, 'characterOffsetEnd': 11, 'pos': 'VBZ', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 3, 'word': 'moved', 'originalText': 'moved', 'lemma': 'move', 'characterOffsetBegin': 12, 'characterOffsetEnd': 17, 'pos': 'VBN', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 4, 'word': 'from', 'originalText': 'from', 'lemma': 'from', 'characterOffsetBegin': 18, 'characterOffsetEnd': 22, 'pos': 'IN', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 5, 'word': 'Real', 'originalText': 'Real', 'lemma': 'real', 'characterOffsetBegin': 23, 'characterOffsetEnd': 27, 'pos': 'JJ', 'ner': 'ORGANIZATION', 'before': ' ', 'after': ' '}, {'index': 6, 'word': 'Madrid', 'originalText': 'Madrid', 'lemma': 'Madrid', 'characterOffsetBegin': 28, 'characterOffsetEnd': 34, 'pos': 'NNP', 'ner': 'ORGANIZATION', 'before': ' ', 'after': ' '}, {'index': 7, 'word': 'to', 'originalText': 'to', 'lemma': 'to', 'characterOffsetBegin': 35, 'characterOffsetEnd': 37, 'pos': 'TO', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 8, 'word': 'Juventus', 'originalText': 'Juventus', 'lemma': 'Juventus', 'characterOffsetBegin': 38, 'characterOffsetEnd': 46, 'pos': 'NNP', 'ner': 'ORGANIZATION', 'before': ' ', 'after': ''}, {'index': 9, 'word': '.', 'originalText': '.', 'lemma': '.', 'characterOffsetBegin': 46, 'characterOffsetEnd': 47, 'pos': '.', 'ner': 'O', 'before': '', 'after': ' '}]}, {'index': 1, 'entitymentions': [{'docTokenBegin': 14, 'docTokenEnd': 15, 'tokenBegin': 5, 'tokenEnd': 6, 'text': 'Barcelona', 'characterOffsetBegin': 76, 'characterOffsetEnd': 85, 'ner': 'ORGANIZATION'}], 'tokens': [{'index': 1, 'word': 'While', 'originalText': 'While', 'lemma': 'while', 'characterOffsetBegin': 48, 'characterOffsetEnd': 53, 'pos': 'IN', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 2, 'word': 'messi', 'originalText': 'messi', 'lemma': 'messus', 'characterOffsetBegin': 54, 'characterOffsetEnd': 59, 'pos': 'NNS', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 3, 'word': 'still', 'originalText': 'still', 'lemma': 'still', 'characterOffsetBegin': 60, 'characterOffsetEnd': 65, 'pos': 'RB', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 4, 'word': 'plays', 'originalText': 'plays', 'lemma': 'play', 'characterOffsetBegin': 66, 'characterOffsetEnd': 71, 'pos': 'VBZ', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 5, 'word': 'for', 'originalText': 'for', 'lemma': 'for', 'characterOffsetBegin': 72, 'characterOffsetEnd': 75, 'pos': 'IN', 'ner': 'O', 'before': ' ', 'after': ' '}, {'index': 6, 'word': 'Barcelona', 'originalText': 'Barcelona', 'lemma': 'Barcelona', 'characterOffsetBegin': 76, 'characterOffsetEnd': 85, 'pos': 'NNP', 'ner': 'ORGANIZATION', 'before': ' ', 'after': ''}]}]}
Si observa detenidamente el script anterior, puede encontrar las etiquetas POS, las entidades nombradas y la versión lematizada de cada palabra.
Lemmatización
Ahora exploremos los resultados anotados. Primero, imprimiremos las lematizaciones de las palabras en las dos oraciones de nuestro conjunto de datos:
for sentence in annot_doc["sentences"]:  
    for word in sentence["tokens"]:
        print(word["word"] + " => " + word["lemma"])
En la secuencia de comandos anterior, el bucle externo itera a través de cada oración en el documento y el bucle interno itera a través de cada palabra en la oración. Dentro del bucle interno, la palabra y su correspondiente forma lemmatizada están impresas en la consola. La salida se ve así:
Ronaldo=>Ronaldo  
has=>have  
moved=>move  
from=>from  
Real=>real  
Madrid=>Madrid  
to=>to  
Juventus=>Juventus  
.=>.
While=>while  
messi=>messus  
still=>still  
plays=>play  
for=>for  
Barcelona=>Barcelona  
Por ejemplo, puede ver que la palabra movedha sido lemmatizada a move, de manera similar, la palabra playsha sido lemmatizada a play.
Etiquetado POS
De la misma manera, podemos encontrar las etiquetas POS para cada palabra. Mira el siguiente script:
for sentence in annot_doc["sentences"]:  
    for word in sentence["tokens"]:
        print (word["word"] + "=>" + word["pos"])
En la salida, deberías ver los siguientes resultados:
Ronaldo=>NNP  
has=>VBZ  
moved=>VBN  
from=>IN  
Real=>JJ  
Madrid=>NNP  
to=>TO  
Juventus=>NNP  
.=>.
While=>IN  
messi=>NNS  
still=>RB  
plays=>VBZ  
for=>IN  
Barcelona=>NNP  
El conjunto de etiquetas utilizado para las etiquetas POS es el conjunto de etiquetas Penn Treebank y se puede encontrar aquí .
Reconocimiento de la entidad nombrada
Para encontrar entidades con nombre en nuestro documento, podemos usar el siguiente script:
for sentence in annot_doc["sentences"]:  
    for word in sentence["tokens"]:
        print (word["word"] + "=>" + word["ner"])
La salida se ve así:
Ronaldo=>PERSON  
has=>O  
moved=>O  
from=>O  
Real=>ORGANIZATION  
Madrid=>ORGANIZATION  
to=>O  
Juventus=>ORGANIZATION  
.=>O
While=>O  
messi=>O  
still=>O  
plays=>O  
for=>O  
Barcelona=>ORGANIZATION  
Podemos ver que Ronaldoha sido identificado como un PERSONtiempo que Barcelonaha sido identificado Organization, lo que en este caso es correcto.

Análisis de los sentimientos

Para encontrar el sentimiento de una oración, todo lo que tiene que pasar es sentimentel valor de la annotatorspropiedad. Mira el siguiente script:
doc = "I like this chocolate. This chocolate is not good. The chocolate is delicious. Its a very tasty chocolate. This is so bad"  
annot_doc = nlp_wrapper.annotate(doc,  
    properties={
       'annotators': 'sentiment',
       'outputFormat': 'json',
       'timeout': 1000,
    })
Para encontrar el sentimiento, podemos iterar sobre cada oración y luego usar la sentimentValuepropiedad para encontrar el sentimiento. El sentimentValuevalor devuelto es entre 1 y 4, donde 1 corresponde a un sentimiento altamente negativo, mientras que 4 corresponde a un sentimiento altamente positivo. La sentimentpropiedad se puede utilizar para obtener sentimiento en forma verbal positivees decir negativeneutral.
El siguiente script encuentra el sentimiento para cada oración en el documento que definimos anteriormente.
for sentence in annot_doc["sentences"]:  
    print ( " ".join([word["word"] for word in sentence["tokens"]]) + " => " \
        + str(sentence["sentimentValue"]) + " = "+ sentence["sentiment"])
Salida:
I like this chocolate . => 2 = Neutral  
This chocolate is not good . => 1 = Negative  
The chocolate is delicious . => 3 = Positive  
Its a very tasty chocolate . => 3 = Positive  
This is so bad => 1 = Negative  

Conclusión

StanfordCoreNLPEs otra biblioteca extremadamente útil para el procesamiento de lenguaje natural. En este artículo, estudiamos cómo configurar el entorno para ejecutar StanfordCoreNLP. Luego exploramos el uso de la biblioteca StanfordCoreNLP para tareas comunes de la PNL, como la lematización, el etiquetado POS y el reconocimiento de la entidad nombrada, y finalmente, completamos el artículo con análisis sentimental utilizando StanfordCoreNLP.

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

Post Top Ad

Your Ad Spot

Páginas