Des modèles capables de lire des documents entiers et de comprendre leur sens comme un humain. Voici comment les entraîner sans se perdre dans les détails techniques.

INSTALLER LES Outils NÉCESSAIRES

Pour commencer, il faut installer les bibliothèques Python qui vont vous permettre de travailler avec les embeddings multi-vecteurs. Ces outils transforment vos textes en représentations numériques compréhensibles par les machines. Sans eux, impossible d'entraîner vos modèles.

pip install -U "sentence-transformers[train]"

Cette commande installe la dernière version de Sentence Transformers, une bibliothèque spécialisée dans la création et l'entraînement de modèles d'embeddings. Le [train] à la fin indique que vous installez aussi les outils nécessaires pour l'entraînement, pas seulement pour l'utilisation basique.

CHARGEMENT DU MODÈLE DE BASE

Une fois les outils installés, il faut choisir un modèle pré-entraîné. Ces modèles sont déjà capables de comprendre le langage, mais ils ne sont pas encore optimisés pour vos besoins spécifiques. Le choix du modèle dépend de la taille de vos données et de la puissance de votre ordinateur.

from sentence_transformers import MultiVectorEncoder

# Charger le modèle en précision 32 bits si votre mémoire le permet
model = MultiVectorEncoder(
    "lightonai/mLateOn-unsupervised",
    modelkwargs={"torchdtype": "float32"},
    processorkwargs={"modelmax_length": 8192},  # limite de tokens du tokenizer
)

Le modèle mLateOn-unsupervised est conçu pour traiter des documents longs sans limite de taille. La précision float32 est recommandée pour l'entraînement car elle offre un bon équilibre entre précision et consommation mémoire.

ADAPTER LE MODÈLE À VOS DOCUMENTS

Les modèles pré-entraînés sont souvent limités par la taille des textes qu'ils peuvent analyser. Par exemple, certains modèles comme GTE-ModernColBERT-v1 sont conçus pour traiter des requêtes de 48 tokens et des documents de 300 tokens. Si vos documents sont plus longs, il faut ajuster ces paramètres.

# Permettre au modèle de lire des documents complets au lieu des limites imposées
model[0].query_length = None
model[0].document_length = None

En supprimant ces limites, le modèle peut analyser des textes de n'importe quelle longueur, comme un livre entier ou un article scientifique. C'est comme donner des lunettes de lecture à un modèle qui avait des œillères.

CONFIGURER LA GESTION DES PONCTUATIONS

Les ponctuations peuvent perturber l'analyse des textes. Par exemple, les virgules ou les points-virgules n'apportent pas de sens utile à la compréhension du langage. Il est donc préférable de les ignorer pendant l'entraînement.

import string

# Le module MultiVectorMask est responsable de la gestion des mots à ignorer
model[2].skiplist_words = list(string.punctuation)
model[2].resolvewithtokenizer(model.tokenizer)  # recalculer les identifiants des tokens après modification

Cette étape consiste à créer une liste noire de mots à sauter, comme les signes de ponctuation. Le modèle apprendra à les ignorer automatiquement, ce qui améliore la qualité des embeddings générés.

CHOISIR UN MODÈLE SPÉCIALISÉ

Tous les modèles ne se valent pas. Certains sont optimisés pour des tâches spécifiques, comme la compréhension de textes médicaux ou juridiques. Le choix du modèle dépend donc de votre domaine d'application.

from sentence_transformers import MultiVectorEncoder

model = MultiVectorEncoder("answerdotai/ModernBERT-base", modelkwargs={"torchdtype": "float32"})

Le modèle ModernBERT-base est une version améliorée de BERT, optimisée pour des tâches de recherche d'information. Il utilise 768 dimensions pour représenter les embeddings, puis les réduit à 128 dimensions pour gagner en efficacité.

PRÉPARER VOTRE PROPRE ENSEMBLE DE DONNÉES

Pour entraîner un modèle, il faut des données. Dans ce cas, il s'agit de paires de questions et de passages de texte. Ces données doivent être soigneusement préparées : nettoyées, filtrées et organisées.

from datasets import load_dataset

traindataset = loaddataset("tomaarsen/miriad-4.4M-split", split="train")

print(train_dataset)
Dataset({ features: ['question', 'passage_text'], num_rows: 4467542 })

L'ensemble de données miriad-4.4M-split contient plus de 4 millions de paires question-passage. Chaque paire est un exemple que le modèle utilisera pour apprendre à associer une question à la réponse la plus pertinente dans un texte.

CRÉER UN ENSEMBLE DE DONNÉES PERSONNALISÉ

Si vous n'avez pas accès à un ensemble de données public, vous pouvez créer le vôtre à partir de fichiers locaux. Par exemple, un fichier CSV ou JSON contenant vos propres questions et documents.

