Dans la série d’articles qui suit nous allons retracer une partie de l’histoire de NLP (Natural Language Processing) au travers de certains des frameworks de modélisation ayant marqué des avancées notables dans le domaine.
Depuis les premières réflexions autour des agents conversationnels dans les années 50 avec la formulation du test de Turing jusqu’aux LLM (Large Language Model) que l’on utilise actuellement, le NLP a connu de nombreux paradigmes de conceptualisation. L’objectif de cette série d’articles est de présenter certains de ces paradigmes et de constituer le cheminement intellectuel permettant d’appréhender certains concepts avancés.
Le premier article de cette série va porter sur une méthode statistique élémentaire de modélisation du langage : les n-grams.
Contexte, histoire et définition
Avant de rentrer dans le vif du sujet il est important de définir ce que l’on entend par modélisation du langage. La modélisation du langue est une discipline qui consiste à construire des modèles de traitement automatique du langage naturel. Ces modèles tentent de capturer la richesse, la structure, et les nuances du langage pour accomplir diverses tâches, telles que la traduction automatique, la reconnaissance vocale, la correction automatique, la génération de texte, et bien d’autres.
La méthode de modélisation du langage par n-grammes est l’une des premières tentatives de modélisation statistique et auto-régressive du langage. Son principe est assez simple : à partir d’un contexte donné (un début de phrase par exemple), le n-gram vise à déterminer la probabilité d’apparition du token suivant. Un token est l’unité de découpage du langage, un token peut être aussi petit qu’une lettre et aussi grand qu’un groupe de mots en passant par toutes les tailles intermédiaires.
Pour illustrer, si l’on considère des mots de la langue française, issus d’un vocabulaire de plusieurs milliers de mots, l’objectif est de prédire la probabilité d’apparition de chaque mot du vocabulaire suivant dans un contexte donné tel que « Le fermier cuisine une ». Dans cet exemple, les mots probables pourraient être, par exemple, « omelette » ou « poule ». Cette approche est appelée modélisation 5-gramme du langage, car elle cherche à prédire le cinquième mot à partir des quatre premiers.
L’exemple précédent illustre l’aspect statistique de la modélisation : le n-grams construit une estimation de la probabilité conditionnelle de chaque élément du vocabulaire en fonction d’un contexte. Il convient également de mentionner que les probabilités d’apparition de chaque n-gramme sont généralement déduites à partir d’un corpus de texte (ce processus sera expliqué dans la section suivante). En ce qui concerne l’aspect auto-régressif du modèle, cela signifie que le modèle peut générer du texte en se basant sur ses propres prédictions. Reprenons l’exemple du 5-gramme précédent :
- 0) Initialisation: le contexte initial est « Le fermier cuisine une »
- 1) Inférence du modèle: à partir du contexte le modèle renvoie le mot suivant, ici « omelette »
- 2) Mise à jour du contexte: On supprime le premier mot du contexte précédent et on ajoute au nouveau contexte le mot renvoyé par le modèle, le contexte devient ainsi « fermier cuisine une omelette »
- 3) Inférence du modèle: à partir du nouveau contexte le modèle renvoie le mot suivant, par exemple « aux »
- On répète 2) et 3) jusqu’à ce que l’on ai généré la quantité de texte souhaitée
L’idée des n-grams a émergé dans les années 1940 dans les travaux de Claude Shannon dans « A mathematical Theory of Communication » (1948) sur la théorie de l’information. Ces modèles ont connu une grande popularité dans les années 90 et au début des années 2000, notamment avec l’amélioration des capacités de calcul des processeurs. Les n-grams ont été largement utilisés dans des domaines tels que la reconnaissance de la parole ou encore pour de la classification de texte (filtres anti-spam par exemple).
De nos jours, la modélisation n-grams a perdu de sa popularité, principalement en raison de l’émergence de techniques offrant des capacités de représentation plus puissantes. Cependant, ces modèles sont toujours utilisés à des fins pédagogiques en raison de leur simplicité de compréhension, d’implémentation et d’entraînement.
Zoom le bigram au niveau de la lettre
Pour appréhender les n-grams, concentrons-nous sur un exemple simple que nous aborderons avec une approche élémentaire:
- Objectif : On cherche à construire un modèle bigram au niveau de la lettre à partir d’un texte.
- Exemple de génération du modèle : Prenons la phrase ‘je développe un volca’ le modèle va générer le caractère suivant uniquement à partir du dernier caractère ‘a’. On espère ici que ce caractère générer sera ‘n’.
- Limite du modèle : Le manque de contexte risque d’affecter la qualité de la génération du modèle.
- Vocabulaire : le vocabulaire est ici l’ensemble des 26 lettres de l’alphabet, les 10 chiffres, les espaces et les apostrophes. La taille du vocabulaire est donc 38.
- Dataset : pour cet exemple on utilise le premier tome de Dune en format txt.
Il faut garder à l’esprit que ce modèle est un exemple pour des raisons pédagogiques, en général si l’on voulait utiliser un tel modèle, ce serait un n-grams avec n > 2 et au niveau du mot et non du caractère.
Construction du modèle
La construction du modèle bigram se fait de la manière suivante :
- Initialisation de la matrice de comptage des bigrams : on initialise une table de taille (38×38) avec des zéros. On créé une correspondance de chaque caractère du vocabulaire avec un numéro allant de 0 à 37. Chaque ligne correspond à un premier caractère possible tandis que chaque colonne correspond à un deuxième caractère possible. Chaque case du tableau comptera le nombre d’occurrences du bigram ayant pour premier caractère le caractère correspondant au numéro de la ligne et ayant pour deuxième caractère le caractère correspondant au numéro de colonne.
- Comptage des bigrams : on parcourt le texte caractère par caractère. Pour chaque caractère on regarde le caractère suivant et on incrémente de 1 la case de la matrice de comptage correspondant au bi-gram.
- Conversion en probabilités : pour finir on normalise chaque ligne de la matrice afin que chaque ligne représente une distribution de probabilités.
Après construction on peut visualiser le modèle bigram sous sa forme matricielle :

