Comment obtenir les bons Vector Embeddings ?
Cet article a été publié à l'origine dans The New Stack et est repris ici avec permission.
Une introduction complète aux vector embeddings et à la manière de les générer avec des modèles open source populaires.
Image par Денис Марчук de Pixabay
Les encastrements vectoriels sont essentiels lorsque l'on travaille sur la similarité sémantique. Cependant, un vecteur est simplement une série de nombres ; un encastrement vectoriel est une série de nombres représentant des données d'entrée. L'intégration vectorielle permet de structurer des données non structurées ou de 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 encastrements vectoriels ont une grande influence sur de nombreuses tâches, en particulier sur la recherche sémantique. Toutefois, il est essentiel d'obtenir les encastrements vectoriels appropriés avant de les utiliser. Par exemple, si vous utilisez un modèle d'image pour vectoriser du texte, ou vice versa, vous obtiendrez probablement de mauvais résultats.
Dans cet article, nous allons apprendre ce que signifient les embeddings vectoriels, comment générer les embeddings vectoriels appropriés pour vos applications en utilisant différents modèles et comment utiliser au mieux les embeddings vectoriels avec des bases de données vectorielles telles que Milvus et Zilliz Cloud.
Comment les incrustations vectorielles sont-elles créées ?
Maintenant que nous comprenons l'importance des embeddings vectoriels, apprenons comment ils fonctionnent. Un vector embedding est la représentation interne des données d'entrée dans un modèle d'apprentissage profond, également connu sous le nom de modèles d'intégration ou de réseau neuronal profond. 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'intégration vectorielle correspond aux données transmises à la couche prédictive d'un réseau neuronal.
La dimensionnalité d'un vecteur intégré est équivalente à la taille de l'avant-dernière couche du modèle et est donc interchangeable avec la taille ou la longueur du vecteur. Les dimensions courantes des vecteurs sont 384 (générées par Sentence Transformers Mini-LM), 768 (par Sentence Transformers MPNet), 1 536 (par OpenAI) et 2 048 (par ResNet-50).
Que signifie l'intégration vectorielle ?
Quelqu'un m'a demandé un jour ce que signifiait chaque dimension d'un vector embedding. La réponse courte est : rien. Une seule dimension d'un vecteur intégré ne signifie rien, car elle est trop abstraite pour que l'on puisse en déterminer la signification. Cependant, lorsque nous prenons 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'apprentissage et du modèle lui-même. Les modèles de texte et d'image génèrent des encastrements différents parce qu'ils sont formés pour des types de données fondamentalement différents. Même des modèles de texte différents génèrent des encastrements différents. Ils diffèrent parfois par leur taille, mais aussi par les attributs qu'ils représentent. Par exemple, un modèle formé sur des données juridiques apprendra des choses différentes d'un modèle formé sur des données de soins de santé. J'ai exploré ce sujet dans mon article sur la comparaison des vector embeddings.
Générer les bons vector embeddings
Comment obtenir 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 présentés ici sont open source et proviennent de Hugging Face ou PyTorch.
Intégration d'images
La reconnaissance d'images a pris son essor en 2012 après l'apparition d'AlexNet. 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 neuronaux résiduels (ResNet) résolvent le problème de la disparition du gradient dans les réseaux neuronaux convolutionnels profonds à l'aide de connexions raccourcies. Ces connexions permettent à la sortie des couches précédentes d'aller directement aux couches suivantes sans passer par toutes les couches intermédiaires, évitant ainsi le problème du gradient de fuite. Cette conception rend ResNet moins complexe que VGGNet (Visual Geometry Group), un réseau neuronal convolutionnel précédemment très performant.
Je recommande deux implémentations de ResNet-50 à titre d'exemple : ResNet 50 sur Hugging Face et ResNet 50 sur PyTorch Hub. Bien que les réseaux soient les mêmes, 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 demander au modèle de se comporter comme s'il était en cours d'exécution pour l'inférence. Ensuite, la fonction embed
génère l'intégration vectorielle.
# 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 encapsulage vectoriel à partir de Hugging Face. Tout d'abord, nous avons besoin d'un extracteur de caractéristiques et d'un modèle de la bibliothèque transformers
. Nous utiliserons l'extracteur de caractéristiques pour obtenir des entrées pour le modèle et utiliserons le modèle pour obtenir des 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()
Incrustations de texte
Les ingénieurs et les chercheurs ont expérimenté le langage naturel et l'IA depuis l'invention de l'IA. Parmi les premières expériences, on peut citer
- ELIZA, le premier chatbot thérapeute de l'IA.
- La chambre chinoise de John Searle, une expérience de pensée qui examine si la capacité de traduire entre le chinois et l'anglais nécessite une compréhension de la langue.
- Traductions entre l'anglais et le russe basées sur des règles.
Le fonctionnement de l'IA sur le langage naturel a évolué de manière significative par rapport à son intégration basée sur des règles. En commençant par les réseaux neuronaux primaires, nous avons ajouté des relations de récurrence par le biais des RNN pour suivre les étapes dans le temps. Ensuite, nous avons utilisé des transformateurs pour résoudre le problème de la transduction des séquences.
Les transformateurs se composent d'un encodeur, qui code 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 prochain jeton correct pour terminer la séquence de sortie. Le GPT-3, le modèle linguistique le plus populaire à ce jour, comprend des décodeurs stricts. Ils codent l'entrée et prédisent le(s) bon(s) mot(s) suivant(s).
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>”)
Encastrements multimodaux
Les modèles multimodaux sont moins bien 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 que vous le feriez avec un modèle d'image, comme le montre 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()
Incrustations audio
L'IA pour l'audio a reçu moins d'attention que l'IA pour le texte ou les images. Le cas d'utilisation le plus courant pour l'audio est la conversion de la parole en texte dans des secteurs tels que les centres d'appel, la technologie médicale et l'accessibilité. Un modèle open source populaire pour la conversion de la parole au texte est Whisper d'OpenAI. Le code ci-dessous montre comment obtenir des embeddings vectoriels à partir du modèle parole-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
Encastrements vidéo
Les encastrements vidéo sont plus complexes que les encastrements audio ou d'images. Une approche multimodale est nécessaire lorsque l'on travaille avec des vidéos, car elles contiennent du son et des images synchronisés. Un modèle vidéo populaire est le perceur multimodal de DeepMind. Ce tutoriel montre comment utiliser ce 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 encastrements vectoriels et comment les générer à l'aide de différents modèles d'encastrement 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 telles que Milvus et Zilliz Cloud sont spécialement conçues pour le stockage, l'indexation et la recherche dans des ensembles massifs de données non structurées par le biais d'incrustations vectorielles. Elles constituent également l'une des infrastructures les plus critiques pour les différentes piles d'IA.
Les bases de données vectorielles utilisent généralement l'algorithme ANN (Approximate Nearest Neighbor) pour calculer la distance spatiale entre le vecteur de la requête et les vecteurs stockés dans la base de données. Plus les deux vecteurs sont proches, plus ils sont pertinents. L'algorithme trouve ensuite les k premiers voisins les plus proches 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 de recherche LLM (RAG), les systèmes de questions-réponses, les systèmes de recommandation, les recherches sémantiques et les recherches de similitudes d'images, de vidéos et d'audio.
Pour en savoir plus sur les encastrements vectoriels, les données non structurées et les bases de données vectorielles, commencez par la série Base de données vectorielles 101.
Résumé
Les vecteurs sont un outil puissant pour travailler avec des données non structurées. Ils permettent de comparer mathématiquement différents éléments de données non structurées sur la base de la similarité sémantique. Le choix du bon modèle d'incorporation de vecteurs est essentiel pour construire un moteur de recherche vectoriel pour n'importe quelle application.
Dans ce billet, nous avons appris que les vector embeddings sont la représentation interne des données d'entrée dans un réseau neuronal. Par conséquent, ils dépendent fortement de l'architecture du réseau et des données utilisées pour former le modèle. Les différents types de données (tels que les images, le texte et l'audio) requièrent des modèles spécifiques. Heureusement, de nombreux modèles open source pré-entraînés sont disponibles. Dans cet article, nous avons abordé 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 utiliser au mieux les embeddings vectoriels, les bases de données vectorielles sont l'outil le plus populaire.
- Comment les incrustations vectorielles sont-elles créées ?
- Que signifie l'intégration vectorielle ?
- Générer les bons vector embeddings
- Stockage, indexation et recherche d'embeddings vectoriels avec des bases de données vectorielles
- Résumé
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word