Comment obtenir les bons embeddings vectoriels
Cet article a été initialement publié dans The New Stack et est republié ici avec autorisation.
Une introduction complète aux embeddings vectoriels et à la manière de les générer avec des modèles open source populaires.
Image par Денис Марчук depuis Pixabay
Les embeddings vectoriels sont essentiels lorsque l’on travaille avec la similarité sémantique. Cependant, un vecteur est simplement une série de nombres ; un embedding vectoriel est une série de nombres représentant des données d’entrée. Grâce aux embeddings vectoriels, nous pouvons structurer des données non structurées ou travailler avec n’importe quel type de données en les convertissant en une série de nombres. Cette approche nous permet d’effectuer des opérations mathématiques sur les données d’entrée, plutôt que de nous appuyer sur des comparaisons qualitatives.
Les embeddings vectoriels jouent un rôle important dans de nombreuses tâches, en particulier pour la recherche sémantique. Cependant, il est crucial d’obtenir les embeddings vectoriels appropriés avant de les utiliser. Par exemple, si vous utilisez un modèle d’image pour vectoriser du texte, ou inversement, vous obtiendrez probablement de mauvais résultats.
Dans cet article, nous découvrirons ce que signifient les embeddings vectoriels, comment générer les bons embeddings vectoriels pour vos applications à l’aide de différents modèles, et comment tirer le meilleur parti des embeddings vectoriels avec des bases de données vectorielles comme Milvus et Zilliz Cloud.
Comment les embeddings vectoriels sont-ils créés ?
Maintenant que nous comprenons l’importance des embeddings vectoriels, apprenons comment ils fonctionnent. Un embedding vectoriel est la représentation interne des données d’entrée dans un modèle d’apprentissage profond, également appelé modèle d’embedding ou réseau neuronal profond. Alors, comment extraire ces informations ?
Nous obtenons des vecteurs en supprimant la dernière couche et en prenant la sortie de l’avant-dernière couche. La dernière couche d’un réseau neuronal produit généralement la prédiction du modèle ; nous prenons donc la sortie de l’avant-dernière couche. L’embedding vectoriel correspond aux données transmises à la couche prédictive d’un réseau neuronal.
La dimensionnalité d’un embedding vectoriel est équivalente à la taille de l’avant-dernière couche du modèle et, par conséquent, interchangeable avec la taille ou la longueur du vecteur. Les dimensionnalités vectorielles courantes incluent 384 (générée par Sentence Transformers Mini-LM), 768 (par Sentence Transformers MPNet), 1 536 (par OpenAI) et 2 048 (par ResNet-50).
Que signifie un embedding vectoriel ?
Quelqu’un m’a un jour demandé quelle était la signification de chaque dimension dans un embedding vectoriel. La réponse courte est : rien. Une seule dimension dans un embedding vectoriel ne signifie rien, car elle est trop abstraite pour que l’on puisse en déterminer le sens. Cependant, lorsque nous considérons toutes les dimensions ensemble, elles fournissent la signification sémantique des données d’entrée.
Les dimensions du vecteur sont des représentations abstraites de haut niveau de différents attributs. Les attributs représentés dépendent des données d’entraînement et du modèle lui-même. Les modèles de texte et d’image génèrent des embeddings différents parce qu’ils sont entraînés pour des types de données fondamentalement différents. Même différents modèles de texte génèrent des embeddings différents. Parfois, ils diffèrent par leur taille ; d’autres fois, ils diffèrent par les attributs qu’ils représentent. Par exemple, un modèle entraîné sur des données juridiques apprendra des choses différentes d’un modèle entraîné sur des données de santé. J’ai exploré ce sujet dans mon article comparant les embeddings vectoriels.
Générer les bons embeddings vectoriels
Comment obtenez-vous les bons embeddings vectoriels ? Tout commence par l’identification du type de données que vous souhaitez intégrer. Cette section couvre l’intégration de cinq types de données différents : images, texte, audio, vidéos et données multimodales. Tous les modèles que nous présentons ici sont open source et proviennent de Hugging Face ou de PyTorch.
Embeddings d’images
La reconnaissance d’images a pris son essor en 2012 après l’arrivée d’AlexNet sur le devant de la scène. Depuis, le domaine de la vision par ordinateur a connu de nombreuses avancées. Le dernier modèle notable de reconnaissance d’images est ResNet-50, un réseau résiduel profond à 50 couches basé sur l’ancienne architecture ResNet-34.
Les réseaux de neurones résiduels (ResNet) résolvent le problème de disparition du gradient dans les réseaux de neurones convolutifs profonds grâce à des connexions de raccourci. Ces connexions permettent à la sortie des couches précédentes d’aller directement vers les couches ultérieures sans passer par toutes les couches intermédiaires, évitant ainsi le problème de disparition du gradient. Cette conception rend ResNet moins complexe que VGGNet (Visual Geometry Group), un réseau de neurones convolutif qui obtenait auparavant les meilleures performances.
Je recommande deux implémentations de ResNet-50 à titre d’exemples : ResNet 50 sur Hugging Face et ResNet 50 sur PyTorch Hub. Bien que les réseaux soient identiques, le processus d’obtention des embeddings diffère.
L’exemple de code ci-dessous montre comment utiliser PyTorch pour obtenir des embeddings vectoriels. Tout d’abord, nous chargeons le modèle depuis PyTorch Hub. Ensuite, nous supprimons la dernière couche et appelons .eval() pour indiquer au modèle de se comporter comme s’il s’exécutait en mode inférence. Puis, la fonction embed génère l’embedding vectoriel.
# Load the embedding model with the last layer removed
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True) model = torch.nn.Sequential(*(list(model.children())[:-1]))
model.eval()
def embed(data):
with torch.no_grad():
output = model(torch.stack(data[0])).squeeze()
return output
HuggingFace utilise une configuration légèrement différente. Le code ci-dessous montre comment obtenir un embedding vectoriel à partir de Hugging Face. Tout d’abord, nous avons besoin d’un extracteur de caractéristiques et d’un modèle provenant de la bibliothèque transformers . Nous utiliserons l’extracteur de caractéristiques pour obtenir les entrées du modèle et utiliserons le modèle pour obtenir les sorties et extraire le dernier état caché.
# Load model directly
from transformers import AutoFeatureExtractor, AutoModelForImageClassification
extractor = AutoFeatureExtractor.from_pretrained("microsoft/resnet-50")
model = AutoModelForImageClassification.from_pretrained("microsoft/resnet-50")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Embeddings de texte
Les ingénieurs et les chercheurs expérimentent avec le langage naturel et l’IA depuis l’invention de l’IA. Parmi les premières expériences figurent :
- ELIZA, le premier chatbot thérapeute basé sur l’IA.
- La chambre chinoise de John Searle, une expérience de pensée qui examine si la capacité à traduire entre le chinois et l’anglais nécessite une compréhension de la langue.
- Les traductions fondées sur des règles entre l’anglais et le russe.
Le fonctionnement de l’IA sur le langage naturel a considérablement évolué depuis ses embeddings fondés sur des règles. En partant des réseaux de neurones primaires, nous avons ajouté des relations de récurrence via les RNN afin de suivre les étapes dans le temps. À partir de là, nous avons utilisé les transformeurs pour résoudre le problème de transduction de séquences.
Les transformeurs se composent d’un encodeur, qui encode une entrée dans une matrice représentant l’état, d’une matrice d’attention et d’un décodeur. Le décodeur décode l’état et la matrice d’attention afin de prédire le bon jeton suivant pour terminer la séquence de sortie. GPT-3, le modèle de langage le plus populaire à ce jour, se compose de décodeurs stricts. Ils encodent l’entrée et prédisent le ou les bons jetons suivants.
Voici deux modèles de la bibliothèque sentence-transformers de Hugging Face que vous pouvez utiliser en plus des embeddings d’OpenAI :
- MiniLM-L6-v2 : un modèle à 384 dimensions
- MPNet-Base-V2 : un modèle à 768 dimensions
Vous pouvez accéder aux embeddings des deux modèles de la même manière.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("<model-name>")
vector_embeddings = model.encode(“<input>”)
Embeddings multimodaux
Les modèles multimodaux sont moins développés que les modèles d’image ou de texte. Ils relient souvent les images au texte.
L’exemple open source le plus utile est CLIP VIT, un modèle image-texte. Vous pouvez accéder aux embeddings de CLIP VIT de la même manière qu’avec un modèle d’image, comme indiqué dans le code ci-dessous.
# Load model directly
from transformers import AutoProcessor, AutoModelForZeroShotImageClassification
processor = AutoProcessor.from_pretrained("openai/clip-vit-large-patch14")
model = AutoModelForZeroShotImageClassification.from_pretrained("openai/clip-vit-large-patch14")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Embeddings audio
L’IA pour l’audio a reçu moins d’attention que l’IA pour le texte ou les images. Le cas d’usage le plus courant pour l’audio est la transcription vocale en texte pour des secteurs tels que les centres d’appels, les technologies médicales et l’accessibilité. Un modèle open source populaire pour la transcription vocale en texte est Whisper d’OpenAI. Le code ci-dessous montre comment obtenir des embeddings vectoriels à partir du modèle de transcription vocale en texte.
import torch
from transformers import AutoFeatureExtractor, WhisperModel
from datasets import load_dataset
model = WhisperModel.from_pretrained("openai/whisper-base")
feature_extractor = AutoFeatureExtractor.from_pretrained("openai/whisper-base")
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
input_features = inputs.input_features
decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
vector_embedding = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
Embeddings vidéo
Les embeddings vidéo sont plus complexes que les embeddings audio ou d’image. Une approche multimodale est nécessaire lorsque l’on travaille avec des vidéos, car elles incluent de l’audio et des images synchronisés. Un modèle vidéo populaire est le multimodal perceiver de DeepMind. Ce tutoriel sous forme de notebook montre comment utiliser le modèle pour classer une vidéo.
Pour obtenir les embeddings de l’entrée, utilisez outputs[1][-1].squeeze() à partir du code présenté dans le notebook au lieu de supprimer les sorties. Je mets en évidence cet extrait de code dans la fonction autoencode .
def autoencode_video(images, audio):
# only create entire video once as inputs
inputs = {'image': torch.from_numpy(np.moveaxis(images, -1, 2)).float().to(device),
'audio': torch.from_numpy(audio).to(device),
'label': torch.zeros((images.shape[0], 700)).to(device)}
nchunks = 128
reconstruction = {}
for chunk_idx in tqdm(range(nchunks)):
image_chunk_size = np.prod(images.shape[1:-1]) // nchunks
audio_chunk_size = audio.shape[1] // SAMPLES_PER_PATCH // nchunks
subsampling = {
'image': torch.arange(
image_chunk_size * chunk_idx, image_chunk_size * (chunk_idx + 1)),
'audio': torch.arange(
audio_chunk_size * chunk_idx, audio_chunk_size * (chunk_idx + 1)),
'label': None,
}
# forward pass
with torch.no_grad():
outputs = model(inputs=inputs, subsampled_output_points=subsampling)
output = {k:v.cpu() for k,v in outputs.logits.items()}
reconstruction['label'] = output['label']
if 'image' not in reconstruction:
reconstruction['image'] = output['image']
reconstruction['audio'] = output['audio']
else:
reconstruction['image'] = torch.cat(
[reconstruction['image'], output['image']], dim=1)
reconstruction['audio'] = torch.cat(
[reconstruction['audio'], output['audio']], dim=1)
vector_embeddings = outputs[1][-1].squeeze()
# finally, reshape image and audio modalities back to original shape
reconstruction['image'] = torch.reshape(reconstruction['image'], images.shape)
reconstruction['audio'] = torch.reshape(reconstruction['audio'], audio.shape)
return reconstruction
return None
Stockage, indexation et recherche d’embeddings vectoriels avec des bases de données vectorielles
Maintenant que nous comprenons ce que sont les embeddings vectoriels et comment les générer à l’aide de divers modèles d’embedding puissants, la question suivante est de savoir comment les stocker et en tirer parti. Les bases de données vectorielles sont la réponse.
Les bases de données vectorielles comme Milvus et Zilliz Cloud sont spécialement conçues pour stocker, indexer et effectuer des recherches dans d’immenses ensembles de données non structurées au moyen d’embeddings vectoriels. Elles constituent également l’une des infrastructures les plus critiques pour diverses piles d’IA.
Les bases de données vectorielles utilisent généralement l’algorithme Approximate Nearest Neighbor (ANN) pour calculer la distance spatiale entre le vecteur de requête et les vecteurs stockés dans la base de données. Plus les deux vecteurs sont proches, plus ils sont pertinents. Ensuite, l’algorithme trouve les k plus proches voisins et les fournit à l’utilisateur.
Les bases de données vectorielles sont populaires dans des cas d’utilisation tels que la génération augmentée par récupération des LLM (RAG), les systèmes de questions-réponses, les systèmes de recommandation, les recherches sémantiques, ainsi que les recherches de similarité d’images, de vidéos et d’audio.
Pour en savoir plus sur les embeddings vectoriels, les données non structurées et les bases de données vectorielles, envisagez de commencer par la série Vector Database 101 .
Résumé
Les vecteurs sont un outil puissant pour travailler avec des données non structurées. À l’aide de vecteurs, nous pouvons comparer mathématiquement différentes portions de données non structurées en fonction de leur similarité sémantique. Le choix du bon modèle d’embedding vectoriel est essentiel pour créer un moteur de recherche vectorielle pour toute application.
Dans cet article, nous avons appris que les plongements vectoriels sont la représentation interne des données d’entrée dans un réseau de neurones. Par conséquent, ils dépendent fortement de l’architecture du réseau et des données utilisées pour entraîner le modèle. Différents types de données (comme les images, le texte et l’audio) nécessitent des modèles spécifiques. Heureusement, de nombreux modèles open source préentraînés sont disponibles à l’utilisation. Dans cet article, nous avons couvert les modèles pour les cinq types de données les plus courants : images, texte, multimodal, audio et vidéo. De plus, si vous souhaitez tirer le meilleur parti des plongements vectoriels, les bases de données vectorielles sont l’outil le plus populaire.
Continuer à lire

Introducing Business Critical Plan: Enterprise-Grade Security and Compliance for Mission-Critical AI Applications
Discover Zilliz Cloud’s Business Critical Plan—offering advanced security, compliance, and uptime for mission-critical AI and vector database workloads.

Bringing AI to Legal Tech: The Role of Vector Databases in Enhancing LLM Guardrails
Discover how vector databases enhance AI reliability in legal tech, ensuring accurate, compliant, and trustworthy AI-powered legal solutions.

DeepSeek Always Busy? Deploy It Locally with Milvus in Just 10 Minutes—No More Waiting!
Learn how to set up DeepSeek-R1 on your local machine using Ollama, AnythingLLM, and Milvus in just 10 minutes. Bypass busy servers and enhance AI responses with custom data.