On peut tirer de nombreuses informations à l’œil nu d’une telle matrice. Par exemple, la probabilité que la lettre « u » suive la lettre « q » est de 0.915 ou encore la probabilité que la lettre « e » suive la lettre « v » est de 0.745.
Une des forces du modèle bigram d’un point de vue pédagogique est le fait que l’on puisse le représenter sous forme matricielle de manière exhaustive lorsque le vocabulaire est suffisamment petit. Par contre le manque de contexte limite beaucoup les capacités du modèle ; si l’on reprend l’exemple de tout à l’heure « je développe un volca », la probabilité que la lettre « n » suive la lettre « a » n’est que de 0.018. De plus on sent bien que le modèle manque cruellement de contexte.
Génération auto régressive de texte utilisant un bigram
Afin de se faire une idée de la puissance de représentation possible avec ce genre de modèle nous allons l’utiliser pour générer du texte. La marche à suivre est :
- Initialisation : on fixe un caractère initial, ici on choisit une espace mais l’on pourrait choisir n’importe quel caractère.
- Tirage du caractère suivant : on sélectionne la ligne associée au caractère courant. Cette ligne constitue une distribution de probabilité pour le tirage du caractère suivant. On effectue donc un tirage d’un seul sample de la distribution multinomiale du caractère suivant ce qui nous donne l’indice du caractère suivant.
- Récurrence : le caractère tiré devient le caractère courant. On répète le processus jusqu’à obtention de la quantité de texte souhaitée.
Voici un exemple résultat:

Comme on pouvait s’y attendre le résultat ‘est plutôt décevant. Néanmoins si l’on compare avec une suite de caractères tirés complètement au hasard :

La chaîne de caractères générée par notre modèle est bien plus vraisemblable ce qui signifie que le modèle a néanmoins appris des informations significatives bien que modestes à ce stade.
A titre de comparaison avec les génération précédentes, voici le résultat obtenu avec un bigram au niveau du mot entraîné sur le même texte:

Cette génération reste de faible qualité bien que les grains générés soient maintenant de vrais mots. Dans cet exemple, le vocabulaire a environ 12 000 éléments pour un texte de 200 000 mots. La matrice de probabilité obtenue suite au comptage des bigrams est donc extrêmement creuse. Cela a pour effet de rendre la distribution d’un mot en fonction du précédent assez proche d’une distribution uniforme et donc le résultat devient assez proche du hasard. Le tirage des mots au hasard est d’ailleurs difficilement discernable du tirage utilisant le modèle bigram au niveau du mot.
Pour illustrer le point précédent, voici un graphe montrant les divers distributions de probabilités des tokens en fonction du token précédent pour chacun des modèles bigram construit :