from datasets import load_dataset

dataset = loaddataset("csv", datafiles="my_file.csv")
# ou


dataset = loaddataset("json", datafiles="my_file.json")

La bibliothèque datasets de Hugging Face permet de charger facilement des fichiers locaux. Vous pouvez aussi créer un ensemble de données à partir de dictionnaires Python.

from datasets import Dataset

queries = []
documents = []
# Ouvrir un fichier, effectuer un prétraitement, un filtrage, un nettoyage, etc.
# puis ajouter les résultats aux listes

dataset = Dataset.from_dict({
    "query": queries,
    "document": documents,
})

Cette méthode est utile si vous avez vos propres données brutes. Vous pouvez les nettoyer, les filtrer et les organiser avant de les convertir en un format compatible avec l'entraînement.

STRUCTURER VOS DONNÉES POUR L'ENTRAÎNEMENT

Les données doivent être organisées sous forme de tuples contenant une requête, un ou plusieurs documents et des scores de pertinence. Ces scores indiquent à quel point chaque document est pertinent par rapport à la requête.

(query, document1, ., documentN, scores)

Par exemple, une requête comme "Qu'est-ce que l'intelligence artificielle ?" pourrait être associée à plusieurs documents, chacun avec un score de 0 à 1 indiquant sa pertinence. Le modèle apprendra à maximiser les scores des documents les plus pertinents.

CHOISIR UNE FONCTION DE PERTE ADAPTÉE

L'entraînement d'un modèle repose sur une fonction de perte qui mesure l'écart entre les prédictions du modèle et les résultats attendus. Pour les embeddings multi-vecteurs, plusieurs fonctions de perte sont disponibles.

from sentence_transformers import MultiVectorEncoder
from sentencetransformers.multivector_encoder.losses import CachedMultiVectorMultipleNegativesRankingLoss

model = MultiVectorEncoder("lightonai/mLateOn-unsupervised", modelkwargs={"torchdtype": "float32"})

loss = CachedMultiVectorMultipleNegativesRankingLoss(
    model=model,
    minibatchsize=16,  # nombre de documents encodés par lot : limite la mémoire, pas la qualité
)

La fonction CachedMultiVectorMultipleNegativesRankingLoss est conçue pour améliorer la pertinence des résultats. Elle compare plusieurs documents négatifs (peu pertinents) avec un document positif (pertinent) pour chaque requête. Le modèle apprend ainsi à distinguer les bons résultats des mauvais.

LIMITER LA CONSOMMATION MÉMOIRE

L'entraînement de modèles d'embeddings peut consommer énormément de mémoire. Pour éviter les problèmes, il est possible de limiter le nombre de tokens traités en une seule fois.

minibatchnumtokens=15000

Cette limite de 15 000 tokens par lot permet de contrôler la consommation mémoire. C'est comme réduire la taille d'une image avant de l'envoyer par email : ça prend moins de place, mais ça reste utilisable.

DISTILLER LE MODÈLE POUR PLUS D'EFFICACITÉ

La distillation est une technique qui permet de réduire la taille d'un modèle tout en conservant ses performances. Cela rend le modèle plus rapide et moins gourmand en ressources.

MultiVectorDistillKLDivLoss

Cette fonction de perte utilise la divergence de Kullback-Leibler pour comparer les prédictions du modèle enseignant (grand et puissant) avec celles du modèle étudiant (petit et efficace). Le modèle étudiant apprend ainsi à imiter le modèle enseignant sans avoir besoin de sa puissance.

CONFIGURER LES PARAMÈTRES D'ENTRAÎNEMENT

L'entraînement nécessite des paramètres précis pour obtenir de bons résultats. Ces paramètres incluent le nombre d'époques, la taille des lots, le taux d'apprentissage et bien d'autres.

from sentence_transformers import MultiVectorEncoderTrainingArguments
from sentence_transformers.base.sampler import BatchSamplers

args = MultiVectorEncoderTrainingArguments(
    # Paramètre obligatoire :
    output_dir="models/mLateOn-medical",
    # Paramètres d'entraînement optionnels :
    numtrainepochs=1,
    perdevicetrainbatchsize=128,  # taille effective du lot contrastif, grâce à GradCache
    perdeviceevalbatchsize=16,
    learning_rate=1e-4,
    warmup_steps=0.05,
    prompts={"question": "[Q] ", "passage_text": "[D] "},  # marqueurs du checkpoint, indexés par colonne d'entraînement
    fp16=False,  # mettre à True si votre GPU supporte le FP16
    bf16=True,  # mettre à True si votre GPU supporte le BF16
    batchsampler=BatchSamplers.NODUPLICATES,  # les négatifs dans le lot bénéficient de l'absence de doublons
    # Paramètres de suivi/débogage optionnels :
    eval_strategy="steps",
    eval_steps=0.1,
    save_strategy="steps",
    save_steps=0.05,
    logging_steps=0.01,
    run_name="mLateOn-medical",  # sera utilisé par exemple dans Trackio ou W&B
)

