Tokenisation BPE: un vocabulaire construit par fréquences
Pourquoi la tokenisation avec Byte Pair Encoding (BPE)?
Le
Byte Pair Encoding (BPE) est une méthode de tokenisation qui a été introduite pour résoudre un problème fondamental du NLP, il s'agit de la gestion des mots rares ou inconnus.
Dans les approches classiques, chaque mot est une unité, ce qui entraîne un vocabulaire immense et une incapacité à traiter les néologismes ou les fautes d’orthographe. BPE contourne cela en décomposant les mots en sous-unités fréquentes. Concrètement, on commence avec des caractères individuels, puis on fusionne les paires les plus fréquentes pour former progressivement un vocabulaire de sous-mots. Ainsi, un mot rare peut être représenté comme une combinaison de sous-unités connues, ce qui réduit la taille du vocabulaire et améliore la couverture linguistique.
Même si des techniques comme le stemming ou la lemmatisation permettent de normaliser le texte, elles n’entraînent pas une réduction significative du vocabulaire. En effet, chaque mot reste représenté par une unité distincte, et le nombre total de tokens demeure élevé. C’est précisément pour répondre à cette limite que des méthodes plus avancées, comme la tokenisation en sous-mots (BPE, WordPiece) ont été développées
La raison d’être de BPE est donc double:
- Réduire le vocabulaire en évitant d’avoir des millions de mots distincts.
- Gérer les mots rares et inconnus en les décomposant en morceaux plus fréquents.
Par exemple, le mot
unhappiness peut être découpé en
un +
happiness, et si
happiness est encore trop rare, il peut être décomposé en
hap +
piness. Cela permet aux modèles de comprendre et de traiter des mots qu’ils n’ont jamais vus auparavant, tout en conservant une granularité linguistique utile.
Le BPE est à l’origine un algorithme de compression de données. Il a été conçu pour réduire la taille des fichiers en remplaçant les paires de caractères les plus fréquentes par des symboles uniques. En NLP, on a détourné ce principe: au lieu de compresser un texte, on l’utilise pour construire un vocabulaire de sous-unités.
Le Byte Pair Encoding (BPE) est aujourd’hui une technique de tokenisation incontournable, utilisée dans des modèles modernes de NLP comme GPT (Generative Pre-trained Transformer) et d’autres architectures dérivées.
Principe de fonctionnement de l’algorithme BPE
Le mode de fonctionnement de l’algorithme BPE repose sur une idée simple: fusionner progressivement les paires de symboles les plus fréquentes pour construire un vocabulaire de sous-unités.
On commence avec un texte découpé en caractères individuels. Ensuite, on compte toutes les paires de caractères adjacents et on remplace la paire la plus fréquente par un nouveau symbole. Ce processus est répété jusqu’à atteindre la taille de vocabulaire souhaitée.
Prenons le mot
lower par exemple.
- Étape 1: on le représente sous forme de caractères individuels l o w e r.
- Étape 2: si la paire la plus fréquente est lo, on la fusionne → lo w e r
- Étape 3: si ensuite er est fréquente, on la fusionne → lo w er.
- Étape 4: si low apparaît souvent, on obtient → low er.
Ainsi, au lieu de traiter
lower comme un mot entier, BPE le décompose en sous-unités fréquentes (
low et
er), ce qui permet au modèle de gérer plus facilement les mots rares ou nouveaux.
Il est important de comprendre que les tokens générés par l’algorithme BPE ne sont pas fixes et peuvent varier d’un texte à un autre pour le même mot. En effet, le modèle BPE est entraîné sur un corpus spécifique, et ce sont les fréquences des paires de caractères dans ce corpus qui déterminent quelles fusions sont réalisées.
Mise en pratique de la tokenisation BPE
Entraîner un modèle de tokenisation BPE avec SentencePiece
Nous allons entraîner un modèle de tokenisation en sous-mots avec
SentencePiece sur un corpus existant.
SentencePiece est une bibliothèque qui implémente plusieurs méthodes de tokenisation, dont BPE. Elle a été développée par Google et permet de réaliser une tokenisation en sous-mots de manière totalement automatique et indépendante de la langue.
Je propose le code suivant:
import sentencepiece as spm
# Entrainement du modèle SentencePiece
spm.SentencePieceTrainer.Train(
'--input=data.txt --model_prefix=m --vocab_size=300'
)
# Chargement du modèle
sp = spm.SentencePieceProcessor(model_file='m.model')
# Tokenisation à l'aide du modèle entrainé
tokens = sp.encode('This is an example sentence.', out_type=str)
print(tokens)
On commence par importer la bibliothèque SentencePiece dans notre script Python:
import sentencepiece as spm
Si la bibliothèque SentencePiece n’est pas encore installée dans notre environnement Python, on peut l’installer avec la commande suivante:
!pip install sentencepiece
Ensuite, on entraine le modèle:
spm.SentencePieceTrainer.Train(
'--input=data.txt --model_prefix=m --vocab_size=300'
)
Expliquons les options passées au modèle:
- --input=data.txt: indique le fichier texte qui servira de corpus d’entraînement. C’est à partir de ce contenu que SentencePiece va apprendre à découper les mots en sous-unités.
- --model_prefix=m: définit le préfixe des fichiers générés. Après l’entraînement, on obtiendra par exemple m.model (le modèle entraîné) et m.vocab (la liste des tokens).
- --vocab_size=300: fixe la taille du vocabulaire à 300 tokens. Cela signifie que SentencePiece va construire un vocabulaire de 300 sous-unités optimales à partir du corpus.
Un vocabulaire de grande taille (vocab_size élevé) permet de réduire la fragmentation des mots et d’améliorer la précision de la représentation, car davantage de mots fréquents ou spécifiques peuvent être intégrés directement comme tokens uniques plutôt que découpés en sous-unités.
Après, on crée un objet SentencePieceProcessor qui charge le modèle de tokenisation entraîné (m.model):
sp = spm.SentencePieceProcessor(model_file='m.model')
Cet objet
sp sera ensuite utilisé pour encoder du texte en tokens ou décoder des tokens en texte.
En fin, on utilise le modèle SentencePiece chargé pour encoder la phrase en une séquence de tokens;
tokens = sp.encode('This is an example sentence.', out_type=str)
Le paramètre
out_type=str précise que les tokens doivent être renvoyés sous forme de chaînes de caractères (sous-mots) et non sous forme d’indices numériques.
L'exéuction du code complet produit ce résultat:
['▁Th', 'is', '▁is', '▁a', 'n', '▁e', 'x', 'a', 'm', 'p', 'le', '▁s', 'ent', 'en', 'ce', '.']
Le symbole spécial ▁ inséré par SentencePiece marque soit la présence d’un espace avant le token, soit le début de la phrase, afin de préserver l’information de séparation des mots lors de l’encodage et du décodage.
Si vous exécutez ce même code, vous obtiendrez probablement un résultat différent, car la segmentation en tokens dépend directement du corpus utilisé pour l’entraînement. En effet, chaque corpus construit un vocabulaire spécifique qui influence la manière dont les phrases sont découpées.