Les pics les plus forts ont des valeurs maximums de 0.06 pour le modèle bigram au niveau du mot (à gauche) ce qui est plutôt faible, on est très proche de distributions uniformes. Au contraire, le modèle bigram au niveau du caractère (à droite) présente des distributions plus franches avec des pics plus marqués.
On sent qu’il y a un équilibre à trouver entre taille du vocabulaire, taille du corpus de texte utilisé et pertinence des distributions obtenues.
Évaluation du modèle
Lorsqu’on souhaite vérifier l’efficacité de notre modèle n-grams, c’est-à-dire sa capacité à prédire le texte de manière précise, on dit qu’on évalue le modèle.
Pour apprendre à notre modèle comment les tokens s’enchaînent, on lui donne à lire une grande partie du texte, disons 80%. La partie restante, les 20%, sert à tester si notre modèle a bien appris.
Pour évaluer notre modèle, nous procédons comme suit : pour chaque token du texte dans notre partie de test, nous regardons quelle est le token qui vient ensuite. Si notre modèle fonctionne correctement, il devrait être capable de prédire ce token suivant avec précision.
Pour mesurer la précision de ces prédictions, nous transformons cette attente en une formule mathématique simple, faisant de la prédiction une question de probabilité. Notre vocabulaire contient 38 tokens, on créé donc un vecteur de 38 emplacements. On place un ‘1’ à la position qui correspond au token suivant dans le texte, et des ‘0’ partout ailleurs. Cela signifie que nous sommes à 100% sûrs de quelle token vient après.
Le modèle fait une prédiction semblable pour déterminer le token suivant, mais au lieu d’avoir un seul ‘1’ et le reste des ‘0’s, il attribuera des probabilités différentes à chaque élément du vocabulaire selon ce qu’il a appris pendant la phase d’entraînement.
Il nous faut ensuite une méthode pour comparer la prédiction de notre modèle avec la réalité (le ‘1’ que nous avons placé). Pour cela, nous utilisons une mesure appelée « cross entropie« , qui calcule à quel point nos prédictions se rapprochent des résultats réels. En d’autres termes, elle nous aide à comprendre si notre modèle est un bon devin ou non en moyennant cette mesure sur l’ensemble des caractères prédits.
Plus le score de cross entropie est bas, mieux c’est, car cela signifie que les prédictions de notre modèle sont très proches de la réalité.
Limites
Dans notre exploration des n-grams, il est important de noter certaines limites évidentes. Ces limites peuvent affecter la manière dont nous comprenons et utilisons les n-grams dans différents contextes.
Tout d’abord, considérons la question du contexte limité. Les n-grams capturent des séquences d’éléments d’un vocabulaire d’une longueur spécifique, ce qui signifie que plus le contexte est large (c’est-à-dire plus le nombre d’éléments pris en compte est grand), plus nous avons besoin d’un ensemble de données d’entraînement considérable et varié pour obtenir une représentation précise. Cela peut entraîner une augmentation exponentielle de l’espace de recherche nécessaire pour construire ces modèles, ce qui peut être très exigeant en termes de ressources computationnelles et de temps.
Ensuite, il y a la rareté des tokens. Certains éléments ou combinaisons d’éléments peuvent être très rares dans un ensemble de données, ce qui signifie qu’ils ne sont pas bien représentés dans les modèles de n-grams. Cela peut conduire à des lacunes dans notre compréhension ou notre prédiction des données, en particulier lorsque ces tokens rares sont significatifs dans un certain contexte.
De plus, comme entrevu dans la comparaison entre bigram au niveau du caractère et bigram au niveau du mot, la combinatoire des n-grams à considérer devient exponentiellement grande avec la taille du vocabulaire et le n choisit. Il faut alors un corpus de texte d’entraînement d’autant plus large et varié que ces deux variables augmentent ce qui n’est possible que jusqu’à un certain point.
Enfin, les n-grams offrent une représentation non sémantique des données. Cela signifie que chaque n-gram est traité de la même manière, sans tenir compte de la signification ou de la similarité sémantique entre les différents mots ou séquences de mots. Par exemple, un n-gram peut inclure des éléments qui sont totalement différents sur le plan sémantique mais qui se produisent fréquemment ensemble dans un texte. Cette limitation peut rendre les modèles de n-grams mécaniquement restreints dans leur capacité à saisir la richesse et la subtilité du langage naturel.
Conclusion
On a entrevu dans cet article la construction de modèles n-grams pour de la génération auto régressive de texte. Cette méthode très simple et facile à implémenter présente néanmoins de nombreuses limites auxquelles on se heurte très rapidement lors d’expérimentations. Notons aussi que ces modèles ont très peu d’usages pratiques en raison de leurs divers limitations. En revanche, du point de vue de la modélisation mathématique, les n-grams s’apparentent de prêt aux modèles de chaîne de Markov qui eux sont encore utilisés actuellement notamment en traitement du signal.
On a vu qu’un des points les plus bloquant est la représentation non sémantique des mots/caractères. On verra dans l’article suivant comment construire une représentation sémantique du langage. C’est ce genre de représentations qui nous permettront dans les articles suivant de créer des modèles aux capacités de généralisation plus poussées.
sources :

