
La carte du sens : comment les modèles d’intégration « comprennent » le langage humain
vous travaillez dans le développement de l’intelligence artificielle, si vous étudiez ou envisagez de travailler avec cette technologie, vous êtes certainement tombé sur intégration de modèles tout au long de votre voyage.
À la base, un modèle d’intégration est un réseau de neurones entraîné à mapper des mots ou des phrases similaires dans un espace vectoriel continu, dans le but de se rapprocher mathématiquement des objets contextuellement ou conceptuellement similaires.
En termes plus simples, imaginez une bibliothèque où les livres ne sont pas classés uniquement par auteur et par titre, mais selon de nombreuses autres dimensions, telles que ambiance, sujet, humeur, style d’écritureetc.
Une autre bonne analogie est celle d’une carte elle-même. Pensez à une carte et à deux villes que vous ne connaissez pas. Disons que vous n’êtes pas très bon en géographie et que vous ne savez pas où se trouvent Tokyo et New York sur la carte. Si je vous dis que nous devrions prendre le petit-déjeuner à New York et le déjeuner à Tokyo, vous pourriez dire : « Faisons-le ».
Cependant, une fois que je vous ai donné les coordonnées pour que vous puissiez vérifier les villes sur la carte, vous verrez qu’elles sont très éloignées les unes des autres. C’est comme donner les plongements à un modèle : ce sont les coordonnées !
Construire la carte
Avant même que vous posiez une question, le modèle d’intégration a été formé. Il a lu des millions de phrases et noté des modèles. Par exemple, il constate que « chat » et « chaton » apparaissent souvent dans les mêmes types de phrases, alors que « chat » et « réfrigérateur » le font rarement.
Avec ces modèles, le modèle attribue à chaque mot un ensemble de coordonnées sur un espace mathématique, comme une carte invisible.
- Les concepts similaires (comme « chat » et « chaton ») sont placés les uns à côté des autres sur la carte.
- Les concepts quelque peu liés (comme « chat » et « chien ») sont placés les uns à côté des autres, mais pas les uns sur les autres.
- Des concepts totalement indépendants (comme « chat » et « physique quantique ») sont placés dans des coins complètement différents de la carte, comme New York et Tokyo.
L’empreinte digitale
Bon. Nous savons maintenant comment la carte a été créée. Qu’est-ce qui vient ensuite ?
Nous allons maintenant travailler avec ce modèle d’intégration formé. Une fois que nous donnons au modèle une phrase comme « Le chaton pelucheux dort » :
- Il ne regarde pas les lettres. Au lieu de cela, il visite ces coordonnées sur sa carte pour chaque mot.
- Il calcule le point central (la moyenne) de tous ces emplacements. Ce point central unique devient « l’empreinte digitale » de la phrase entière.
- Il place une épingle sur la carte à l’endroit où se trouve l’empreinte digitale de votre question.
- Il regarde autour de lui en cercle pour voir quelles autres empreintes digitales se trouvent à proximité.
Tous les documents qui « vivent » à proximité de votre question sur cette carte sont considérés comme une correspondance, car ils partagent la même « ambiance » ou le même sujet, même s’ils ne partagent pas exactement les mêmes mots.

