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
Contenido
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.