Python para PNL: Introducción a la biblioteca de patrones

P

Este es el octavo artículo de mi serie de artículos sobre Python para PNL. En mi artículo anterior, expliqué cómo se puede usar la biblioteca TextBlob 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 al análisis de opiniones. En este artículo, exploraremos la biblioteca de patrones de Python , que es otra biblioteca de procesamiento de lenguaje natural extremadamente útil.

La biblioteca de patrones es una biblioteca multipropósito capaz de manejar las siguientes tareas:

  • Procesamiento de lenguaje natural: Realización de tareas como tokenización, derivación, etiquetado POS, análisis de sentimientos, etc.
  • Minería de datos: contiene API para extraer datos de sitios como Twitter, Facebook, Wikipedia, etc.
  • Machine Learning: contiene modelos de Machine Learning como SVM, KNN y perceptron, que se pueden usar para tareas de clasificación, regresión y agrupación en clústeres.

En este artículo, veremos las dos primeras aplicaciones de la biblioteca de patrones de la lista anterior. Exploraremos el uso de la biblioteca de patrones para PNL realizando tareas como tokenización, derivación y análisis de sentimientos. También veremos cómo se puede usar la biblioteca de patrones para la minería web.

Instalación de la biblioteca

Para instalar la biblioteca, puede usar el siguiente comando pip:

$ pip install pattern

De lo contrario, si está usando la distribución Anaconda de Python, puede usar el siguiente comando Anaconda para descargar la biblioteca:

$ conda install -c asmeurer pattern

Funciones de biblioteca de patrones para PNL

En esta sección, veremos algunas de las aplicaciones de PNL de la biblioteca de patrones.

Tokenización, etiquetado de POS y fragmentación

En las bibliotecas NLTK y spaCy, tenemos una función separada para tokenizar, etiquetar POS y encontrar frases nominales en documentos de texto. Por otro lado, en la biblioteca de patrones existe el parsemétodo todo en uno que toma una cadena de texto como parámetro de entrada y devuelve los tokens correspondientes en la cadena, junto con la etiqueta POS.

El parsemétodo también nos dice si un token es un sintagma nominal o verbo, sujeto u objeto. También puede recuperar tokens lematizados configurando el lemmataparámetro en True. La sintaxis del parsemétodo junto con los valores predeterminados para diferentes parámetros es la siguiente:

parse(string,
    tokenize=True,      # Split punctuation marks from words?
    tags=True,          # Parse part-of-speech tags? (NN, JJ, ...)
    chunks=True,        # Parse chunks? (NP, VP, PNP, ...)
    relations=False,    # Parse chunk relations? (-SBJ, -OBJ, ...)
    lemmata=False,      # Parse lemmata? (ate => eat)
    encoding='utf-8',   # Input string encoding.
    tagset=None         # Penn Treebank II (default) or UNIVERSAL.
)

Veamos el parsemétodo en acción:

from pattern.en import parse
from pattern.en import pprint

pprint(parse('I drove my car to the hospital yesterday', relations=True, lemmata=True))

Para utilizar el parsemétodo, debe importar el enmódulo de la patternbiblioteca. El enmódulo contiene funciones de PNL en inglés. Si usa el pprintmétodo para imprimir la salida del parsemétodo en la consola, debería ver la siguiente salida:

         WORD   TAG    CHUNK   ROLE   ID     PNP    LEMMA

             I   PRP    NP      SBJ    1      -      i
         drove   VBD    VP      -      1      -      drive
            my   PRP$   NP      OBJ    1      -      my
           car   NN     NP ^    OBJ    1      -      car
            to   TO     -       -      -      -      to
           the   DT     NP      -      -      -      the
      hospital   NN     NP ^    -      -      -      hospital
     yesterday   NN     NP ^    -      -      -      yesterday

En la salida, puede ver las palabras tokenizadas junto con su etiqueta POS, el fragmento al que pertenecen los tokens y la función. También puede ver la forma lematizada de los tokens.

Si llama al splitmétodo en el objeto devuelto por el parsemétodo, la salida será una lista de oraciones, donde cada oración es una lista de tokens y cada token es una lista de palabras, junto con las etiquetas asociadas con las palabras.

Por ejemplo, mire el siguiente guión:

