Prétraitement du texte et tokenisation

Première leçon du cours Traitement du langage (NLP) et LLM, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Normaliser un texte (casse, accents, espaces) en connaissant les compromis
  • Découper un texte en tokens par mots puis en sous-mots
  • Comprendre le principe de l'algorithme BPE utilisé par les LLM

Normalisation du texteTokenisationByte Pair Encoding (BPE)

Un modèle de langage ne lit pas des phrases : il manipule des nombres. La première étape de tout projet NLP consiste donc à transformer le texte en une suite d’identifiants de tokens issus d’un vocabulaire fixe.

Normaliser le texte

La normalisation rend comparables des écritures différentes d’un même mot :

import re
import unicodedata

def normaliser(texte):
    texte = texte.lower()                                   # casse
    texte = unicodedata.normalize("NFD", texte)             # sépare lettres et accents
    texte = "".join(c for c in texte if unicodedata.category(c) != "Mn")
    texte = re.sub(r"\s+", " ", texte).strip()             # espaces multiples
    return texte

print(normaliser("  L'Été   est LÀ ! "))   # "l'ete est la !"

Chaque choix a un coût : retirer les accents confond « pêche » et « pèche », passer en minuscules efface la différence entre « Apple » et « apple ». Pour un classifieur TF-IDF, une normalisation forte aide souvent ; pour un modèle Transformer pré-entraîné, on ne normalise presque pas : son tokenizer a été conçu pour le texte brut. Règle essentielle : le même prétraitement doit être appliqué à l’entraînement et en production.

Tokeniser en mots

L’approche la plus simple découpe sur les caractères alphanumériques :

def tokeniser(texte):
    return re.findall(r"\w+", normaliser(texte))

print(tokeniser("Le colis n'est pas arrivé."))
# ['le', 'colis', 'n', 'est', 'pas', 'arrive']

Des bibliothèques comme spaCy gèrent finement les élisions, les nombres ou les dates, et ajoutent la lemmatisation (« arrivées » → « arriver »). Le défaut des tokens-mots : le vocabulaire explose et tout mot absent de l’entraînement (faute de frappe, nom propre, néologisme) devient inconnu.

Les sous-mots et BPE

Les modèles modernes découpent en sous-mots : les mots fréquents restent entiers, les mots rares sont décomposés (« anticonstitutionnellement » → « anti », « constitution », « nellement »). Il n’y a plus de mot inconnu.

L’algorithme BPE (Byte Pair Encoding) apprend ce vocabulaire :

  1. partir de chaque mot découpé en caractères (ou en octets, pour couvrir tout Unicode) ;
  2. compter les paires adjacentes de symboles dans le corpus, pondérées par la fréquence des mots ;
  3. fusionner la paire la plus fréquente en un nouveau symbole ;
  4. recommencer jusqu’à la taille de vocabulaire souhaitée (souvent 32 000 à 200 000 tokens).
from collections import Counter

corpus = {("b", "a", "s"): 5, ("b", "a", "l"): 3, ("v", "a", "s"): 2}
paires = Counter()
for mot, freq in corpus.items():
    for a, b in zip(mot, mot[1:]):
        paires[(a, b)] += freq
print(paires.most_common(1))   # [(('a', 's'), 7)] -> on fusionne "a" + "s"

WordPiece (BERT) et Unigram (SentencePiece) suivent la même idée avec d’autres critères de fusion.

Les tokenizers des modèles

Avec Hugging Face, chaque modèle fournit son tokenizer :

from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("camembert-base")
enc = tok("Le colis n'est pas arrivé.")
print(enc["input_ids"])                                   # identifiants
print(tok.convert_ids_to_tokens(enc["input_ids"]))        # morceaux de mots

Le nombre de tokens compte : il détermine la limite de contexte d’un modèle et le coût des API de LLM, facturées au token. Le français produit en général un peu plus de tokens que l’anglais pour un même contenu.

À retenir

Normalisation cohérente, tokenisation adaptée au modèle, et conscience du nombre de tokens : ces bases conditionnent tout le reste, du TF-IDF aux LLM.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Python dans le navigateur2 indices

    Normaliser et tokeniser

    Écrivez normaliser(texte) (minuscules, suppression des accents via unicodedata, espaces multiples réduits et bords supprimés) et tokeniser(texte) qui renvoie la liste des mots (re.findall(r"\w+", ...)) du texte normalisé.

    import re
    import unicodedata
    
    def normaliser(texte):
        # TODO
        pass
    
    def tokeniser(texte):
        # TODO
        pass
  2. CodeDifficulté 3Python dans le navigateur2 indices

    Une étape de BPE

    Le corpus est un dictionnaire {tuple_de_symboles: fréquence}. Écrivez compter_paires(corpus) qui renvoie un Counter des paires adjacentes pondérées par la fréquence, et fusionner(paire, corpus) qui renvoie un nouveau corpus où chaque occurrence adjacente de la paire est remplacée par la concaténation des deux symboles.

    from collections import Counter
    
    def compter_paires(corpus):
        # TODO
        pass
    
    def fusionner(paire, corpus):
        # TODO
        pass
  3. QCMDifficulté 11 indice

    Pourquoi des sous-mots ?

    Quel est le principal avantage d’une tokenisation en sous-mots (BPE) par rapport à une tokenisation en mots ?

    • Elle supprime la ponctuation
    • Elle évite les mots inconnus en décomposant les mots rares en morceaux connus, avec un vocabulaire de taille maîtrisée
    • Elle produit toujours moins de tokens
    • Elle traduit automatiquement le texte

Quiz de fin de leçon

  1. Pourquoi éviter de retirer les accents avant un modèle Transformer pré-entraîné ?

    • Parce que c'est trop lent
    • Parce que son tokenizer et ses poids ont été appris sur du texte brut : modifier le texte dégrade les représentations
    • Parce que les accents sont des tokens spéciaux
    • Parce que cela augmente le coût
  2. Dans BPE, quelle paire fusionne-t-on à chaque étape ?

    • La première paire du corpus
    • La paire adjacente la plus fréquente
    • La paire la plus rare
    • Une paire tirée au hasard
  3. Pourquoi compter les tokens d’un prompt avant d’appeler un LLM ?

    • Pour corriger l'orthographe
    • Parce que le coût et la limite de contexte s'expriment en tokens
    • Parce que le modèle ne lit que les 100 premiers mots
    • Pour choisir la température

La suite du cours

  1. Sac de mots, TF-IDF et classification de textes18 min
  2. Embeddings et recherche sémantique18 min
  3. Transformers, attention et grands modèles de langage20 min
  4. RAG : génération augmentée par la recherche20 min
  5. Adapter un modèle : fine-tuning léger (LoRA) et évaluation20 min

Traitement du langage (NLP) et LLM · Avancé · 4 h 21