Niveau
Expert
Env.
Local (Windows), Local (Linux), Google Colab
Code
Python
Libs
spacy
Sources

Tuto : Le NLP avec SpaCy !

Du NLP (Natural Language Processing) oui mais avec quoi ?

Chose promise, chose due ! je vous avais fait part dans mon article sur les sac de mots que nous irions plus loin avec du NLP, et bien nous y voilà. Maintenant, quel outillage choisir ? quelle librairie utiliser ? en effet le monde Python semble se déchirer entre deux package : l’un historique NLTK (Natural Language Toolkit) et le petit nouveau SpaCy (2015).

Loin de moi l’idée de faire un comparatif de ces deux très bonnes librairies que sont NLTK et SpaCy. Il y a du pour et du contre chez chacune, mais la facilité d’utilisation, la disponibilité de vecteurs de mots pré-entraînés ainsi que des modèles statistiques dans plusieurs langues (anglais, allemand et espagnol) mais surtout en Français m’ont définitivement fait basculer vers SpaCy. Place aux jeunes 😉

Ce petit tuto va donc vous montrer comment utiliser cette librairie.

Installer et utiliser la librairie

Cette librairie n’est pas installée par défaut avec Python. Pour l’installer le plus simple est de lancer une ligne de commande et de faire appel à l’utilitaire pip comme suit :

ShellSession
pip install -U spaCy
python -m spacy download fr
python -m spacy download fr_core_news_md

NB: Les deux dernières commandes permettent d’utiliser les modèles déjà entrainés en Français. Ensuite pour utiliser SpaCy il faut importer la librairie mais aussi l’initialiser avec la bonne langue avec la directive load()

Python
import spacy
from spacy import displacy
nlp = spacy.load('fr')

La tokenisation

La première chose que nous allons faire est de « tokeniser » une phrase afin de la découper grammaticalement. La tokenisation est l’opération qui consiste à segmenter une phrase en unités « atomiques » : les tokens. Les tokenisations les plus courantes sont le découpage en mots ou bien en phrases. Nous allons commencer par les mots et pour cela nous utiliserons la classe token de SpaCy :

Python
import spacy
from spacy import displacy
nlp = spacy.load('fr')
doc = nlp('Demain je travaille à la maison')
for token in doc:
    print(token.text)

Le code précédent découpe la phrase ‘Demain je travaille à la maison’ et affiche chaque élément

Demain
je
travaille
à
la
maison
en
France

Rien de très impressionnant pour l’instant, nous avons juste découpé une phrase. Regardons maintenant de plus près ce qu’a fait en plus SpaCy lors de ce découpage :

Python
doc = nlp("Demain je travaille à la maison.")
for token in doc:
    print("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}".format(
        token.text,
        token.idx,
        token.lemma_,
        token.is_punct,
        token.is_space,
        token.shape_,
        token.pos_,
        token.tag_,
        token.ent_type_
    ))

L’objet token est bien plus riche qu’il n’y parait et renvoit beaucoup d’informations grammaticales sur les mots de la phrase :

Demain	0	Demain	False	False	Xxxxx	PROPN	PROPN___	
je	7	il	False	False	xx	PRON	PRON__Number=Sing|Person=1	
travaille	10	travailler	False	False	xxxx	VERB	VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin	
à	20	à	False	False	x	ADP	ADP___	
la	22	le	False	False	xx	DET	DET__Definite=Def|Gender=Fem|Number=Sing|PronType=Art	
maison	25	maison	False	False	xxxx	NOUN	NOUN__Gender=Fem|Number=Sing	
.	31	.	True	False	.	PUNCT	PUNCT___	

Cet objet nous informe de l’utilisation/qualification de chaque mot (pour plus de détails allez dans l’aide de SpaCy):

  • text: Le texte/mot original
  • lemma_: la forme de base du mot (pour un verbe conjugué par exemple on aura son infinitif)
  • pos_: Le tag part-of-speech (détail ici)
  • tag_: Les informations détaillées part-of-speech (détail ici)
  • dep_: Dépendance syntaxique (inter-token)
  • shape: format/pattern
  • is_alpha: Alphanumérique ?
  • is_stop: Le mot fait-il partie d’une Stop-List ?
  • etc.

Tokenison maintenant des phrases. En fait le travail est déjà fait (Cf. documentation) et il suffit de récupérer l’objet sents du document :

Python
doc = nlp("Demain je travaille à la maison. Je vais pouvoir faire du NLP")
for sent in doc.sents:
    print(sent)

Le résultat :

Demain je travaille à la maison.
Je vais pouvoir faire du NLP

SpaCy permet bien sur de récupérer les phrases nominales (cad les phrases sans verbes):

Python
doc = nlp("Terrible désillusion pour la championne du monde")
for chunk in doc.noun_chunks:
    print(chunk.text, " --> ", chunk.label_)