Les paramètres comme numtrainepochs=1 indiquent que le modèle sera entraîné pendant une seule époque. Le learning_rate=1e-4 définit la vitesse à laquelle le modèle apprend. Plus ce taux est élevé, plus le modèle s'adapte rapidement, mais plus il risque de faire des erreurs.

ÉVALUER LES PERFORMANCES DU MODÈLE

Une fois l'entraînement terminé, il est crucial d'évaluer les performances du modèle. Plusieurs évaluateurs sont disponibles pour mesurer la qualité des embeddings générés.

MultiVectorInformationRetrievalEvaluator

Cet évaluateur mesure la capacité du modèle à retrouver des documents pertinents à partir de requêtes. Il utilise des métriques comme la précision et le rappel pour évaluer les performances.

TESTER AVEC DES BENCHMARKS SPÉCIFIQUES

Pour aller plus loin, il existe des benchmarks spécialisés dans l'évaluation des embeddings multi-vecteurs. Ces benchmarks permettent de comparer votre modèle avec d'autres modèles de l'état de l'art.

MultiVectorNanoBEIREvaluator

Le benchmark NanoBEIR est conçu pour évaluer les modèles sur des tâches de recherche d'information à petite échelle. Il permet de tester rapidement la qualité des embeddings avant de passer à des évaluations plus complexes.

MultiVectorTripletEvaluator

Cet évaluateur utilise des triplets de données : une requête, un document pertinent et un document non pertinent. Le modèle doit apprendre à rapprocher la requête du document pertinent et à éloigner la requête du document non pertinent.

MultiVectorRerankingEvaluator

Le réordonnancement est une étape clé dans les systèmes de recherche d'information. Cet évaluateur mesure la capacité du modèle à réordonner les résultats pour placer les documents les plus pertinents en tête de liste.

DISTILLER LE MODÈLE AVEC DES DONNÉES DE RÉFÉRENCE

La distillation peut aussi être appliquée avec des données de référence pour améliorer les performances du modèle. Cette technique utilise des paires de données pour guider l'apprentissage.

{'query': '.', 'positive': [.], 'negative': [.]}

Chaque exemple contient une requête, une liste de documents positifs (pertinents) et une liste de documents négatifs (non pertinents). Le modèle apprend à maximiser la similarité avec les documents positifs et à minimiser celle avec les documents négatifs.

ÉVALUER LA DISTILLATION

Pour mesurer l'efficacité de la distillation, il existe des évaluateurs spécifiques qui comparent les performances du modèle avant et après distillation.

MultiVectorDistillationEvaluator

Cet évaluateur utilise des métriques comme la perte de distillation pour évaluer la qualité de la distillation. Une perte faible indique que le modèle a bien appris à imiter le modèle enseignant.

CONFIGURER UN ÉVALUATEUR POUR LA RECHERCHE D'INFORMATION

Pour tester votre modèle dans un contexte de recherche d'information, il faut un ensemble de données d'évaluation adapté. Cet ensemble doit contenir des questions, des documents pertinents et des documents non pertinents.

from datasets import load_dataset
from sentencetransformers.multivector_encoder.evaluation import MultiVectorInformationRetrievalEvaluator

dataset = load_dataset("tomaarsen/miriad-4.4M-split")

# 1 000 questions d'évaluation, chacune associée à son passage pertinent,
# avec environ 10 000 passages uniques comme corpus initial
corpus = {}
queries = {}
relevant_docs = {}
passagetoid = {}
for idx, row in enumerate(dataset["eval"]):
    if row["passagetext"] not in passageto_id:
        passagetoid[row["passagetext"]] = f"p{len(passageto_id)}"
        corpus[passagetoid[row["passagetext"]]] = row["passagetext"]

Cet extrait de code montre comment préparer un ensemble de données pour l'évaluation. Chaque passage de texte est associé à un identifiant unique, comme p0, p1, etc. Les questions et les documents pertinents sont ensuite organisés dans des dictionnaires pour faciliter l'évaluation.

Sources :
  • Hugging Face Blog

L'indépendance de CLODCO est votre garantie.

Pour que l'actualité de l'IA reste sans filtre et sans concession, votre soutien est indispensable. Votre contribution est le seul moteur de notre liberté éditoriale.

Soutenir CLODCO