Python para PNL: combinación de vocabulario y frases con SpaCy

Este es el tercer artículo de esta serie de artículos sobre Python para el procesamiento del lenguaje natural. En el artículo anterior, vimos cómo las bibliotecas NLTK y spaCy de Python...

Este es el tercer artículo de esta serie de artículos sobre Python para el procesamiento del lenguaje natural. En el Artículo anterior, vimos cómo NLTK de Python y [spacey](https://space .io/) se pueden usar para realizar tareas simples de NLP como tokenización, [derivación y lematización](https://nlp.stanford. edu/IR-book/html/htmledition/stemming-and-lemmatization-1.html). También vimos cómo realizar el etiquetado de partes del discurso, el reconocimiento de entidades nombradas y el análisis de sustantivos. Sin embargo, todas estas operaciones se realizan en palabras individuales.

En este artículo, avanzaremos un paso más y exploraremos el vocabulario y la combinación de frases usando la biblioteca spaCy. Definiremos patrones y luego veremos qué frases coinciden con el patrón que definimos. Esto es similar a definir expresiones regulares que involucran partes del discurso.

Coincidencia basada en reglas

La biblioteca spaCy viene con la herramienta Matcher que se puede usar para especificar reglas personalizadas para la coincidencia de frases. El proceso para usar la herramienta Matcher es bastante sencillo. Lo primero que tienes que hacer es definir los patrones que quieres hacer coincidir. A continuación, debe agregar los patrones a la herramienta ‘Coincidir’ y, finalmente, debe aplicar la herramienta ‘Coincidir’ al documento con el que desea hacer coincidir sus reglas. Esto se explica mejor con la ayuda de un ejemplo.

Para la coincidencia basada en reglas, debe realizar los siguientes pasos:

Creación de un objeto coincidente

El primer paso es crear el objeto comparador:

1
2
3
4
5
import spacy
nlp = spacy.load('en_core_web_sm')

from spacy.matcher import Matcher
m_tool = Matcher(nlp.vocab)

Definición de patrones {#definición de patrones}

El siguiente paso es definir los patrones que se utilizarán para filtrar frases similares. Supongamos que queremos encontrar las frases "quick-brown-fox", "quick brown fox", "quickbrownfox" o "quick brownfox". Para hacerlo, necesitamos crear los siguientes cuatro patrones:

1
2
3
4
p1 = [{'LOWER': 'quickbrownfox'}]
p2 = [{'LOWER': 'quick'}, {'IS_PUNCT': True}, {'LOWER': 'brown'}, {'IS_PUNCT': True}, {'LOWER': 'fox'}]
p3 = [{'LOWER': 'quick'}, {'LOWER': 'brown'}, {'LOWER': 'fox'}]
p4 =  [{'LOWER': 'quick'}, {'LOWER': 'brownfox'}]

En el guión anterior,

  • p1 busca la frase "quickbrownfox"
  • p2 busca la frase "quick-brown-fox"
  • p3 intenta buscar "qucik brown fox"
  • p4 busca la frase "quick brownfox"

El atributo del token LOWER define que la frase debe convertirse a minúsculas antes de la coincidencia.

Una vez que se definen los patrones, debemos agregarlos al objeto Matcher que creamos anteriormente.

1
m_tool.add('QBF', None, p1, p2, p3, p4)

Aquí "QBF" es el nombre de nuestro comparador. Puedes darle cualquier nombre.

Aplicación de Matcher al documento

Ya tenemos listo nuestro emparejador. El siguiente paso es aplicar el comparador en un documento de texto y ver si podemos obtener alguna coincidencia. Primero vamos a crear un documento simple:

1
2
sentence = nlp(u'The quick-brown-fox jumps over the lazy dog. The quick brown fox eats well. \
               the quickbrownfox is dead. the dog misses the quick brownfox')

Para aplicar el comparador a un documento. Es necesario pasar el documento como un parámetro al objeto comparador. El resultado serán todos los identificadores de las frases coincidentes en el documento, junto con sus posiciones inicial y final en el documento. Ejecute el siguiente script:

1
2
phrase_matches = m_tool(sentence)
print(phrase_matches )

La salida del script anterior se ve así:

1
[(12825528024649263697, 1, 6), (12825528024649263697, 13, 16), (12825528024649263697, 21, 22), (12825528024649263697, 29, 31)]

En la salida, puede ver que se han hecho coincidir cuatro frases. El primer número largo en cada salida es la identificación de la frase coincidente, el segundo y tercer número son las posiciones inicial y final de la frase.

Para ver realmente el resultado de una mejor manera, podemos iterar a través de cada frase coincidente y mostrar su valor de cadena. Ejecute el siguiente script:

1
2
3
4
for match_id, start, end in phrase_matches:
    string_id = nlp.vocab.strings[match_id]  
    span = sentence[start:end]                   
    print(match_id, string_id, start, end, span.text)

Producción:

1
2
3
4
12825528024649263697 QBF 1 6 quick-brown-fox
12825528024649263697 QBF 13 16 quick brown fox
12825528024649263697 QBF 21 22 quickbrownfox
12825528024649263697 QBF 29 31 quick brownfox

Desde la salida, puede ver todas las frases coincidentes junto con sus identificadores de vocabulario y la posición inicial y final.

Más opciones para la coincidencia basada en reglas

La documentación oficial de la biblioteca de sPacy contiene detalles de todas las fichas y comodines que se pueden usar para la coincidencia de frases.

Por ejemplo, el atributo "*" se define para buscar una o más instancias del token.

Escribamos un patrón simple que pueda identificar la frase "quick--brown--fox" o quick-brown---fox.

Primero eliminemos el emparejador anterior QBF.

1
m_tool.remove('QBF')

A continuación, necesitamos definir nuestro nuevo patrón:

1
2
p1 = [{'LOWER': 'quick'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'brown'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'fox'}]
m_tool.add('QBF', None, p1)

El patrón p1 coincidirá con todas las frases en las que haya uno o más signos de puntuación en la frase quick brown fox. Definamos ahora nuestro documento para filtrar:

1
sentence = nlp(u'The quick--brown--fox jumps over the  quick-brown---fox')

Puede ver que nuestro documento tiene dos frases quick--brown--fox y quick-brown---fox, que debe coincidir con nuestro patrón. Apliquemos nuestra matemática al documento y veamos los resultados:

1
2
3
4
5
6
phrase_matches = m_tool(sentence)

for match_id, start, end in phrase_matches:
    string_id = nlp.vocab.strings[match_id]  
    span = sentence[start:end]                   
    print(match_id, string_id, start, end, span.text)

La salida del script anterior se ve así:

1
2
12825528024649263697 QBF 1 6 quick--brown--fox
12825528024649263697 QBF 10 15 quick-brown---fox

A partir de la salida, puede ver que nuestro comparador ha hecho coincidir con éxito las dos frases.

Coincidencia basada en frases

En la última sección, vimos cómo podemos definir reglas que se pueden usar para identificar frases del documento. Además de definir reglas, podemos especificar directamente las frases que estamos buscando.
Esta es una forma más eficiente de hacer coincidir frases.

En esta sección, haremos coincidencias de frases dentro de un artículo de Wikipedia sobre inteligencia artificial.

Antes de ver los pasos para realizar la coincidencia de frases, primero analicemos el artículo de Wikipedia que usaremos para realizar la coincidencia de frases. Ejecute el siguiente script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import bs4 as bs  
import urllib.request  
import re  
import nltk

scrapped_data = urllib.request.urlopen('https://en.wikipedia.org/wiki/Artificial_intelligence')  
article = scrapped_data .read()

parsed_article = bs.BeautifulSoup(article,'lxml')

paragraphs = parsed_article.find_all('p')

article_text = ""

for p in paragraphs:  
    article_text += p.text
    
    
processed_article = article_text.lower()  
processed_article = re.sub('[^a-zA-Z]', ' ', processed_article )  
processed_article = re.sub(r'\s+', ' ', processed_article)

El script ha sido explicado en detalle en mi artículo sobre Implementando Word2Vec con Gensim Library en Python. Puedes ir a leer el artículo si quieres para entender cómo funciona el análisis en Python.

El artículo_procesado contiene el documento que usaremos para la coincidencia de frases.

Los pasos para realizar la coincidencia de frases son bastante similares a la coincidencia basada en reglas.

Crear objeto de comparación de frases

Como primer paso, debe crear el objeto PhraseMatcher. El siguiente script hace eso:

1
2
3
4
5
6
import spacy
nlp = spacy.load('en_core_web_sm')


from spacy.matcher import PhraseMatcher
phrase_matcher = PhraseMatcher(nlp.vocab)

Observe que en la sección anterior creamos el objeto Matcher. Aquí, en este caso, estamos creando el objeto PhraseMathcer.

Crear lista de frases

En el segundo paso, debe crear una lista de frases para que coincidan y luego convertir la lista en documentos spaCy NLP como se muestra en el siguiente script:

1
2
3
phrases = ['machine learning', 'robots', 'intelligent agents']

patterns = [nlp(text) for text in phrases]

Finalmente, debe agregar su lista de frases al comparador de frases.

1
phrase_matcher.add('AI', None, *patterns)

Aquí el nombre de nuestro emparejador es AI.

Aplicación de Matcher al documento

Al igual que la coincidencia basada en reglas, nuevamente debemos aplicar nuestro comparador de frases al documento. Sin embargo, nuestro artículo analizado no está en formato de documento spaCy. Por lo tanto, convertiremos nuestro artículo al formato de documento sPacy y luego aplicaremos nuestro comparador de frases al artículo.

1
2
3
sentence = nlp (processed_article)

matched_phrases = phrase_matcher(sentence)

En el resultado, tendremos todos los ID de todas las frases coincidentes junto con sus índices de inicio y finalización en el documento, como se muestra a continuación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[(5530044837203964789, 37, 39),
 (5530044837203964789, 402, 404),
 (5530044837203964789, 693, 694),
 (5530044837203964789, 1284, 1286),
 (5530044837203964789, 3059, 3061),
 (5530044837203964789, 3218, 3220),
 (5530044837203964789, 3753, 3754),
 (5530044837203964789, 5212, 5213),
 (5530044837203964789, 5287, 5288),
 (5530044837203964789, 6769, 6771),
 (5530044837203964789, 6781, 6783),
 (5530044837203964789, 7496, 7498),
 (5530044837203964789, 7635, 7637),
 (5530044837203964789, 8002, 8004),
 (5530044837203964789, 9461, 9462),
 (5530044837203964789, 9955, 9957),
 (5530044837203964789, 10784, 10785),
 (5530044837203964789, 11250, 11251),
 (5530044837203964789, 12290, 12291),
 (5530044837203964789, 12411, 12412),
 (5530044837203964789, 12455, 12456)]

Para ver el valor de cadena de las frases coincidentes, ejecute el siguiente script:

1
2
3
4
for match_id, start, end in matched_phrases:
    string_id = nlp.vocab.strings[match_id]  
    span = sentence[start:end]                   
    print(match_id, string_id, start, end, span.text)

En el resultado, verá el valor de cadena de las frases coincidentes como se muestra a continuación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
5530044837203964789 AI 37 39 intelligent agents
5530044837203964789 AI 402 404 machine learning
5530044837203964789 AI 693 694 robots
5530044837203964789 AI 1284 1286 machine learning
5530044837203964789 AI 3059 3061 intelligent agents
5530044837203964789 AI 3218 3220 machine learning
5530044837203964789 AI 3753 3754 robots
5530044837203964789 AI 5212 5213 robots
5530044837203964789 AI 5287 5288 robots
5530044837203964789 AI 6769 6771 machine learning
5530044837203964789 AI 6781 6783 machine learning
5530044837203964789 AI 7496 7498 machine learning
5530044837203964789 AI 7635 7637 machine learning
5530044837203964789 AI 8002 8004 machine learning
5530044837203964789 AI 9461 9462 robots
5530044837203964789 AI 9955 9957 machine learning
5530044837203964789 AI 10784 10785 robots
5530044837203964789 AI 11250 11251 robots
5530044837203964789 AI 12290 12291 robots
5530044837203964789 AI 12411 12412 robots
5530044837203964789 AI 12455 12456 robots

Desde el resultado, puede ver las tres frases que intentamos buscar junto con su índice de inicio y finalización y los identificadores de cadena.

Palabras vacías {#palabras vacías}

Antes de concluir este artículo, solo quería tocar el concepto de palabras vacías. Las palabras vacías son palabras en inglés como "the", "a", "an", etc. que no tienen ningún significado propio. Las palabras vacías a menudo no son muy útiles para tareas de PNL, como la clasificación de textos o el modelado del lenguaje. Por lo tanto, a menudo es mejor eliminar estas palabras vacías antes de continuar con el procesamiento del documento.

La biblioteca spaCy contiene 305 palabras vacías. Además, según nuestros requisitos, también podemos agregar o eliminar palabras vacías de la biblioteca spaCy.

Para ver las palabras vacías de spaCy predeterminadas, podemos usar el atributo stop_words del modelo spaCy como se muestra a continuación:

1
2
3
import spacy
sp = spacy.load('en_core_web_sm')
print(sp.Defaults.stop_words)

En el resultado, verá todas las palabras vacías de sPacy:

1
{'less', 'except', 'top', 'me', 'three', 'fifteen', 'a', 'is', 'those', 'all', 'then', 'everyone', 'without', 'must', 'has', 'any', 'anyhow', 'keep', 'through', 'bottom', 'get', 'indeed', 'it', 'still', 'ten', 'whatever', 'doing', 'though', 'eight', 'various', 'myself', 'across', 'wherever', 'himself', 'always', 'thus', 'am', 'after', 'should', 'perhaps', 'at', 'down', 'own', 'rather', 'regarding', 'which', 'anywhere', 'whence', 'would', 'been', 'how', 'herself', 'now', 'might', 'please', 'behind', 'every', 'seems', 'alone', 'from', 'via', 'its', 'become', 'hers', 'there', 'front', 'whose', 'before', 'against', 'whereafter', 'up', 'whither', 'two', 'five', 'eleven', 'why', 'below', 'out', 'whereas', 'serious', 'six', 'give', 'also', 'became', 'his', 'anyway', 'none', 'again', 'onto', 'else', 'have', 'few', 'thereby', 'whoever', 'yet', 'part', 'just', 'afterwards', 'mostly', 'see', 'hereby', 'not', 'can', 'once', 'therefore', 'together', 'whom', 'elsewhere', 'beforehand', 'themselves', 'with', 'seem', 'many', 'upon', 'former', 'are', 'who', 'becoming', 'formerly', 'between', 'cannot', 'him', 'that', 'first', 'more', 'although', 'whenever', 'under', 'whereby', 'my', 'whereupon', 'anyone', 'toward', 'by', 'four', 'since', 'amongst', 'move', 'each', 'forty', 'somehow', 'as', 'besides', 'used', 'if', 'name', 'when', 'ever', 'however', 'otherwise', 'hundred', 'moreover', 'your', 'sometimes', 'the', 'empty', 'another', 'where', 'her', 'enough', 'quite', 'throughout', 'anything', 'she', 'and', 'does', 'above', 'within', 'show', 'in', 'this', 'back', 'made', 'nobody', 'off', 're', 'meanwhile', 'than', 'neither', 'twenty', 'call', 'you', 'next', 'thereupon', 'therein', 'go', 'or', 'seemed', 'such', 'latterly', 'already', 'mine', 'yourself', 'an', 'amount', 'hereupon', 'namely', 'same', 'their', 'of', 'yours', 'could', 'be', 'done', 'whole', 'seeming', 'someone', 'these', 'towards', 'among', 'becomes', 'per', 'thru', 'beyond', 'beside', 'both', 'latter', 'ours', 'well', 'make', 'nowhere', 'about', 'were', 'others', 'due', 'yourselves', 'unless', 'thereafter', 'even', 'too', 'most', 'everything', 'our', 'something', 'did', 'using', 'full', 'while', 'will', 'only', 'nor', 'often', 'side', 'being', 'least', 'over', 'some', 'along', 'was', 'very', 'on', 'into', 'nine', 'noone', 'several', 'i', 'one', 'third', 'herein', 'but', 'further', 'here', 'whether', 'because', 'either', 'hereafter', 'really', 'so', 'somewhere', 'we', 'nevertheless', 'last', 'had', 'they', 'thence', 'almost', 'ca', 'everywhere', 'itself', 'no', 'ourselves', 'may', 'wherein', 'take', 'around', 'never', 'them', 'to', 'until', 'do', 'what', 'say', 'twelve', 'nothing', 'during', 'sixty', 'sometime', 'us', 'fifty', 'much', 'for', 'other', 'hence', 'he', 'put'}

También puede verificar si una palabra es una palabra vacía o no. Para hacerlo, puede usar el atributo is_stop como se muestra a continuación:

1
sp.vocab['wonder'].is_stop

Dado que "wonder" no es una palabra vacía, verás False en la salida.

Para agregar o eliminar palabras vacías en spaCy, puede usar los métodos sp.Defaults.stop_words.add() y sp.Defaults.stop_words.remove() respectivamente.

1
sp.Defaults.stop_words.add('wonder')

A continuación, debemos establecer la etiqueta is_stop para wonder en 'True` como se muestra a continuación:

1
sp.vocab['wonder'].is_stop = True

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Subtítulos de imágenes con CNN y Transformers con Keras"](https://wikihtp.com/courses/image-captioning-with-cnns-and -transformadores-con-keras/#cta){target="_blank"}.

En este proyecto guiado, aprenderá a crear un modelo de subtítulos de imágenes, que acepta una imagen como entrada y produce un subtítulo de texto como salida.

Aprenderás a:

  • Preprocesar texto
  • Vectorizar la entrada de texto fácilmente
  • Trabaje con la API tf.data y cree conjuntos de datos de alto rendimiento
  • Cree Transformers desde cero con TensorFlow/Keras y KerasNLP: la adición horizontal oficial a Keras para crear modelos NLP de última generación
  • Cree arquitecturas híbridas donde la salida de una red se codifica para otra

¿Cómo enmarcamos los subtítulos de las imágenes? La mayoría lo considera un ejemplo de aprendizaje profundo generativo, porque estamos enseñando a una red a generar descripciones. Sin embargo, me gusta verlo como una instancia de traducción automática neuronal: estamos traduciendo las características visuales de una imagen en palabras. A través de la traducción, estamos generando una nueva representación de esa imagen, en lugar de simplemente generar un nuevo significado. Verlo como traducción, y solo por generación de extensión, enfoca la tarea bajo una luz diferente y la hace un poco más intuitiva.

Enmarcar el problema como uno de traducción hace que sea más fácil averiguar qué arquitectura querremos usar. Los transformadores solo de codificador son excelentes para comprender el texto (análisis de opinión, clasificación, etc.) porque los codificadores codifican representaciones significativas. Los modelos de solo decodificador son excelentes para la generación (como GPT-3), ya que los decodificadores pueden inferir representaciones significativas en otra secuencia con el mismo significado. La traducción generalmente se realiza mediante una arquitectura de codificador-decodificador, donde los codificadores codifican una representación significativa de una oración (o imagen, en nuestro caso) y los decodificadores aprenden a convertir esta secuencia en otra representación significativa que es más interpretable para nosotros (como una oración).

Conclusión

La combinación de frases y vocabulario es una de las tareas de procesamiento de lenguaje natural más importantes. En este artículo, continuamos nuestra discusión sobre cómo usar Python para realizar coincidencias basadas en reglas y frases. Además, también vimos palabras vacías spaCy.

In the próximo artículo, we will see parts of speech tagging and named entity recognition in detail.