Terrible désillusion pour la championne du monde  -->  NP

NER

SpaCy dispose d’un système de reconnaissance d’entités statistiques (NER ou Named Entity Recognition) très performant et qui va assigner des étiquettes à des plages contiguës de tokens.

Python
doc = nlp("Demain je travaille en France chez Tableau")
for ent in doc.ents:
    print(ent.text, ent.label_)

Le code précédent parcours les mots dans leur contexte et va reconnaître que la France est un élément de localisation et que Tableau est une organisation (commerciale) :

France LOC
Tableau ORG

Dépendances

Personnellement je trouve que c’est la fonction la plus impressionnante car grâce à elle nous allons pouvoir recomposer une phrase en reliant les mots dans leur contexte. Dans l’exemple ci-dessous nous reprenons notre phrase et indiquons chaque dépendance avec les propriétés dep_

Python
doc = nlp('Demain je travaille en France chez Tableau')
for token in doc:
    print("{0}/{1} <--{2}-- {3}/{4}".format(
                                        token.text, 
                                        token.tag_, 
                                        token.dep_, 
                                        token.head.text, 
                                        token.head.tag_))

Le résultat est intéressant mais pas vraiment lisible :

Demain/PROPN___ <--advmod-- travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
je/PRON__Number=Sing|Person=1 <--nsubj-- travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin <--ROOT-- travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
en/ADP___ <--case-- France/PROPN__Gender=Fem|Number=Sing
France/PROPN__Gender=Fem|Number=Sing <--obl-- travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
chez/ADP___ <--case-- Tableau/NOUN__Gender=Masc|Number=Sing
Tableau/NOUN__Gender=Masc|Number=Sing <--obl-- travaille/VERB__Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin

Heureusement SpaCy a une fonction de trace pour rendre ce résultat visuel. Pour l’utiliser vous devez importer displacy:

Python
from spacy import displacy
displacy.render(doc, style='dep', jupyter=True, options={'distance': 130})

C’est tout de suite plus parlant comme ça non ?

Voilà qui conclu cette première partie sur l’utilisation de NLP avec la librairie SpaCy. Pour les curieux du NLP, n’hésitez pas à lire aussi mon article sur NLTK.

Partager cet article

12 Replies to “Tuto : Le NLP avec SpaCy !”

  1. Très intéressant et très utile.
    Je passe à Spacy !
    J’analyse le grand débat national comme exemple d’une analyse d’opinions liées aux questions.
    Dominique Pignon
    Directeur de recherches cnrs

  2. J’ai fait quelques tests avec spaCy en français avec les derniers pack 2020. Je suis assez surpris par la renommée de l’outil, le résultat est plutôt nul. La détection des verbes marche plutôt pas mal, mais avec un bête algo associé à une racinisation et un dico FR, j’aurais explosé ses performances. Concernant la détection des entités nommé, c’est ni fait ni à faire. Le résultat est complètement hasardeux et absurde. Pour le coup un algo de détection des termes ucfirst associé à une regexp détectant les mots après les déterminants aurait fait 100x mieux. C’est vraiment décevant.

  3. C’est vrai que les modèles entraînés en Français ne sont pas au niveaux de ceux en Anglais (comme très souvent d’ailleurs). Rien de magique non plus avec le NLP il faut souvent retravailler les résultats obtenus ou mieux préparer les données en amont. @AtomBusiness, pourrais-tu peut être nous faire partager plus en détail ton expérience ?

  4. Oui c’est le sentiment que j’en ai eu en testant. J’ai l’impression qu’il a été entraîné sur de l’anglais et adapté pour le français.
    Sur des phrases longues, j’avais de très mauvais résultats, donc j’ai testé sur des phrases très courtes, et je vous laisse voir le résultat : https://imgur.com/a/il0YMc2

    Donc pour l’instant je suis dos au mur, je ne sais pas quel outils me permettrait d’extraire mes verbes/entitées nommées efficacement dans une phrase. Je misais beaucoup sur spaCy, mais en l’état il est inutilisable dans une industrialisation sérieuse.

  5. Pour info et retour d’expérience …
    Je développe un assistant vocal en français entres autres php (Symfony) et j’ai regardé un peu spaCy.
    Je rejoins les commentaires plutôt négatifs ci-dessus sur son intérêt et ses performances du moins en français.
    Outre le fait que l’usage soit plutôt en python qui aurait donc demandé dans mon architecture un wrapper php, j’ai développé des fonctions simples d’analyse lexicale et syntaxique qui rendent le service.
    Pour la tokenisation et la classification, j’ai utilisé la bibliothèque php ai-ml.
    Cet assistant vocal s’intègre dans un projet de smart-home qui fonctionne depuis quelques années.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.