from pattern.en import parse
from pattern.en import pprint

print(parse('I drove my car to the hospital yesterday', relations=True, lemmata=True).split())

La salida del script anterior se ve así:

[[['I', 'PRP', 'B-NP', 'O', 'NP-SBJ-1', 'i'], ['drove', 'VBD', 'B-VP', 'O', 'VP-1', 'drive'], ['my', 'PRP$', 'B-NP', 'O', 'NP-OBJ-1', 'my'], ['car', 'NN', 'I-NP', 'O', 'NP-OBJ-1', 'car'], ['to', 'TO', 'O', 'O', 'O', 'to'], ['the', 'DT', 'B-NP', 'O', 'O', 'the'], ['hospital', 'NN', 'I-NP', 'O', 'O', 'hospital'], ['yesterday', 'NN', 'I-NP', 'O', 'O', 'yesterday']]]

Pluralización y singularización de las fichas

Los métodos pluralizey singularizese utilizan para convertir palabras singulares en plurales y viceversa, respectivamente.

from pattern.en import pluralize, singularize

print(pluralize('leaf'))
print(singularize('theives'))

La salida se ve así:

leaves
theif

Conversión de adjetivos en grados comparativos y superlativos

Puede recuperar grados comparativos y superlativos de un adjetivo usando comparativey superlativefunciones. Por ejemplo, el grado comparativo de bien es mejor y el grado superlativo de bien es mejor. Veamos esto en acción:

from pattern.en import comparative, superlative

print(comparative('good'))
print(superlative('good'))

Salida:

better
best

Encontrar N-gramos

N-gramos se refiere a “n” combinaciones de palabras en una oración. Por ejemplo, para la oración “Va al hospital”, 2 gramos serían (Va), (Va a) y (Al hospital). N-Grams puede desempeñar un papel crucial en la clasificación de textos y el modelado del lenguaje.

En la biblioteca de patrones, el ngrammétodo se usa para encontrar todos los n-gramas en una cadena de texto. El primer parámetro del ngrammétodo es la cadena de texto. El número de n-gramos se pasa al nparámetro del método. Mira el siguiente ejemplo:

from pattern.en import ngrams

print(ngrams("He goes to hospital", n=2))

Salida:

[('He', 'goes'), ('goes', 'to'), ('to', 'hospital')]

Encontrar sentimientos

El sentimiento se refiere a una opinión o sentimiento hacia una determinada cosa. La biblioteca de patrones ofrece funcionalidad para encontrar opiniones a partir de una cadena de texto.

En Pattern, el sentimentobjeto se usa para encontrar la polaridad (positividad o negatividad) de un texto junto con su subjetividad.

Dependiendo de los adjetivos positivos (bueno, mejor, excelente, etc.) y negativos (malo, horrible, patético, etc.) que ocurren con más frecuencia, se asigna al texto una puntuación de sentimiento entre 1 y -1. Esta puntuación de sentimiento también se llama polaridad.

Además de la puntuación de sentimiento, también se devuelve la subjetividad. El valor de subjetividad puede estar entre 0 y 1. La subjetividad cuantifica la cantidad de opinión personal e información fáctica contenida en el texto. La subjetividad más alta significa que el texto contiene opiniones personales en lugar de información fáctica.

from pattern.en import sentiment

print(sentiment("This is an excellent movie to watch. I really love it"))

Cuando ejecute el script anterior, debería ver el siguiente resultado:

(0.75, 0.8)

La frase “Esta es una película excelente para ver. Me encanta” tiene un sentimiento de 0,75, lo que demuestra que es muy positiva. De igual forma, la subjetividad de 0.8 se refiere al hecho de que la oración es una opinión personal del usuario.

Verificar si una declaración es un hecho

La modalityfunción de la biblioteca de patrones se puede utilizar para encontrar el grado de certeza en la cadena de texto. La modalityfunción devuelve un valor entre -1 y 1. En el caso de los hechos, la modalityfunción devuelve un valor mayor que 0,5.

Aquí hay un ejemplo en acción:

from pattern.en import parse, Sentence
from pattern.en import modality

text = "Paris is the capital of France"
sent = parse(text, lemmata=True)
sent = Sentence(sent)

print(modality(sent))
1.0

