Le traitement automatique du langage (TAL, ou NLP en anglais) vise un objectif en apparence simple — analyser un texte écrit par ordinateur — mais qui recouvre des tâches d’une diversité surprenante : annotation, analyse syntaxique, classification de textes, réécriture, agents conversationnels, reconnaissance optique de caractères, reconnaissance de la parole.
Ce qui rend le langage difficile à traiter
La langue résiste par nature à la formalisation. L’ambiguïté et la vivacité de la langue — homonymes, homographes, homophones — compliquent toute interprétation automatique. L’échantillonnage bute sur les mots inconnus, les néologismes, les noms propres. La grammaire elle-même reste ambiguë, et le vocabulaire ne cesse de s’enrichir. Ces irrégularités posent une question de fond, à laquelle toute méthode de traitement du langage doit répondre d’une manière ou d’une autre : comment représenter un mot pour qu’un ordinateur puisse le manipuler ?
Représenter un mot : du one-hot au word embedding
La réponse la plus naïve, le one-hot encoding, représente chaque mot par un vecteur creux dont une seule coordonnée vaut 1. Cette approche souffre d’un défaut structurel : elle ne capture aucune relation sémantique entre les mots — « chat » et « chien » sont, dans cet espace, aussi éloignés que « chat » et « voiture ».
Le word embedding répond à ce défaut en représentant chaque mot par un vecteur dense, appris statistiquement à partir de la co-occurrence des mots au sein des phrases d’un corpus. L’avantage principal de cette représentation réside dans une forte corrélation entre la similarité des sens (les sèmes) et la similarité géométrique des embeddings eux-mêmes — deux mots employés dans des contextes similaires se retrouvent proches dans l’espace vectoriel.
Deux approches historiques ont introduit ce paradigme fondé sur l’apprentissage automatique : Word2Vec (Google, 2013), dont la variante Continuous Bag-of-Words (CBOW) prédit un mot cible à partir de son contexte, et FastText (Facebook, 2016), qui affine cette idée. GloVe (Global Vector for Word Representation) complète ce paysage par une approche fondée sur les statistiques globales de co-occurrence à l’échelle du corpus entier.
Distance cosinus
La proximité sémantique entre deux mots et , une fois représentés sous forme d’embeddings, se mesure généralement par la distance cosinus entre leurs vecteurs — un angle faible traduisant une forte similarité sémantique.
Séquences et la nécessité d’une mémoire
Un texte n’est pas un sac de mots indépendants : c’est une séquence, une suite d’observations où l’ordre porte lui-même du sens. Traiter correctement une séquence exige donc, d’une manière ou d’une autre, une forme de mémoire — ce qui a longtemps orienté le domaine vers les réseaux récurrents (RNN), puis leurs variantes à mémoire longue (LSTM), avant qu’un changement de paradigme radical n’intervienne avec les Transformers.
Les Transformers
Introduits en 2017, les Transformers reposent sur un mécanisme d’attention, capable de traiter efficacement les dépendances longues au sein d’une séquence — là où un RNN peinait à conserver l’information sur de longues distances. Leur avantage décisif tient à leur traitement parallèle des données, contrairement aux RNN et LSTM qui traitent nécessairement une séquence pas à pas.
Leur architecture générale s’organise en blocs d’encodeurs et de décodeurs, articulés autour d’un mécanisme d’attention multi-tête : plutôt que de calculer une seule pondération d’attention entre les éléments d’une séquence, le modèle en calcule plusieurs en parallèle, chacune capturant un type de relation différent entre les tokens.
Application pratique : classifier des requêtes SQL
Un exercice pratique illustre la progression naturelle d’une approche fréquentiste vers une approche connexionniste, sur une tâche de classification de requêtes SQL — typiquement, distinguer une requête légitime d’une tentative d’injection.
L’approche fréquentiste
On s’appuie d’abord sur une représentation par comptage de mots. CountVectorizer (scikit-learn) transforme une collection de textes en une matrice numérique de tokens, préparant les données à leur classification :
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
matrix = vectorizer.fit_transform(data.text)Chaque ligne de la matrice résultante représente un texte individuel du jeu de données. vectorizer.get_feature_names_out() retourne les mots du corpus, triés selon leur position dans la matrice creuse, tandis que vectorizer.vocabulary_ fournit non pas leur fréquence mais leur index au sein du corpus. Sur cette représentation, un modèle Naive Bayes ou une régression logistique suffisent souvent à obtenir un premier résultat exploitable.
L’approche connexionniste
Vectoriser un texte pour un réseau de neurones admet plusieurs granularités : segmenter en mots (chacun représenté par un vecteur), segmenter en caractères, ou extraire des n-grammes.
Définition
Un n-gramme est une sous-séquence de éléments construite à partir d’une séquence donnée. Si l’ordre importe peu, on s’intéresse plutôt à des fréquences de n-grammes — une approche statistique, à l’instar des méthodes TF-IDF.
Le nettoyage du texte reste une étape presque toujours nécessaire : retrait des mots vides (stop words — des termes si communs qu’il est inutile de les indexer), de la ponctuation, et application d’un stemming qui retire les suffixes flexionnels (-ing, -ly).
Une fois le texte nettoyé, deux voies s’ouvrent pour l’encodage des tokens : le one-hot encoding, dont on a vu qu’il souffre d’un problème de sparsité, ou le plongement de tokens (word embedding), qui reprend la logique déjà décrite plus haut :
from tensorflow.keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(
num_words=10000,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
char_level=False, # si True, chaque caractère devient un token
)Après entraînement du tokenizer sur le corpus, on constitue des ensembles d’entraînement, de validation et de test sous forme de séquences, avant de les injecter dans un modèle simple :
model = Sequential()
model.add(Embedding(10000, 8, input_length=maxlen))
model.add(Flatten())
model.add(Dense(10, activation='relu'))
model.add(Dense(1, activation='sigmoid'))Pour des tâches plus exigeantes, on peut réutiliser des embeddings pré-entraînés (GloVe, FastText, Word2Vec) plutôt que d’apprendre une représentation dès le départ, ou passer directement à des architectures récurrentes ou à base de Transformers (BERT) une fois la simple couche d’embedding jugée insuffisante.