title | description | prev | next | type | id |
---|---|---|---|---|---|
Capítulo 2: Análisis de datos a gran escala con spaCy |
En este capítulo usarás tus nuevas habilidades para extraer información específica de grandes volúmenes de texto. Aprenderás a sacarle el mayor provecho a las estructuras de datos de spaCy y cómo combinar los enfoques estadísticos y basados en reglas de manera efectiva para el análisis de texto. |
/chapter1 |
/chapter3 |
chapter |
2 |
- Busca el string "cat" en
nlp.vocab.strings
para obtener el hash. - Busca el hash para obtener el string.
- Puedes usar el string store en
nlp.vocab.strings
como un diccionario de Python normal. Por ejemplo,nlp.vocab.strings["unicornio"]
devolverá el hash y buscar el hash devolverá el string"unicornio"
.
- Busca el label del string "PER" en
nlp.vocab.strings
para obtener el hash. - Busca el hash para obtener el string.
- Puedes usar el string store en
nlp.vocab.strings
como un diccionario de Python normal. Por ejemplo,nlp.vocab.strings["unicornio"]
devolverá el hash y buscar el hash devolverá el string"unicornio"
.
¿Porqué devuelve un error este código?
from spacy.lang.es import Spanish
from spacy.lang.de import German
# Crea un objeto nlp de español y uno de alemán
nlp = Spanish()
nlp_de = German()
# Obtén el ID para el string "Bowie"
bowie_id = nlp.vocab.strings["Bowie"]
print(bowie_id)
# Busca el ID de "Bowie" en el vocabulario
print(nlp_de.vocab.strings[bowie_id])
Los hashes no pueden ser revertidos. Para prevenir este problema añade la palabra al nuevo vocabulario. Para hacer esto, procesa el texto, busca el string, o usa el mismo vocabulario para resolver el hash de regreso a string.
Cualquier string puede ser convertido a un hash.
El nombre de variable nlp
es solo una convención. Si el código usara el nombre
de variable nlp
en vez de nlp_de
se sobrescribiría el objeto nlp
existente, incluyendo el vocabulario.
¡Creemos algunos objetos Doc
desde cero!
- Importa el
Doc
desdespacy.tokens
. - Crea un
Doc
a partir dewords
yspaces
. ¡No te olvides de pasar el vocabulario!
La clase Doc
recibe 3 argumentos: el vocabulario compartido (generalmente
nlp.vocab
), una lista de words
y una lista de spaces
, ( valores booleanos
que indican si una palabra está seguida de un espacio o no).
- Importa el
Doc
desdespacy.tokens
. - Crea un
Doc
a partir dewords
yspaces
. ¡No te olvides de pasar el vocabulario!
Mira cada palabra en el texto deseado y revisa si está seguido por un espacio.
Si lo está, el valor del espacio debería ser True
. Si no, debería ser False
.
- Importa el
Doc
desdespacy.tokens
. - Completa los
words
y losspaces
para que coincidan con el texto deseado y crea undoc
.
Presta atención a los tokens individuales. Para ver cómo se tokeniza un string
normalmente en spaCy puedes probarlo e imprimir los tokens de
nlp("¡¿En serio?!")
.
En este ejercicio crearás los objetos Doc
y Span
manualmente y actualizarás
las entidades nombradas - igual que lo hace spaCy detrás de cámaras. Un objeto
nlp
compartido ya fue creado.
- Importa las clases
Doc
ySpan
desdespacy.tokens
. - Usa la clase
Doc
directamente para crear undoc
a partir de palabras y espacios. - Crea un
Span
para "David Bowie" desde eldoc
y asígnalo al label"PER"
. - Sobrescribe los
doc.ents
con una lista de una entidad, elSpan
"David Bowie".
- El
Doc
es inicializado con tres argumentos: el vocabulario compartido, e.g.nlp.vocab
, una lista de palabras y una lista de valores booleanos que indican si una palabra está seguida por un espacio. - La clase
Span
recibe cuatro argumentos: eldoc
de referencia, el índice de inicio del token, el índice del final del token y un label opcional. - La propiedad
doc.ents
es escribible así que puedes asignarle cualquier iterable que consista de objetosSpan
.
El código en este ejemplo está intentando analizar un texto y recoger todos los nombres propios que están seguidos por un verbo.
import spacy
nlp = spacy.load("es_core_news_sm")
doc = nlp("Por Berlín fluye el río Esprea.")
# Obtén todos los tokens y los part-of-speech tags
token_texts = [token.text for token in doc]
pos_tags = [token.pos_ for token in doc]
for index, pos in enumerate(pos_tags):
# Revisa si el token actual es un nombre propio
if pos == "PROPN":
# Revisa si el token siguiente es un verbo
if pos_tags[index + 1] == "VERB":
result = token_texts[index]
print("Encontré un nombre propio antes de un verbo:", result)
¿Por qué está mal este código?
No debería ser necesario convertir strings de regreso a objetos Token
.
Deberías evitar convertir tokens a strings si todavía necesitas acceder a sus
atributos y relaciones.
Siempre convierte los resultados a strings lo más tarde posible e intenta usar los atributos nativos de los tokens para mantener la consistencia.
El atributo .pos_
devuelve el part-of-speech tag grueso y PROPN
es el tag
correcto para revisar los nombres propios.
- Reescribe el código y usa los atributos nativos de los tokens en vez de listas
de
token_texts
ypos_tags
. - Has un loop sobre cada
token
en eldoc
y revisa el atributotoken.pos_
. - Usa
doc[token.i + 1]
para revisar el token siguiente y su atributo.pos_
. - Si encuentras un nombre propio antes de un verbo imprime en pantalla su
token.text
.
- Quita los
token_texts
ypos_tags
– ¡No necesitamos compilar listas de strings por adelantado! - En vez de iterar sobre los
pos_tags
, has un loop sobre cadatoken
en eldoc
y revisa el atributotoken.pos_
. - Para chequear si el próximo token es un verbo, mira el
doc[token.i + 1].pos_
.
En este ejercicio usarás un modelo de español más grande, que incluye al rededor de 20.000 word vectors. El modelo ya está pre-instalado.
- Carga el modelo mediano
"es_core_news_md"
con word vectors. - Imprime en pantalla el vector de
"banano"
usando el atributotoken.vector
.
- Para cargar el modelo estadístico llama a
spacy.load
con su nombre en string. - Para acceder al token en el doc puedes usar su índice. Por ejemplo,
doc[4]
.
En este ejercicio usarás el método similarity
de spaCy para comparar objetos
Doc
, Token
y Span
y obtener puntajes de similitud.
- Usa el método
doc.similarity
para comparar eldoc1
con eldoc2
e imprime el resultado en pantalla.
- El método
doc.similarity
recibe un argumento: el otro objeto con el que debe comparar el objeto actual.
- Usa el método
token.similarity
para comparar eltoken1
altoken2
e imprime el resultado en pantalla.
- El método
token.similarity
recibe un argumento: el otro objeto con el que debe comparar el objeto actual.
- Crea spans para "restaurante genial"/ "bar muy divertido".
- Usa
span.similarity
para compararlos e imprime el resultado en pantalla.
¿Por qué este patrón no encuentra los tokens "Silicon Valley" en el doc
?
pattern = [{"LOWER": "silicon"}, {"TEXT": " "}, {"LOWER": "valley"}]
doc = nlp("¿Por qué Silicon Valley necesita miles de astrofísicos?")
El atributo LOWER
en el patrón describe a los tokens que pueden ser
encontrados con el valor dado en minúsculas. Así, {"LOWER": "valley"}
encontrará tokens como "Valley", "VALLEY", "valley", etc.
El tokenizer se encarga de hacer las separaciones por los espacios en blanco y cada diccionario en el patrón describe un token.
Por defecto, todos los tokens descritos por un patrón van a ser encontrados una vez. Los operadores solo tienen que ser añadidos para cambiar este comportamiento - por ejemplo, para encontrar cero o más veces.
Los dos patrones en este ejercicio contienen errores y no van a tener los
resultados esperados. ¿Puedes arreglarlos? Si te atascas intenta imprimir en
pantalla los tokens en el doc
para ver cómo se va a dividir el texto y ajusta
el patrón para que cada diccionario represente un token.
- Edita el
pattern1
para que encuentre correctamente todas las menciones de una cantidad de tiempo, más un sustantivo. - Edita el
pattern2
para que encuentre correctamente todas las menciones de"pac-man"
, sin importar si son minúsculas o mayúsculas, más una palabra en mayúsculas.
- Procesa los strings que deben ser encontrados con el objeto
nlp
- for ejemplo,[token.text for token in nlp("pac-man Live")]
. - Inspecciona los tokens y asegúrate de que cada diccionario en el patrón describa correctamente a un token.
A veces es más eficiente buscar los strings exactos en vez de escribir los
patrones describiendo los tokens individuales. Esto es especialmente cierto para
cosas que tienen categorías finitas - como todos los países del mundo. Aquí
tenemos una lista de países, así que usémoslos como base para nuestro script
para extraer información. La lista de nombres en strings está disponible en la
variable COUNTRIES
.
- Importa el
PhraseMatcher
e inicialízalo con elvocab
compartido como la variablematcher
. - Añade los patrones de frases y llama al matcher sobre el
doc
.
El vocab
compartido está disponible como nlp.vocab
.
En el ejercicio anterior escribiste un script usando el PhraseMatcher
de spaCy
para encontrar nombres de países en un texto. Usemos ese buscador de países en
un texto más largo. Analiza la sintaxis y actualiza las entidades del documento
con los países resultantes.
- Itera sobre los resultados y crea un
Span
con el label"LOC"
(Nombres de ubicaciones definidas política o geográficamente). - Sobrescribe las entidades en el
doc.ents
y añade el span resultante. - Obtén el token cabeza de la raíz del span.
- Imprime en pantalla el texto del token cabeza y el span.
- Recuerda que el texto está disponible como la variable
text
. - El token raíz del span está disponible como
span.root
. El token cabeza está disponible a través del atributotoken.head
.