En el script anterior, primero importamos el parsemétodo junto con la Sentenceclase. En la segunda línea, importamos la modalityfunción. El parsemétodo toma texto como entrada y devuelve una forma tokenizada del texto, que luego se pasa al Sentenceconstructor de la clase. El modalitymétodo toma el Sentenceobjeto de la clase y devuelve la modalidad de la oración.

Dado que la cadena de texto “París es la capital de Francia” es un hecho, en la salida verá un valor de 1.

De manera similar, para una oración que no es segura, el valor devuelto por el modalitymétodo es alrededor de 0.0. Mira el siguiente guión:

text = "I think we can complete this task"
sent = parse(text, lemmata=True)
sent = Sentence(sent)

print(modality(sent))
0.25

Dado que la cadena en el ejemplo anterior no es muy segura, la modalidad de la cadena anterior será 0,25.

Correcciones ortográficas

El suggestmétodo se puede utilizar para averiguar si una palabra está escrita correctamente o no. El suggestmétodo devuelve 1 si una palabra está escrita correctamente al 100%. De lo contrario, el suggestmétodo devuelve las posibles correcciones de la palabra junto con su probabilidad de corrección.

Mira el siguiente ejemplo:

from pattern.en import suggest

print(suggest("Whitle"))

En el guión de arriba tenemos una palabra Whitleque está mal escrita. En la salida, verá posibles sugerencias para esta palabra.

[('While', 0.6459209419680404), ('White', 0.2968881412952061), ('Title', 0.03280067283431455), ('Whistle', 0.023549201009251473), ('Chile', 0.0008410428931875525)]

Según el suggestmétodo, hay una probabilidad de 0,64 de que la palabra sea “Mientras”, de manera similar, hay una probabilidad de 0,29 de que la palabra sea “Blanca”, y así sucesivamente.

Ahora deletreemos una palabra correctamente:

from pattern.en import suggest
print(suggest("Fracture"))

Salida:

[('Fracture', 1.0)]

En el resultado, puede ver que hay un 100% de probabilidad de que la palabra esté escrita correctamente.

Trabajar con números

La biblioteca de patrones contiene funciones que se pueden usar para convertir números en forma de cadenas de texto en sus contrapartes numéricas y viceversa. Para convertir de texto a representación numérica numberse utiliza la función. De manera similar, para volver a convertir de números a su representación de texto correspondiente numerals, se utiliza la función. Mira el siguiente guión:

from pattern.en import number, numerals

print(number("one hundred and twenty two"))
print(numerals(256.390, round=2))

Salida:

122
two hundred and fifty-six point thirty-nine

En el resultado, verá 122 que es la representación numérica del texto “ciento veintidós”. De manera similar, debería ver “doscientos cincuenta y seis coma treinta y nueve”, que es la representación de texto del número 256.390.

Recuerde, para la numeralsfunción tenemos que proporcionar el valor entero al que queremos que se redondee nuestro número.

La quantifyfunción se utiliza para obtener una estimación del recuento de palabras de los elementos de la lista, que proporciona una frase para referirse al grupo. Si una lista tiene 3-8 elementos similares, la quantifyfunción lo cuantificará en “varios”. Dos elementos se cuantifican en un “par”.

from pattern.en import quantify

print(quantify(['apple', 'apple', 'apple', 'banana', 'banana', 'banana', 'mango', 'mango']))

En la lista, tenemos tres manzanas, tres plátanos y dos mangos. La salida de la quantifyfunción para esta lista se ve así:

several bananas, several apples and a pair of mangoes

De manera similar, el siguiente ejemplo demuestra las otras estimaciones de recuento de palabras.

from pattern.en import quantify

print(quantify({'strawberry': 200, 'peach': 15}))
print(quantify('orange', amount=1200))

Salida:

hundreds of strawberries and a number of peaches
thousands of oranges

Funciones de biblioteca de patrones para minería de datos

En la sección anterior, vimos algunas de las funciones más utilizadas de la biblioteca de patrones para PNL. En esta sección, veremos cómo se puede usar la biblioteca de patrones para realizar una variedad de tareas de minería de datos.

El webmódulo de la biblioteca de patrones se utiliza para tareas de minería web.

Acceso a páginas web

