HyperAI
Back to Headlines

SPLADE-Modell feinjustiert für kosteneffiziente hybride Suchanwendungen

vor 4 Tagen

Sentence Transformers ist eine Python-Bibliothek, die das Training und die Verwendung von Embedding- und Reranker-Modellen für eine Vielzahl von Anwendungen wie hybrider Generierung, semantischer Suche, semantischer Textähnlichkeit und Paraphrase-Mining ermöglicht. Die letzten großen Versionen haben erhebliche Verbesserungen beim Training eingeführt. In diesem Artikel werde ich zeigen, wie man ein dünnbesetztes Modell (sparse encoder) feintune und warum man dies tun möchte. Das Resultat ist das Modell „sparse-encoder/example-inference-free-splade-distilbert-base-uncased-nq“, das besonders gut in hybriden Suchszenarien oder bei der Kombination von Suchen und Reranking abschneidet. Dünnbesetzte Embedding-Modelle unterscheiden sich von dichtbesetzten Modellen dadurch, dass sie hochdimensionale Vektoren mit vielen Nullwerten erzeugen. Jede aktive Dimension in einem dünnbesetzten Embedding entspricht einem spezifischen Token im Vokabular des Modells, was Interpretierbarkeit ermöglicht. Zum Beispiel erzeugt das State-of-the-Art-Modell „naver/splade-v3“ 30.522-dimensionale Vektoren: ```python from sentence_transformers import SparseEncoder Modell vom Hugging Face Hub herunterladen model = SparseEncoder("naver/splade-v3") Inferenz durchführen sentences = [ "Das Wetter ist heute wunderschön.", "Es ist draußen so sonnig!", "Er fuhr zum Stadion.", ] embeddings = model.encode(sentences) print(embeddings.shape) (3, 30522) Ähnlichkeitswerte der Embeddings berechnen similarities = model.similarity(embeddings, embeddings) print(similarities) tensor([[ 32.4323, 5.8528, 0.0258], [ 5.8528, 26.6649, 0.0302], [ 0.0258, 0.0302, 24.0839]]) Embeddings dekodieren, um sie zu interpretieren decoded = model.decode(embeddings, top_k=10) for decoded, sentence in zip(decoded, sentences): print(f"Satz: {sentence}") print(f"Dekodiert: {decoded}") print() Satz: Das Wetter ist heute wunderschön. Dekodiert: [('Wetter', 2.754288673400879), ('heute', 2.610959529876709), ('wunderschön', 2.431990623474121), ('momentan', 1.5520408153533936), ('schön', 1.5046082735061646), ('angenehm', 1.4664798974990845), ('hübsch', 0.8986214995384216), ('gestern', 0.8603134155273438), ('nett', 0.8322536945343018), ('Sommer', 0.7702118158340454)] Satz: Es ist draußen so sonnig! Dekodiert: [('draußen', 2.6939032077789307), ('sonnig', 2.535827398300171), ('so', 2.0600898265838623), ('draußen', 1.5397940874099731), ('Wetter', 1.1198079586029053), ('sehr', 0.9873268604278564), ('angenehm', 0.9406591057777405), ('es', 0.9026399254798889), ('Sommer', 0.684999406337738), ('Sonne', 0.6520509123802185)] Satz: Er fuhr zum Stadion. Dekodiert: [('Stadion', 2.7872302532196045), ('fuhr', 1.8208855390548706), ('Fahrt', 1.6665740013122559), ('fahren', 1.5565159320831299), ('er', 1.4721972942352295), ('Stadien', 1.449463129043579), ('zu', 1.0441515445709229), ('Auto', 0.7002660632133484), ('Besuch', 0.5118278861045837), ('Fußball', 0.502326250076294)] ``` Ein weiteres zentrales Element der neuralen dünnbesetzten Modelle ist die Abfrage- und Dokumentenerweiterung. Diese Methoden erweitern den ursprünglichen Text automatisch um semantisch verwandte Terme, was sie zur Überwindung von Vokabularfehlern und zur Behandlung von Fehlschreibungen befähigt. Zum Beispiel wird der Satz „Das Wetter ist heute wunderschön.“ erweitert zu Termen wie „schön“, „angenehm“, „hübsch“ und „nett“. Warum sollten dünnbesetzte Modell-Embeddings verwendet werden? Sie bieten einen wertvollen Mittelweg zwischen traditionellen lexikalischen Methoden wie BM25 und dichtbesetzten Modellen wie Sentence Transformers. Ihre Vorteile sind: Effizienz: Sie sind Speicher- und rechenleistungseffizient. Interpretierbarkeit: Die aktiven Dimensionen in den Embeddings können direkt auf Tokens im Vokabular zugeordnet werden. Leistung: Sie übertreffen oft traditionelle lexikalische Suchmethoden, ohne dabei die Effizienz von dünnbesetzten Darstellungen zu opfern. Dünnbesetzte Modelle müssen jedoch oft feintune werden, um spezifische Domänen oder Sprachen besser zu erkennen. Zum Beispiel würde das Modell den Begriff „Cephalalgie“ standardmäßig nicht als „Kopfschmerzen“ erweitern. Durch Feintuning kann das Modell lernen, sich ausschließlich auf die für Sie relevanten Domänen oder Sprachen zu konzentrieren. Das Training von Sentence Transformer-Modellen umfasst verschiedene Komponenten: das Modell, Datensätze, Verlustfunktionen, Trainingsparameter, Evaluatoren und den Trainer. Hier eine detaillierte Betrachtung dieser Komponenten: Modell Dünnbesetzte Encoder-Modelle bestehen aus einer Reihe von Modulen, die Flexibilität bieten. Wenn man ein bereits vorbereitetes Modell feintunen möchte, kann man es einfach herunterladen: ```python from sentence_transformers import SparseEncoder model = SparseEncoder("naver/splade-cocondenser-ensembledistil") ``` Wenn man stattdessen von einem anderen Checkpoint oder von Grund auf neu trainieren möchte, können folgende Architekturen verwendet werden: Splade Splade-Modelle verwenden einen MLMTransformer gefolgt von einem SpladePooling-Modul. Der MLMTransformer lädt ein vorbereitetes Masked Language Modeling-Modell (z.B. BERT, RoBERTa, DistilBERT), und SpladePooling poolt die Ausgabe des MLMHead, um einen einzigen dünnbesetzten Embedding mit der Größe des Vokabulars zu erzeugen: ```python from sentence_transformers import models, SparseEncoder from sentence_transformers.sparse_encoder.models import MLMTransformer, SpladePooling Initialisieren des MLM-Transformers (verwenden eines Fill-Mask-Modells) mlm_transformer = MLMTransformer("google-bert/bert-base-uncased") Initialisieren des SpladePooling-Moduls splade_pooling = SpladePooling(pooling_strategy="max") Erstellen des Splade-Modells model = SparseEncoder(modules=[mlm_transformer, splade_pooling]) ``` Inference-freies Splade Inference-freies Splade verwendet ein Router-Modul mit unterschiedlichen Modulen für Abfragen und Dokumente. Normalerweise besteht der Dokumententeil aus einer traditionellen Splade-Architektur (MLMTransformer gefolgt von SpladePooling), während der Abfragenteil ein SparseStaticEmbedding-Modul ist, das für jedes Token in der Abfrage eine vorgeberechnete Punktzahl zurückgibt: ```python from sentence_transformers import SparseEncoder, models from sentence_transformers.sparse_encoder.models import SparseStaticEmbedding, MLMTransformer, SpladePooling Initialisieren des MLM-Transformers für die Dokumentenkodierung doc_encoder = MLMTransformer("google-bert/bert-base-uncased") Router-Modell mit unterschiedlichen Pfaden für Abfragen und Dokumente erstellen router = models.Router.for_query_document( query_modules=[SparseStaticEmbedding(tokenizer=doc_encoder.tokenizer, frozen=False)], document_modules=[doc_encoder, SpladePooling("max")], ) Inference-freies Modell erstellen model = SparseEncoder(modules=[router], similarity_fn_name="dot") ``` Diese Architektur ermöglicht schnelles Abfrageverarbeitung, da die Rechenaufwände auf die Offline-Phase des Dokumentindexierungs verlagert werden. Verlustfunktionen Verlustfunktionen messen, wie gut das Modell auf einem gegebenen Datenbatch auftritt und leiten den Optimierungsprozess. Je nach Architektur muss entweder SpladeLoss oder CSRLoss verwendet werden. Diese sind Wrapper-Verlustfunktionen, die Sparsitätsregularisierung zu einer Hauptverlustfunktion hinzufügen. Ein Beispiel für die Initialisierung dieser Verlustfunktionen: ```python from sentence_transformers import SparseEncoder from sentence_transformers.sparse_encoder.losses import SpladeLoss, SparseMultipleNegativesRankingLoss Modell laden, um es zu feintunen model = SparseEncoder("distilbert/distilbert-base-uncased") SpladeLoss initialisieren loss = SpladeLoss( model=model, loss=SparseMultipleNegativesRankingLoss(model=model), query_regularizer_weight=5e-5, document_regularizer_weight=3e-5, ) ``` Trainingsparameter Die Klasse SparseEncoderTrainingArguments ermöglicht das Spezifizieren von Parametern, die das Trainingsverhalten beeinflussen: ```python from sentence_transformers import SparseEncoderTrainingArguments args = SparseEncoderTrainingArguments( output_dir="models/splade-distilbert-base-uncased-nq", num_train_epochs=1, per_device_train_batch_size=16, per_device_eval_batch_size=16, learning_rate=2e-5, learning_rate_mapping={r"SparseStaticEmbedding.weight": 1e-3}, warmup_ratio=0.1, fp16=True, batch_sampler=models.BatchSamplers.NO_DUPLICATES, eval_strategy="steps", eval_steps=1000, save_strategy="steps", save_steps=1000, save_total_limit=2, logging_steps=200, run_name="inference-free-splade-distilbert-base-uncased-nq", ) ``` Evaluator Evaluatoren helfen, die Leistung des Modells während des Trainings zu bewerten. Beispiele für implementierte Evaluatoren sind SparseNanoBEIREvaluator, SparseEmbeddingSimilarityEvaluator und SparseTripletEvaluator. Hier ein Beispiel für SparseNanoBEIREvaluator: ```python from sentence_transformers.sparse_encoder.evaluation import SparseNanoBEIREvaluator Evaluator initialisieren dev_evaluator = SparseNanoBEIREvaluator() ``` Trainer Der SparseEncoderTrainer bringt alle bisher besprochenen Komponenten zusammen. Hier ein Beispiel, wie man den Trainer mit dem Modell, den Trainingsparametern, dem Trainingsdatensatz, dem Evaluatordatensatz, der Verlustfunktion und dem Evaluator initialisiert: ```python import logging from datasets import load_dataset from sentence_transformers import SparseEncoder, SparseEncoderTrainer, SparseEncoderTrainingArguments from sentence_transformers.sparse_encoder.losses import SpladeLoss, SparseMultipleNegativesRankingLoss from sentence_transformers.sparse_encoder.evaluation import SparseNanoBEIREvaluator from sentence_transformers.models import Router, MLMTransformer, SpladePooling logging.basicConfig(format="%(asctime)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO) Modell laden mlm_transformer = MLMTransformer("distilbert/distilbert-base-uncased", tokenizer_args={"model_max_length": 512}) splade_pooling = SpladePooling(pooling_strategy="max", word_embedding_dimension=mlm_transformer.get_sentence_embedding_dimension()) router = Router.for_query_document(query_modules=[SparseStaticEmbedding(tokenizer=mlm_transformer.tokenizer, frozen=False)], document_modules=[mlm_transformer, splade_pooling]) model = SparseEncoder(modules=[router]) Datensatz laden full_dataset = load_dataset("sentence-transformers/natural-questions", split="train").select(range(100_000)) dataset_dict = full_dataset.train_test_split(test_size=1_000, seed=12) train_dataset = dataset_dict["train"] eval_dataset = dataset_dict["test"] Verlustfunktion definieren loss = SpladeLoss(model=model, loss=SparseMultipleNegativesRankingLoss(model=model), query_regularizer_weight=0, document_regularizer_weight=3e-3) Trainingsparameter definieren args = SparseEncoderTrainingArguments( output_dir="models/inference-free-splade-distilbert-base-uncased-nq", num_train_epochs=1, per_device_train_batch_size=16, per_device_eval_batch_size=16, learning_rate=2e-5, learning_rate_mapping={r"SparseStaticEmbedding.weight": 1e-3}, warmup_ratio=0.1, fp16=True, batch_sampler=models.BatchSamplers.NO_DUPLICATES, eval_strategy="steps", eval_steps=1000, save_strategy="steps", save_steps=1000, save_total_limit=2, logging_steps=200, run_name="inference-free-splade-distilbert-base-uncased-nq", ) Evaluator initialisieren dev_evaluator = SparseNanoBEIREvaluator() Trainer initialisieren und Training starten trainer = SparseEncoderTrainer(model=model, args=args, train_dataset=train_dataset, eval_dataset=eval_dataset, loss=loss, evaluator=dev_evaluator) trainer.train() Modell nach dem Training erneut evaluiert dev_evaluator(model) Trainiertes Modell speichern model.save_pretrained("models/inference-free-splade-distilbert-base-uncased-nq/final") Modell auf den Hugging Face Hub hochladen model.push_to_hub(args.run_name) ``` Bewertung durch Branchenkenner Dünnbesetzte Embedding-Modelle finden zunehmend Anwendung in Suchszenarien, da sie eine Balance zwischen Effizienz und Leistung bieten. Branchenkenner loben ihre Fähigkeit, semantisch ähnlichen Inhalt zu erkennen und dabei den Speicherverbrauch und die Rechenzeit zu minimieren. Unternehmen wie Hugging Face bieten umfangreiche Sammlungen vortrainierter Modelle an, die die Anpassung und Verwendung von dünnbesetzten Modellen erleichtern.

Related Links