title | description | prev | next | type | id |
---|---|---|---|---|---|
Chapitre 2 : analyse de données à grande échelle avec spaCy |
Dans ce chapitre, tu vas utiliser tes nouvelles compétences pour extraire des informations spécifiques à partir de grandes quantités de textes. Tu vas apprendre à tirer le meilleur parti des structures de données de spaCy, et comment combiner efficacement les approches statistiques et celles basées sur les règles pour l'analyse de textes. |
/chapter1 |
/chapter3 |
chapter |
2 |
- Recherche la chaîne de caractères "chat" dans
nlp.vocab.strings
pour obtenir le hash. - Recherche le hash pour revenir à la chaîne de caractères.
- Tu peux utiliser le magasin de chaînes de caractères
nlp.vocab.strings
comme un dictionnaire Python normal. Par exemplenlp.vocab.strings["licorne"]
va retourner le hash, et la recherche du hash va retourner la chaîne"licorne"
.
- Recherche l'étiquette de la chaîne "PER" dans
nlp.vocab.strings
pour obtenir le hash. - Recherche le hash pour revenir à la chaîne de caractères.
- Tu peux utiliser le magasin de chaînes de caractères
nlp.vocab.strings
comme un dictionnaire Python normal. Par exemplenlp.vocab.strings["licorne"]
va retourner le hash, et la recherche du hash va retourner la chaîne"licorne"
.
Pourquoi ce code génère-t-il une erreur ?
import spacy
# Crée un objet nlp pour le français et un pour l'allemand
nlp = spacy.blank("fr")
nlp_de = spacy.blank("de")
# Obtiens l'ID pour la chaîne 'Bowie'
bowie_id = nlp.vocab.strings["Bowie"]
print(bowie_id)
# Recherche l'ID de "Bowie" dans le vocabulaire
print(nlp_de.vocab.strings[bowie_id])
Les hashes ne peuvent pas être inversés. Pour éviter ce problème, ajoute le mot au nouveau vocabulaire en traitant un texte ou en cherchant la chaîne, ou utilise le même vocabulaire pour résoudre le hash vers une chaîne.
N'importe quelle chaîne de caractères peut être convertie en hash.
Le nom de variable nlp
est seulement une convention. Si le code utilisait le
nom de variable nlp
au lieu de nlp_de
, il écraserait l'objet nlp
existant,
vocabulaire y compris.
Créons quelques objets Doc
de toutes pièces !
- Importe le
Doc
depuisspacy.tokens
. - Crée un
Doc
à partir deswords
et desspaces
. N'oublie pas de passer le vocabulaire en argument !
La classe Doc
prend 3 arguments : le vocabulaire partagé, généralement
nlp.vocab
, une liste de words
et une liste de spaces
, valeurs booléennes
indiquant si le mot est suivi par un espace ou pas.
- Importe le
Doc
depuisspacy.tokens
. - Crée un
Doc
à partir deswords
et desspaces
. N'oublie pas de passer le vocabulaire en argument !
Inspecte chaque mot du résultat textuel souhaité et vérifie s'il est suivi par
un espace. Si c'est le cas, les valeurs d'espace doivent être True
. Sinon,
elles doivent être False
.
- Importe le
Doc
depuisspacy.tokens
. - Complète les
words
etspaces
pour correspondre au texte désiré et créer undoc
.
Fais attention aux tokens individuels. Pour voir comment spaCy effectue
normalement cette chaîne, tu peux essayer d'afficher les tokens pour
nlp("Oh, vraiment ?!")
.
Dans cet exercice, tu vas créer les objets Doc
et Span
manuellement, et
actualiser les entités nommées – exactement comme spaCy le fait en coulisses. Un
objet nlp
partagé a déjà été créé.
- Importe les classes
Doc
etSpan
depuisspacy.tokens
. - Utilise la classe
Doc
directement pour créer undoc
à partir des mots et des espaces. - Crée un
Span
pour "David Bowie" à partir dudoc
et assigne-lui le label"PER"
("personne"). - Remplace
doc.ents
par une liste d'une seule entité, lespan
"David Bowie".
- Le
Doc
est initialisé avec trois arguments : le vocabulaire partagé, par exemplenlp.vocab
, une liste de mots et une liste de valeurs booléennes indiquant si le mot doit ou non être suivi par un espace. - La classe
Span
prend quatre arguments: ledoc
de référence, l'indice du token de début, l'indice du token de fin et un label optionnel. - La propriété
doc.ents
est accessible en écriture, tu peux donc lui assigner n'importe quel itérable composé d'objetsSpan
.
Le code de cet exemple essaie d'analyser un texte et de recueillir tous les noms propres qui sont suivis par un verbe.
import spacy
nlp = spacy.load("fr_core_news_sm")
doc = nlp("Berlin semble être une jolie ville")
# Obtiens tous les tokens et les étiquettes de partie de discours
token_texts = [token.text for token in doc]
pos_tags = [token.pos_ for token in doc]
for index, pos in enumerate(pos_tags):
# Vérifie si le token courant est un nom propre
if pos == "PROPN":
# Vérifie si le token suivant est un verbe
if pos_tags[index + 1] == "VERB":
result = token_texts[index]
print("Trouvé un nom propre avant un verbe :", result)
Pourquoi le code est-il mauvais ?
Il ne sera pas nécessaire de reconvertir les chaînes en objets Token
. Evite
plutôt de convertir les tokens en chaînes de caractères si tu as encore besoin
d'accéder à leurs attributs et leurs relations.
Convertis toujours les résultats en chaînes le plus tard possible, et essaie d'utiliser les attributs natifs des tokens pour garder un code cohérent.
L'attribut .pos_
retourne l'étiquetage grossier de partie de discours et
"PROPN"
est le bon label pour chercher des noms propres.
- Réécris le code pour utiliser les attributs de tokens natifs au lieu des
listes
token_texts
etpos_tags
. - Boucle sur chaque
token
dudoc
et contrôle son attributtoken.pos_
. - Utilise
doc[token.i + 1]
pour vérifier le token suivant et son attribut.pos_
. - Si un nom propre est trouvé devant un verbe, affiche son
token.text
.
- Supprime les
token_texts
etpos_tags
– on n'a pas besoin de compiler d'avance des listes de chaînes de caractères ! - Au lieu d'itérer sur les
pos_tags
, boucle sur chaquetoken
dans ledoc
et vérifie l'attributtoken.pos_
. - Pour savoir si le token suivant est un verbe, jette un oeil à
doc[token.i + 1].pos_
.
Dans cet exercice, nous utiliserons un pipeline français plus étendu, qui comporte environ 20.000 vecteurs de mots. Le package de pipeline est déjà pré-installé.
- Charge le pipeline moyen avec vecteurs de mots
"fr_core_news_md"
. - Affiche le vecteur pour
"bananes"
en utilisant l'attributtoken.vector
.
- Pour charger un pipeline entraîné, appelle
spacy.load
avec son nom sous forme de chaîne de caractères. - Pour accéder à un token dans un doc, tu peux utiliser son indice. Par exemple,
doc[4]
.
Dans cet exercice, tu vas utiliser les méthodes similarity
de spaCy pour
comparer des objets Doc
, Token
et Span
et obtenir leurs scores de
similarité.
- Utilise la méthode
doc.similarity
pour comparerdoc1
àdoc2
et afficher le résultat.
La méthode doc.similarity
prend un argument : l'autre objet auquel l'objet
courant doit être comparé.
- Utilise la méthode
token.similarity
pour comparertoken1
àtoken2
et afficher le résultat.
- La méthode
token.similarity
prend un argument : l'autre objet auquel l'objet courant doit être comparé.
- Crée des spans pour "super restaurant" et "bar vraiment sympa".
- Utilise
span.similarity
pour les comparer et afficher le résultat.
Pourquoi ce motif ne trouve-t-il pas les tokens "Silicon Valley" dans le doc
?
pattern = [{"LOWER": "silicon"}, {"TEXT": " "}, {"LOWER": "valley"}]
doc = nlp("Pourquoi la Silicon Valley est-elle si prisée ?")
L'attribut "LOWER"
dans le motif décrit des tokens dont la forme minuscule
correspond à une valeur donnée. Ainsi {"LOWER": "valley"}
trouvera les tokens
"Valley", "VALLEY", "valley" etc.
Le tokenizer effectue déjà la séparation sur la base des espaces et chaque dictionnaire du motif contient un token.
Par défaut, tous les tokens décrits dans un motif doivent être trouvés exactement une fois. Les opérateurs sont nécessaires uniquement pour modifier ce comportement – par exemple, pour trouver zéro ou plusieurs fois un token.
Les deux motifs de cet exercice comportent des erreurs et ne vont pas
fonctionner comme souhaité. Peux-tu les corriger ? Si tu es bloqué, essaie
d'afficher les tokens du doc
pour voir comment le texte sera séparé et ajuster
les motifs pour que chaque dictionnaire représente un token.
- Édite
pattern1
pour qu'il trouve correctement toutes les mentions quelle que soit la casse pour"Amazon"
suivi d'un nom propre commençant par une majuscule. - Édite
pattern2
pour qu'il trouve correctement toutes les mentions d'un nom suivi de"tout-compris"
quelle que soit sa casse.
- Essaie de traiter les chaînes qui devraient être trouvées par l'objet
nlp
– par exemple[token.text for token in nlp("abonnement tout-compris")]
. - Inspecte les tokens et vérifie que chaque dictionnaire du motif décrit correctement un seul token.
Parfois il est plus efficace de rechercher des chaînes de caractères exactes au
lieu d'écrire des motifs décrivant individuellement les tokens. C'est
particulièrement vrai pour les catégories finies - comme l'ensemble des pays du
monde. Nous disposons déjà d'une liste de pays, alors utilisons-là comme base
pour notre script d'extraction d'informations. Une liste de chaînes est
caractères est accessible via la variable COUNTRIES
.
- Importe le
PhraseMatcher
et initialise-le avec levocab
partagé dans la variablematcher
. - Ajoute les motifs de phrase et appelle le matcher sur le
doc
.
Le vocab
partagé est accessible avec nlp.vocab
.
Dans l'exercice précédent, tu as écrit un script utilisant le PhraseMatcher
de
spaCy pour trouver des noms de pays dans un texte. Nous allons maintenant
l'utiliser sur un texte plus long, analyser la syntaxe et mettre à jour les
entités du document avec les pays trouvés.
- Itère sur les correspondances et crée un
Span
avec le label"GPE"
(entité géopolitique). - Mets à jour les entités dans
doc.ents
en y ajoutant les spans trouvés. - Obtiens la tête du token racine du span trouvé.
- Affiche le texte de la tête et le span.
- Rappelle-toi que le texte est disponible avec la variable
text
. - Le token racine du span est accessible avec
span.root
. La tête d'un token est accessible avec l'attributtoken.head
.