El URLobjeto se utiliza para recuperar contenido de las páginas web. Tiene varios métodos que se pueden utilizar para abrir una página web, descargar el contenido de una página web y leer una página web.

Puede utilizar directamente el downloadmétodo para descargar el contenido HTML de cualquier página web. El siguiente script descarga el código fuente HTML del artículo de Wikipedia sobre inteligencia artificial.

from pattern.web import download

page_html = download('https://en.wikipedia.org/wiki/Artificial_intelligence', unicode=True)

También puede descargar archivos de páginas web, por ejemplo, imágenes utilizando el método URL:

from pattern.web import URL, extension

page_url = URL('https://upload.wikimedia.org/wikipedia/commons/f/f1/RougeOr_football.jpg')
file = open('football' + extension(page_url.page), 'wb')
file.write(page_url.download())
file.close()

En el script de arriba, primero hacemos una conexión con la página web usando el URLmétodo. A continuación, llamamos al extensionmétodo en la página abierta, que devuelve la extensión del archivo. La extensión del archivo se agrega al final de la cadena “fútbol”. Se llama al método abierto para leer esta ruta y, finalmente, el download()método descarga la imagen y la escribe en la ruta de ejecución predeterminada.

Encontrar URL dentro del texto

Puede utilizar el findurlmétodo para extraer URL de cadenas de texto. Aquí hay un ejemplo:

from pattern.web import find_urls

print(find_urls('To search anything, go to www.google.com', unique=True))

En el resultado, verá la URL del sitio web de Google como se muestra a continuación:

['www.google.com']

Realización de solicitudes asincrónicas para páginas web

Las páginas web pueden ser muy grandes y puede llevar bastante tiempo descargar el contenido completo de la página web, lo que puede impedir que un usuario realice cualquier otra tarea en la aplicación hasta que se descargue la página web completa. Sin embargo, el webmódulo de la biblioteca de patrones contiene una función asynchronousque descarga el contenido de una página web de manera paralela. El asynchronousmétodo se ejecuta en segundo plano para que el usuario pueda interactuar con la aplicación mientras se descarga la página web.

Tomemos un ejemplo muy simple del asynchronousmétodo:

from pattern.web import asynchronous, time, Google

asyn_req = asynchronous(Google().search, 'artificial intelligence', timeout=4)
while not asyn_req.done:
    time.sleep(0.1)
    print('searching...')

print(asyn_req.value)

print(find_urls(asyn_req.value, unique=True))

En el script anterior, recuperamos el resultado de búsqueda de Google de la página 1 para la consulta de búsqueda “inteligencia artificial”, puede ver que mientras la página se descarga ejecutamos un ciclo while en paralelo. Finalmente, los resultados recuperados por la consulta se imprimen utilizando el valueatributo del objeto devuelto por el asynchronousmódulo. A continuación, extraemos las URL de la búsqueda, que luego se imprimen en la pantalla.

Obtener resultados de motores de búsqueda con API

La biblioteca de patrones contiene SearchEngineclases derivadas de las clases que se pueden utilizar para conectarse a API de llamada de diferentes motores de búsqueda y sitios web como Google, Bing, Facebook, Wikipedia, Twitter, etc. La SearchEngineconstrucción del objeto acepta tres parámetros:

  • license: La clave de licencia de desarrollador para el motor de búsqueda o sitio web correspondiente
  • throttle: Corresponde a la diferencia de tiempo entre solicitudes sucesivas al servidor
  • langauge: Especifica el idioma de los resultados

El searchmétodo de la SearchEngineclase se utiliza para realizar una solicitud al motor de búsqueda para cierta consulta de búsqueda. El searchmétodo puede tomar los siguientes parámetros:

  • query: La cadena de búsqueda
  • type:El tipo de datos que desea buscar, puede tomar tres valores: SEARCH, NEWSy IMAGE.
  • start: La página desde la que desea iniciar la búsqueda
  • count: El número de resultados por página.

Las clases del motor de búsqueda que heredan la SearchEngineclase junto con su searchmétodo son: Google, Bing, Twitter, Facebook, Wikipedia, y Flickr.

La consulta de búsqueda devuelve objetos para cada elemento. El resultobjeto se puede utilizar para recuperar la información sobre el resultado buscado. Los atributos del resultobjeto son url, title, text, language, author, date.