C’est comme chercher un livre non pas en recherchant un mot-clé spécifique, mais en pointant un endroit sur une carte qui dit « ce sont tous des livres sur les chatons » et en laissant le modèle aller chercher tout ce qui se trouve dans ce quartier.
Étapes d’intégration de modèles
Voyons ensuite comment fonctionne un modèle d’intégration étape par étape après avoir reçu une demande.
- L’ordinateur prend un texte.
- Le décompose en jetons, qui sont le plus petit morceau d’une phrase ayant un sens. Habituellement, c’est un mot ou une partie du mot.
- Morceau: Le texte saisi est divisé en morceaux gérables (souvent autour de 512 jetons), afin de ne pas être submergé par trop d’informations à la fois.
- Intégration: Il transforme chaque extrait de code en une longue liste de nombres (un vecteur) qui agit comme un unique empreinte digitale représentant le sens de ce texte.
- Recherche de vecteurs: Lorsque vous posez une question, le modèle transforme également votre question en « empreinte digitale » et calcule rapidement quels extraits stockés ont les nombres les plus mathématiquesment similaires.
- Le modèle renvoie les vecteurs les plus similaires, associés aux morceaux de texte.
- Génération: Si vous effectuez une génération de récupération augmentée (RAG), le modèle remet ces quelques extraits « gagnants » à une IA (comme un LLM) qui les lit et écrit une réponse à consonance naturelle basée uniquement sur ces informations spécifiques.
Codage
Super. Nous avons beaucoup parlé. Maintenant, essayons de coder un peu et de rendre ces concepts plus pratiques.
Nous commencerons par une simple intégration de BERT (Bidirectionnel Encoder Representations from Transformers). Il a été créé par Google et utilise le Architecture du transformateur et son mécanisme d’attention. Le vecteur d’un mot change en fonction des mots qui l’entourent.
# Imports
from transformers import BertTokenizer
# Load pre-trained BERT tokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
# Sample text for tokenization
text = "Embedding models are so cool!"
# Step 1: Tokenize the text
tokens = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
# View
tokens
{'input_ids': tensor([[ 101, 7861, 8270, 4667, 4275, 2024, 2061, 4658, 999, 102]]),
'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}
Remarquez comment chaque mot a été transformé en identifiant. Comme nous n’avons que 5 mots, certains d’entre eux auraient pu être divisés en deux sous-mots.
- L’identifiant 101 est associé au jeton [CLS]. On pense que le vecteur de ce jeton capture la signification ou les informations globales de la phrase entière ou de la séquence de phrases. C’est comme un tampon qui indique aux LLM la signification de ce morceau. [2]
- L’identifiant 102 est associé au jeton [SEP] à phrases séparées. [2]
Ensuite, appliquons le modèle d’intégration aux données.
Intégration
Voici un autre extrait simple où nous récupérons du texte et l’encodons avec le modèle d’intégration polyvalent et polyvalent. all-MiniLM-L6-v2.
from qdrant_client import QdrantClient, models
from sentence_transformers import SentenceTransformer
# 1. Load embedding model
model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu')
# 2. Initialize Qdrant client
client = QdrantClient(":memory:")
# 3. Create embeddings
docs = ["refund policy", "pricing details", "account cancellation"]
vectors = model.encode(docs).tolist()
# 4. Store Vectors: Create a collection (DB)
client.create_collection(
collection_name="my_collection",
vectors_config = models.VectorParams(size=384,
distance= models.Distance.COSINE)
)
# Upload embedded docs (vectors)
client.upload_collection(collection_name="my_collection",
vectors= vectors,
payload= [{"source": docs[i]} for i in range(len(docs))])
# 5. Search
query_vector = model.encode("How do I cancel my subscription")
# Result
result = client.query_points(collection_name= 'my_collection',
query= query_vector,
limit=2,
with_payload=True)
print("\n\n ======= RESULTS =========")
result.points
Les résultats sont comme prévu. Il pointe vers le annulation de compte sujet!
======= RESULTS =========
[ScoredPoint(id='b9f4aa86-4817-4f85-b26f-0149306f24eb', version=0, score=0.6616353073200185, payload={'source': 'account cancellation'}, vector=None, shard_key=None, order_value=None),
ScoredPoint(id='190eaac1-b890-427b-bb4d-17d46eaffb25', version=0, score=0.2760082702501182, payload={'source': 'refund policy'}, vector=None, shard_key=None, order_value=None)]
Que vient-il de se passer ?
- Nous avons importé un modèle d’intégration pré-entraîné
- Instanciation d’une base de données vectorielle de notre choix : Qdrant [3].
- J’ai intégré le texte et l’ai téléchargé dans la base de données vectorielle dans une nouvelle collection.
- Nous avons soumis une requête.
- Les résultats sont les documents ayant l’« empreinte » mathématique ou la signification la plus proche des intégrations de la requête.
C’est vraiment sympa.
Pour terminer cet article, je me demande si nous pouvons essayer d’affiner un modèle d’intégration. Essayons.
Affiner un modèle d’intégration
Le réglage fin d’un modèle d’intégration est différent du réglage fin d’un LLM. Au lieu d’apprendre au modèle à « parler », vous lui apprenez à réorganiser sa carte interne pour que les concepts spécifiques à votre domaine sont éloignés ou rapprochés.
Le moyen le plus courant et le plus efficace d’y parvenir consiste à utiliser l’apprentissage contrastif avec une bibliothèque telle que Sentence-Transformers.
Tout d’abord, enseignez au modèle à quoi ressemble la proximité en utilisant trois points de données.
- Ancre: L’article de référence (par exemple, « Brand A Cola Soda »)
- Positif: Un article similaire (par exemple, « Brand B Cola Soda ») que ce modèle devrait rassembler.
- Négatif: Un élément différent (par exemple, « Brand A Cola Soda Zero Sugar ») que le modèle devrait repousser.
Ensuite, nous choisissons une fonction de perte pour indiquer au modèle dans quelle mesure il doit changer en cas d’erreur. Vous pouvez choisir entre :
- Perte de classement multiplenégative: Idéal si vous n’avez que des paires (Anchor, Positive). Il suppose que tous les autres positifs du lot sont des « négatifs » pour l’ancre actuelle.
- Perte de triplet: Idéal si vous avez des ensembles explicites (Anchor, Positive, Negative). Il force la distance entre Anchor-Positive à être plus petite qu’Ancre-Negative d’une marge spécifique.
Il s’agit des résultats de similarité des modèles prêts à l’emploi.
from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
from sentence_transformers import util
# 1. Load a pre-trained base model
model = SentenceTransformer('all-MiniLM-L6-v2')
# 1. Define your test cases
query = "Brand A Cola Soda"
choices = [
"Brand B Cola Soda", # The 'Positive' (Should be closer now)
"Brand A Cola Soda Zero Sugar" # The 'Negative' (Should be further away now)
]
# 2. Encode the text into vectors
query_vec = model.encode(query)
choice_vecs = model.encode(choices)
# 3. Compute Cosine Similarity
# util.cos_sim returns a matrix, so we convert to a list for readability
cos_scores = util.cos_sim(query_vec, choice_vecs)[0].tolist()
print(f"\n\n ======= Results for: {query} ===============")
for i, score in enumerate(cos_scores):
print(f"-> {choices[i]}: {score:.5f}")
======= Results for: Brand A Cola Soda ===============
-> Brand B Cola Soda: 0.86003
-> Brand A Cola Soda Zero Sugar: 0.81907
Et quand on essaie de le peaufiner, en montrant à ce modèle que les Cola Sodas devraient être plus proches que la version Zero Sugar, voilà ce qui se passe.
from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
from sentence_transformers import util
# 1. Load a pre-trained base model
fine_tuned_model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. Define your training data (Anchors, Positives, and Negatives)
train_examples = [
InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand C Cola Zero Sugar"]),
InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand A Cola Zero Sugar"]),
InputExample(texts=["Brand A Cola Soda", "Cola Soda", "Brand B Cola Zero Sugar"])
]
# 3. Create a DataLoader and choose a Loss Function
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
train_loss = losses.TripletLoss(model=fine_tuned_model)
# 4. Tune the model
fine_tuned_model.fit(train_objectives=[(train_dataloader, train_loss)],
optimizer_params={'lr': 9e-5},
epochs=40)
# 1. Define your test cases
query = "Brand A Cola Soda"
choices = [
"Brand B Cola Soda", # The 'Positive' (Should be closer now)
"Brand A Cola Zero Sugar" # The 'Negative' (Should be further away now)
]
# 2. Encode the text into vectors
query_vec = fine_tuned_model.encode(query)
choice_vecs = fine_tuned_model.encode(choices)
# 3. Compute Cosine Similarity
# util.cos_sim returns a matrix, so we convert to a list for readability
cos_scores = util.cos_sim(query_vec, choice_vecs)[0].tolist()
print(f"\n\n ======== Results for: {query} ====================")
for i, score in enumerate(cos_scores):
print(f"-> {choices[i]}: {score:.5f}")
======== Results for: Brand A Cola Soda ====================
-> Brand B Cola Soda: 0.86247
-> Brand A Cola Zero Sugar: 0.75732
Ici, nous n’avons pas obtenu un bien meilleur résultat. Ce modèle est entraîné sur une très grande quantité de données, donc ce réglage fin avec un petit exemple n’a pas suffi pour le faire fonctionner comme prévu.
Mais c’est quand même un excellent apprentissage. Nous avons pu faire en sorte que le modèle se rapproche des deux exemples de Cola Soda, mais cela a également rapproché le Zero Cola Soda.
Alignement et uniformité
Un bon moyen de vérifier comment le modèle a été mis à jour consiste à examiner ces métriques
- Alignement: Imaginez que vous ayez un tas d’articles connexes, comme « Brand A Cola Soda » et « Cola Soda ». L’alignement mesure la proximité de ces éléments liés les uns aux autres dans l’espace d’intégration..
- Un score d’alignement élevé signifie que votre modèle est capable de rapprocher des éléments similaires, ce qui est généralement ce que vous souhaitez pour des tâches telles que la recherche de produits similaires.
- Uniformité: Imaginez maintenant tous vos différents éléments, de la « politique de remboursement » à « l’informatique quantique ». L’uniformité mesure la répartition tous ces éléments se trouvent dans l’espace d’intégration. Vous voulez qu’ils soient répartis uniformément plutôt que tous regroupés dans un seul coin.
- Une bonne uniformité signifie que votre modèle peut distinguer efficacement les différents concepts et évite de tout mapper sur une région petite et dense.
Un bon modèle d’intégration doit être équilibré. Il doit rapprocher les éléments similaires (bon alignement) tout en éloignant simultanément les éléments différents et en garantissant que tout l’espace est bien utilisé (bonne uniformité). Cela permet au modèle de capturer des relations significatives sans sacrifier sa capacité à distinguer des concepts distincts.
En fin de compte, l’équilibre idéal dépend souvent de votre application spécifique. Pour certaines tâches, comme la recherche sémantique, vous pouvez donner la priorité à un alignement très fort, tandis que pour d’autres, comme la détection d’anomalies, un degré plus élevé d’uniformité peut être plus critique.
Il s’agit du code pour le calcul de l’alignement, qui est une moyenne des similitudes cosinusoïdales entre les points d’ancrage et les correspondances positives.
from sentence_transformers import SentenceTransformer, util
import numpy as np
import torch
# --- Alignment Metric for Base Model ---
base_alignment_scores = []
# Assuming 'train_examples' was defined in a previous cell and contains (anchor, positive, negative) triplets
for example in train_examples:
# Encode the anchor and positive texts using the base model
anchor_embedding_base = model.encode(example.texts[0], convert_to_tensor=True)
positive_embedding_base = model.encode(example.texts[1], convert_to_tensor=True)
# Calculate cosine similarity between anchor and positive
score_base = util.cos_sim(anchor_embedding_base, positive_embedding_base).item()
base_alignment_scores.append(score_base)
average_base_alignment = np.mean(base_alignment_scores)
Et voici le code pour le calcul de l’uniformité. Il est calculé en prenant d’abord un ensemble diversifié de plongements, puis en calculant la similarité cosinusoïdale entre chaque paire possible de ces plongements, et enfin en faisant la moyenne de tous ces scores de similarité par paire.
# --- Uniformity Metric for Base Model ---
# Use the same diverse set of texts
uniformity_embeddings_base = model.encode(uniformity_texts, convert_to_tensor=True)
# Calculate all pairwise cosine similarities
pairwise_cos_sim_base = util.cos_sim(uniformity_embeddings_base, uniformity_embeddings_base)
# Extract unique pairwise similarities (excluding self-similarity and duplicates)
upper_triangle_indices_base = torch.triu_indices(pairwise_cos_sim_base.shape[0], pairwise_cos_sim_base.shape[1], offset=1)
uniformity_similarity_scores_base = pairwise_cos_sim_base[upper_triangle_indices_base[0], upper_triangle_indices_base[1]].cpu().numpy()
# Calculate the average of these pairwise similarities
average_uniformity_similarity_base = np.mean(uniformity_similarity_scores_base)
Et les résultats. Étant donné les données d’entraînement très limitées utilisées pour le réglage fin (seulement 3 exemples), il n’est pas surprenant que le modèle affiné ne montre pas une nette amélioration par rapport au modèle de base dans ces métriques spécifiques.
Le modèle de base conservé légèrement les éléments liés plus près ensemble que votre modèle affiné (alignement plus élevé), et a également conservé légèrement des éléments différents et sans rapport plus étalé ou moins encombré que votre modèle affiné (uniformité moindre).
* Base Model:
Base Model Alignment Score (Avg Cosine Similarity of Positive Pairs): 0.8451
Base Model Uniformity Score (Avg Pairwise Cos Sim. of Diverse Embeddings): 0.0754
* Fine Tuned Model:
Alignment Score (Average Cosine Similarity of Positive Pairs): 0.8270
Uniformity Score (Average Pairwise Cosine Similarity of Diverse Embeddings): 0.0777
Avant de partir
Dans cet article, nous avons découvert l’intégration de modèles et leur fonctionnement sous le capot, de manière pratique.
Ces modèles ont pris beaucoup d’importance après l’essor de l’IA, constituant un excellent moteur pour les applications RAG et la recherche rapide.
Les ordinateurs doivent disposer d’un moyen de comprendre le texte, et les intégrations en sont la clé. Ils codent le texte en vecteurs de nombres, ce qui permet aux modèles de calculer facilement les distances et de trouver les meilleures correspondances.
Voici mon contact, si vous avez aimé ce contenu. Retrouvez-moi sur mon site Internet.
Code du hub Git
https://github.com/gurezende/Studying/tree/master/Python/NLP/Embedding_Models
Références
[1. Modern NLP: Tokenization, Embedding, and Text Classification] (https://medium.com/data-science-collective/modern-nlp-tokenization-embedding-and-text-classification-448826f489bf?sk=6e5d94086f9636e451717dfd0bf1c03a)
[2. A Visual Guide to Using BERT for the First Time](https://jalammar.github.io/a-visual-guide-to-using-bert-for-the-first-time/)
[3. Qdrant Docs] (https://qdrant.tech/documentation/)



