Python para PNL: Introducción a la biblioteca StanfordCoreNLP

P

Este es el noveno artículo de mi serie de artículos sobre Python para PNL. En el artículo anterior, vimos cómo la biblioteca de patrones de Python se puede usar 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 al análisis de sentimientos. Antes de eso, exploramos la biblioteca TextBlob para realizar tareas similares de procesamiento del lenguaje natural.

En este artículo, exploraremos StanfordCoreNLP biblioteca, que es otra biblioteca extremadamente útil para el procesamiento del lenguaje natural. Veremos diferentes características de StanfordCoreNLP con la ayuda de ejemplos. Entonces, antes de perder más tiempo, comencemos.

Configurar el entorno

El proceso de instalación de StanfordCoreNLP no es tan sencillo como las otras bibliotecas de Python. De hecho, StanfordCoreNLP es una biblioteca que está escrita en Java. Por lo tanto, asegúrese de tener Java instalado en su sistema. Puede descargar el última versión de Java libremente.

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 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 -mx6g especifica que la memoria utilizada por el servidor no debe exceder los 6 gigabytes. Es importante mencionar que debe ejecutar un sistema de 64 bits para tener un montón de hasta 6 GB. 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 ejecuta en el puerto 9000.

Ahora, el paso final es instalar el contenedor de Python para la biblioteca StanfordCoreNLP. La envoltura que usaremos es pycorenlp. El siguiente script descarga la biblioteca contenedora:

$ pip install pycorenlp

Ahora estamos todos listos para conectarnos al servidor StanfordCoreNLP y realizar las tareas NLP deseadas.

Para conectarnos al servidor, tenemos que pasar la dirección del servidor StanfordCoreNLP que inicializamos antes al StanfordCoreNLP clase de la pycorenlp módulo. El objeto devuelto se puede utilizar para realizar tareas de PNL. Mira el siguiente guión:

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.

Lematización, etiquetado POS y reconocimiento de entidades nombradas

La lematización, el etiquetado de partes del habla y el reconocimiento de entidades con nombre son las tareas más básicas de la PNL. La biblioteca StanfordCoreNLP admite la funcionalidad de canalización que se puede utilizar para realizar estas tareas de forma estructurada.

En el siguiente script, crearemos un anotador que primero divide un documento en oraciones y luego divide las oraciones en palabras o tokens. Luego, las palabras se anotan con el POS y las etiquetas de reconocimiento de entidad nombradas.

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 de arriba tenemos un documento con dos frases. Usamos el annotate método del objeto contenedor StanfordCoreNLP que inicializamos anteriormente. El método toma tres parámetros. los annotator El parámetro toma el tipo de anotación que queremos realizar en el texto. Pasamos 'ner, pos' como el valor de la annotator parámetro que especifica que queremos anotar nuestro documento para etiquetas POS y entidades con nombre.

los outputFormat La variable define el formato en el que desea el texto anotado. Los posibles valores son json para objetos JSON, xml para formato XML, text para texto sin formato, y serialize para 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.

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 con nombre y la versión lematizada de cada palabra.

Lematización

Exploremos ahora los resultados anotados. Primero imprimiremos las lematizaciones de las palabras en las dos oraciones en nuestro conjunto de datos:

for sentence in annot_doc["sentences"]:
    for word in sentence["tokens"]:
        print(word["word"] + " => " + word["lemma"])

En el script anterior, el bucle externo recorre cada oración del documento y el bucle interno recorre cada palabra de la oración. Dentro del bucle interno, la palabra y su correspondiente forma lematizada 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 la palabra moved ha sido lematizado a move, de manera similar la palabra plays ha sido lematizado a play.

Etiquetado POS

De la misma forma, podemos encontrar las etiquetas POS para cada palabra. Mira el siguiente guión:

for sentence in annot_doc["sentences"]:
    for word in sentence["tokens"]:
        print (word["word"] + "=>" + word["pos"])

En la salida, debería 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 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 eso Ronaldo ha sido identificado como un PERSON mientras Barcelona ha sido identificado como Organization, que en este caso es correcto.

Análisis de los sentimientos

Para encontrar el sentimiento de una oración, todo lo que tienes que hacer es aprobar sentiment como el valor de la annotators propiedad. Mira el siguiente guión:

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 sentimentValue propiedad para encontrar el sentimiento. los sentimentValue devuelve un valor entre 1 y 4, donde 1 corresponde a un sentimiento muy negativo mientras que 4 corresponde a un sentimiento muy positivo. los sentiment La propiedad se puede usar para obtener sentimientos en forma verbal, es decir positive, negative o neutral.

El siguiente guión 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

StanfordCoreNLP es otra biblioteca extremadamente útil para el procesamiento del 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 PNL como lematización, etiquetado POS y reconocimiento de entidades nombradas y finalmente, completamos el artículo con análisis sentimental utilizando StanfordCoreNLP.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad