Aller au contenu principal

Module 1 — Chaîne de traitement du texte

Le fil rouge du cours est un corpus d'environ dix mille avis clients en français, notés de une à cinq étoiles. Avant tout modèle, ce corpus passe par une chaîne de traitement qui décide, texte par texte, ce qui compte et ce qui ne compte pas. Les décisions prises ici se propagent à tout le reste du cours : un accent supprimé au module 1 ne réapparaîtra jamais au module 6.

Ce qu'est un caractère en Unicode, et pourquoi cela compte

Le caractère « é » peut être une seule unité de code (U+00E9, forme précomposée) ou deux (U+0065 pour « e » suivi de U+0301 pour l'accent aigu combinant). Visuellement, le résultat est identique. Pour un ordinateur, ce sont deux chaînes différentes, et deux jetons différents.

import unicodedata

a = "café" # é précomposé
b = "cafe\u0301" # e + accent combinant
print(a == b) # False
print(len(a), len(b)) # 4, 5

na = unicodedata.normalize("NFC", a)
nb = unicodedata.normalize("NFC", b)
print(na == nb) # True

La forme NFC (Normalization Form Canonical Composition) recompose les caractères précomposés. C'est le format à imposer en entrée de tout pipeline. NFKC va plus loin : elle décompose puis remplace les équivalences de compatibilité — la ligature « fi » devient « fi », le chiffre en exposant « ² » devient « 2 ». Utile pour la recherche, dangereux pour la mise en forme d'origine.

La normalisation NFKC peut détruire de l'information

Sur un corpus financier ou scientifique, réécrire « m² » en « m2 » brouille des unités. Sur un corpus littéraire, aplatir les guillemets français « » en " fait disparaître un indice stylistique. Normalisez en NFC systématiquement, en NFKC seulement après avoir vérifié que rien d'important ne s'y perd.

Casse, ponctuation, chiffres : cinq décisions, jamais une seule

Le nettoyage réel n'est pas une case à cocher, mais une suite de cinq choix pour le corpus d'avis :

  1. Casse. Convertir en minuscules réduit le vocabulaire, mais perd « Paris » contre « paris » (verbe parier). Sur un corpus court, la perte est marginale ; sur un corpus long, elle mérite un test.
  2. Ponctuation. Un point d'exclamation double dans un avis à une étoile porte un signal réel — la colère, la déception. Le supprimer d'entrée, c'est se priver d'une caractéristique gratuite. On garde la ponctuation comme jeton à part entière, quitte à l'ignorer plus tard.
  3. Chiffres. Dans les avis, « 4/5 » et « 100 € » sont des indices forts. Les remplacer par un marqueur générique <NUM> réduit le vocabulaire sans effacer l'information.
  4. URL et emojis. Ils portent tous deux du signal : une URL peut signaler un avis suspect, un emoji résume souvent le sentiment. On les remplace par <URL> et un jeton par emoji.
  5. Élision française. « L'hôtel », « qu'il », « d'un » : la contraction avec l'apostrophe est propre au français. Séparer l'élision de sa base (« l'hôtel » → « l' hôtel ») évite d'apprendre séparément chaque combinaison.
import re

def nettoyer(texte: str) -> str:
texte = unicodedata.normalize("NFC", texte)
texte = re.sub(r"https?://\S+", " <URL> ", texte)
texte = re.sub(r"\d+([.,]\d+)?", " <NUM> ", texte)
texte = re.sub(r"([lLdDjJnNsScCmMtT])'", r"\1' ", texte) # élision
return texte.lower().strip()

print(nettoyer("L'hôtel est parfait ! Note : 4,5/5 sur https://ex.fr"))
# l' hotel est parfait ! note : <NUM> / <NUM> sur <URL>

Mots vides : la liste toute faite est un piège

La bibliothèque nltk livre une liste de mots vides pour le français ; spaCy en livre une autre, légèrement différente. Ce sont des points de départ, pas des vérités.

Le mot « pas », par exemple, est un mot vide dans presque toutes les listes. Sur un corpus d'avis, retirer « pas » transforme « ce n'est pas mal » en « ce est mal », et l'analyse de sentiment s'effondre. De même, « très » et « trop » sont vides selon nltk mais portent un signal d'intensité crucial. La règle pratique : on part de la liste par défaut, on retire les mots liés à la négation et à l'intensité, on l'écrit dans le dépôt et on la relit après chaque itération du modèle.

Ne jamais supprimer les mots vides avant les modèles neuronaux

Pour TF-IDF plus régression logistique (module 3), la suppression réduit le bruit. Pour un plongement (module 4) ou un modèle Transformer (module 6), chaque mot vide participe au contexte et le retirer dégrade toujours les résultats. La règle : suppression liée à l'algorithme, jamais à l'étape de nettoyage.

Racinisation et lemmatisation ne font pas le même travail

La racinisation (SnowballStemmer en français) applique une suite de règles heuristiques qui coupent les suffixes. « mangeaient », « mangera », « manger » deviennent tous « mang ». C'est rapide, brutal et parfois faux (« université » devient « univers »).

La lemmatisation (dans spaCy fr_core_news_sm) rend la forme canonique du mot d'après un analyseur morphologique : « mangeaient » devient « manger », « meilleur » devient « bon », les adjectifs féminins pluriels reviennent au masculin singulier. C'est cent à mille fois plus lent, mais linguistiquement juste.

import spacy

nlp = spacy.load("fr_core_news_sm", disable=["parser", "ner"])
doc = nlp("Les meilleurs hôtels étaient bloqués hier soir")
print([t.lemma_ for t in doc])
# ['le', 'bon', 'hôtel', 'être', 'bloqué', 'hier', 'soir']

Pour TF-IDF, la lemmatisation réduit fortement la dimension du vocabulaire et améliore souvent la référence. Pour un modèle préentraîné, elle est contre-productive : le modèle a été entraîné sur du texte non lemmatisé et attend les formes fléchies.

En résumé

  • Toute chaîne commence par une normalisation NFC ; NFKC seulement après avoir vérifié ce qu'elle change.
  • Les cinq décisions du nettoyage (casse, ponctuation, chiffres, URL, élision) sont un choix pédagogique, pas une recette ; les tester sur la métrique cible.
  • Les listes de mots vides toutes faites cassent l'analyse de sentiment : construire sa liste et l'appliquer seulement pour TF-IDF, jamais pour un modèle neuronal.
  • Racinisation contre lemmatisation : la première est rapide et fausse, la seconde lente et juste ; ne jamais lemmatiser en entrée d'un modèle préentraîné.

Module suivant : à partir du texte propre, comment le découper en jetons — mots, sous-mots, BPE, SentencePiece — et pourquoi la langue française paie plus cher que l'anglais.