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

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

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 NLP que van desde tokenización hasta POS etiquetado y clasificación de texto para análisis de sentimiento. En este artículo, exploraremos la biblioteca Patrón de Python, que es otra biblioteca de procesamiento de lenguaje natural extremadamente útil.

La biblioteca Pattern 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 de POS, análisis de sentimiento, etc.
  • Minería de datos: contiene API para extraer datos de sitios como Twitter, Facebook, Wikipedia, etc.
  • Aprendizaje automático: contiene modelos de aprendizaje automático como SVM, KNN y perceptron, que se pueden usar para tareas de clasificación, regresión y agrupación.

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

Instalación de la biblioteca {#instalación de la biblioteca}

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

1
$ pip install pattern

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

1
$ conda install -c asmeurer pattern

Funciones de biblioteca de patrones para NLP

En esta sección, veremos algunas de las aplicaciones de PNL de Pattern Library.

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 método parse 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 método parse también nos dice si un token es una frase nominal o una frase verbal, o un sujeto o un objeto. También puede recuperar tokens lematizados configurando el parámetro lemmata en True. La sintaxis del método parse junto con los valores predeterminados para diferentes parámetros es la siguiente:

1
2
3
4
5
6
7
8
9
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 método parse en acción:

1
2
3
4
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 usar el método parse, debe importar el módulo en de la biblioteca pattern. El módulo en contiene funciones de PNL en inglés. Si usa el método pprint para imprimir el resultado del método parse en la consola, debería ver el siguiente resultado:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
         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 el resultado, puede ver las palabras tokenizadas junto con su etiqueta POS, el fragmento al que pertenecen los tokens y el rol. También puede ver la forma lematizada de los tokens.

Si llama al método split en el objeto devuelto por el método parse, 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 script:

1
2
3
4
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í:

1
[[['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']]]

Pluralizar y singularizar las fichas {#pluralizar y singularizar las fichas}

Los métodos pluralize y singularize se utilizan para convertir palabras singulares en plurales y viceversa, respectivamente.

1
2
3
4
from pattern.en import pluralize, singularize

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

La salida se ve así:

1
2
leaves
theif

Convertir adjetivos en grados comparativos y superlativos {#convertir adjetivos en grados comparativos y superlativos}

Puede recuperar los grados comparativos y superlativos de un adjetivo utilizando las funciones “comparativa” y “superlativa”. Por ejemplo, el grado comparativo de bien es mejor y el grado superlativo de bien es mejor. Veamos esto en acción:

1
2
3
4
from pattern.en import comparative, superlative

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

Producción:

1
2
better
best

Encontrar N-Gramos

Los N-gramas se refieren a "n" combinaciones de palabras en una oración. Por ejemplo, para la oración "Él va al hospital", 2-gramos serían (Él va), (va a) y (al hospital). Los N-Grams pueden desempeñar un papel crucial en la clasificación de textos y el modelado del lenguaje.

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

1
2
3
from pattern.en import ngrams

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

Producción:

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

Búsqueda de sentimientos

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

En Pattern, el objeto sentimiento 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 aparecen con mayor frecuencia, se asigna al texto una puntuación de sentimiento entre 1 y -1. Esta puntuación de sentimiento también se denomina 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 mayor subjetividad significa que el texto contiene una opinión personal en lugar de información fáctica.

1
2
3
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:

1
(0.75, 0.8)

La oración "Esta es una película excelente para ver. Realmente me encanta" tiene un sentimiento de 0,75, lo que demuestra que es muy positivo. De igual forma, la subjetividad de 0.8 se refiere a que la oración es una opinión personal del usuario.

Comprobar si una declaración es un hecho

La función modalidad de la biblioteca de patrones se puede utilizar para encontrar el grado de certeza en la cadena de texto. La función modalidad devuelve un valor entre -1 y 1. Para los hechos, la función modalidad devuelve un valor superior a 0,5.

Aquí hay un ejemplo de esto en acción:

1
2
3
4
5
6
7
8
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
1.0

En el script anterior, primero importamos el método parse junto con la clase Sentence. En la segunda línea, importamos la función modalidad. El método parse toma texto como entrada y devuelve una forma tokenizada del texto, que luego se pasa al constructor de la clase Sentence. El método modality toma el objeto de la clase Sentence 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 método modalidad está alrededor de 0.0. Mira el siguiente guión:

1
2
3
4
5
text = "I think we can complete this task"
sent = parse(text, lemmata=True)
sent = Sentence(sent)

print(modality(sent))
1
0.25

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

Correcciones ortográficas

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

Mira el siguiente ejemplo:

1
2
3
from pattern.en import suggest

print(suggest("Whitle"))

En el guión de arriba tenemos una palabra Whitle que está escrita incorrectamente. En el resultado, verá posibles sugerencias para esta palabra.

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

Según el método suggest, hay una probabilidad de 0,64 de que la palabra sea "Mientras", de forma similar, hay una probabilidad de 0,29 de que la palabra sea "Blanca", y así sucesivamente.

Ahora vamos a deletrear una palabra correctamente:

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

Producción:

1
[('Fracture', 1.0)]

A partir de la salida, puede ver que hay un 100 % de posibilidades 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 se utiliza la función number. De manera similar, para volver a convertir números a su representación de texto correspondiente, se usa la función numerals. Mira el siguiente guión:

1
2
3
4
from pattern.en import number, numerals

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

Producción:

1
2
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". Del mismo modo, debería ver "doscientos cincuenta y seis punto treinta y nueve", que es la representación de texto del número 256.390.

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

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

1
2
3
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 función cuantificar para esta lista se ve así:

1
several bananas, several apples and a pair of mangoes

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

1
2
3
4
from pattern.en import quantify

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

Producción:

1
2
hundreds of strawberries and a number of peaches
thousands of oranges

Funciones de la biblioteca de patrones para la minería de datos

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

El módulo web de la biblioteca Pattern se utiliza para tareas de minería web.

Acceso a páginas web {#acceso a páginas web}

El objeto URL se utiliza para recuperar contenidos de las páginas web. Tiene varios métodos que se pueden usar para abrir una página web, descargar los contenidos de una página web y leer una página web.

Puede utilizar directamente el método descargar 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.

1
2
3
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:

1
2
3
4
5
6
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 anterior, primero hacemos una conexión con la página web utilizando el método URL. A continuación, llamamos al método extensión 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 open para leer esta ruta y, finalmente, el método download() descarga la imagen y la escribe en la ruta de ejecución predeterminada.

Búsqueda de direcciones URL dentro del texto

Puede usar el método findurl para extraer URL de cadenas de texto. Aquí hay un ejemplo:

1
2
3
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:

1
['www.google.com']

Realización de solicitudes asíncronas 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 módulo web de la biblioteca Pattern contiene una función asynchronous, que descarga contenidos de una página web de manera paralela. El método asincrónico 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 método asincrónico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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 bucle while en paralelo. Finalmente, los resultados recuperados por la consulta se imprimen utilizando el atributo valor del objeto devuelto por el módulo asincrónico. 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 la clase SearchEngine que se deriva de las clases que se pueden usar para conectarse para llamar a las API de diferentes motores de búsqueda y sitios web como Google, Bing, Facebook, Wikipedia, Twitter, etc. El SearchEngine la construcción del objeto acepta tres parámetros:

  • licencia: 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
  • idioma: especifica el idioma de los resultados

El método search de la clase SearchEngine se utiliza para realizar una solicitud al motor de búsqueda para una determinada consulta de búsqueda. El método buscar puede tomar los siguientes parámetros:

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

Las clases de motores de búsqueda que heredan la clase SearchEngine junto con su método search son: Google, Bing, Twitter, Facebook, Wikipedia y Flickr.

La consulta de búsqueda devuelve objetos para cada elemento. El objeto resultado se puede usar para recuperar la información sobre el resultado buscado. Los atributos del objeto resultado son url, título, texto, idioma, autor, fecha.

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á usar su clave de licencia de desarrollador para la API de Google.

1
2
3
4
5
6
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 anterior, creamos un objeto de la clase Google. En el constructor de Google, pase su propia clave de licencia al parámetro license. A continuación, pasamos la cadena inteligencia artificial al método buscar. De forma predeterminada, se devolverán los primeros 10 resultados de la primera página, que luego se iteran, y la URL y el texto de cada resultado se muestran en la pantalla.

El proceso es similar para el motor de búsqueda Bing, solo tiene que reemplazar la clase Bing con Google en el script anterior.

Busquemos ahora en Twitter los tres últimos tuits que contienen el texto "inteligencia artificial". Ejecute el siguiente script:

1
2
3
4
5
6
7
8
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 clase Twitter desde el módulo pattern.web. A continuación, iteramos sobre los tweets devueltos por la clase Twitter 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 en texto sin formato

El método download de la clase URL devuelve datos en forma de HTML. Sin embargo, si desea realizar un análisis semántico del texto, por ejemplo, clasificación de sentimientos, necesita datos limpios sin etiquetas HTML. Puede limpiar los datos con el método texto sin formato. El método toma como parámetro el contenido HTML devuelto por el método descargar y devuelve texto limpio.

Mira el siguiente guión:

1
2
3
4
5
from pattern.web import URL, plaintext

html_content = URL('https://wikihtp.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://wikihtp.com/python-for-nlp-introduction-to-the-textblob-library/.

Es importante recordar que si está utilizando Python 3, deberá llamar al método decode('utf-8') 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 (formato de documento portátil) 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:

1
2
3
4
from pattern.web import URL, PDF

pdf_doc = URL('http://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 función descargar. A continuación, el documento HTML descargado se pasa a la clase PDF, que finalmente lo imprime en la consola.

Borrando el caché

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

1
2
3
from pattern.web import cache

cache.clear()

Conclusión

La biblioteca Pattern 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 distinguen de las otras bibliotecas de NLP.

En este artículo, estudiamos la aplicación de la biblioteca Pattern para el procesamiento del lenguaje natural, la extracción de datos y el web scraping. Vimos cómo realizar tareas básicas de NLP, como la tokenización, la lematización y el análisis de sentimientos con la biblioteca Pattern. 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. .