Ahora veamos un ejemplo muy simple de cómo podemos buscar algo en Google a través de la biblioteca de patrones. Recuerde, para que este ejemplo funcione, deberá utilizar su clave de licencia de desarrollador para la API de Google.

from pattern.web import Google

google = Google(license=None)
for search_result in google.search('artificial intelligence'):
    print(search_result.url)
    print(search_result.text)

En el script de arriba, creamos un objeto de la clase de Google. En el constructor de Google, pase su propia clave de licencia al licenseparámetro. A continuación, pasamos la cadena artificial intelligenceal searchmétodo. De forma predeterminada, se devolverán los primeros 10 resultados de la primera página, que luego se iterarán, y la URL y el texto de cada resultado se mostrarán en la pantalla.

El proceso es similar para el motor de búsqueda Bing, solo tiene que reemplazar la Bingclase Googleen el script anterior.

Busquemos ahora en Twitter los tres últimos tweets que contienen el texto “inteligencia artificial”. Ejecute el siguiente script:

from pattern.web import Twitter

twitter = Twitter()
index = None
for j in range(3):
    for tweet in twitter.search('artificial intelligence', start=index, count=3):
        print(tweet.text)
        index = tweet.id

En el script anterior, primero importamos la Twitterclase del pattern.webmódulo. A continuación, iteramos sobre los tweets devueltos por la Twitterclase y mostramos el texto del tweet en la consola. No necesita ninguna clave de licencia para ejecutar el script anterior.

Conversión de datos HTML a texto sin formato

El downloadmétodo de la URLclase devuelve datos en forma de HTML. Sin embargo, si desea hacer un análisis semántico del texto, por ejemplo, la clasificación de opiniones, necesita datos limpiados sin etiquetas HTML. Puede limpiar los datos con el plaintextmétodo. El método toma como parámetro el contenido HTML devuelto por el downloadmétodo y devuelve texto limpio.

Mira el siguiente guión:

from pattern.web import URL, plaintext

html_content = URL('https://Pharos.sh.com/python-for-nlp-introduction-to-the-textblob-library/').download()
cleaned_page = plaintext(html_content.decode('utf-8'))
print(cleaned_page)

En el resultado, debería ver el texto limpio de la página web:

https://Pharos.sh.com/python-for-nlp-introduction-to-the-textblob-library/.

Es importante recordar que si está utilizando Python 3, necesitará llamar al decode('utf-8')método para convertir los datos de byte a formato de cadena.

Análisis de documentos PDF

La biblioteca de patrones contiene un objeto PDF que se puede utilizar para analizar un documento PDF. PDF (Portable Document Format) es un archivo multiplataforma que contiene imágenes, textos y fuentes en un documento independiente.

Veamos cómo se puede analizar un documento PDF con el objeto PDF:

from pattern.web import URL, PDF

pdf_doc = URL('https://demo.clab.cs.cmu.edu/NLP/syllabus_f18.pdf').download()
print(PDF(pdf_doc.decode('utf-8')))

En el script descargamos un documento usando la downloadfunción. A continuación, el documento HTML descargado se pasa a la clase PDF que finalmente lo imprime en la consola.

Limpiar la caché

Los resultados devueltos por los métodos como SearchEngine.search()y URL.download()se almacenan, de forma predeterminada, en la caché local. Para borrar el caché después de descargar un documento HTML, podemos usar el clearmétodo de la clase de caché, como se muestra a continuación:

from pattern.web import cache

cache.clear()

Conclusión

La biblioteca de patrones es una de las bibliotecas de procesamiento de lenguaje natural más útiles en Python. Aunque no es tan conocido como spaCy o NLTK, contiene funcionalidades como encontrar superlativos y comparativos, y detección de hechos y opiniones que lo distingue de las otras bibliotecas NLP.

En este artículo, estudiamos la aplicación de la biblioteca de patrones para el procesamiento del lenguaje natural, minería de datos y raspado web. Vimos cómo realizar tareas básicas de PNL como tokenización, lematización y análisis de sentimientos con la biblioteca de patrones. Finalmente, también vimos cómo usar Pattern para realizar consultas en motores de búsqueda, extraer tweets en línea y limpiar documentos HTML.

 

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 para su correcto funcionamiento. 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