Notizia
Modelli
Prodotti
keyboard_arrow_down
Lettore
Leggi gli URL e cerca sul web per ottenere LLM più approfonditi.
Incorporamenti
Incorporamenti multilingue multimodali di livello mondiale.
Riclassificazione
Recupero neurale di livello mondiale per massimizzare la pertinenza della ricerca.
Ricerca profonda
Cerca, leggi e ragiona finché non trovi la risposta migliore.
Di più
keyboard_arrow_down
Classificatore
Classificazione zero-shot e few-shot per immagini e testo.
Segmentatore
Tagliare il testo lungo in blocchi ed effettuare la tokenizzazione.

Documentazione API
Generazione automatica di codice per il tuo IDE o LLM di Copilot
open_in_new


Azienda
keyboard_arrow_down
Chi siamo
Contatta le vendite
Programma di stagista
Unisciti a noi
open_in_new
Scarica il logo
open_in_new
Termini & Condizioni


Login
login
Caso Studio
Perché Scalare il Calcolo in Fase di Test per i Modelli di Embedding?
Conclusione
Blog tecnico
dicembre 12, 2024

Scalare il Calcolo di Test-Time per i Modelli di Embedding

I risultati migliori si ottengono con più potenza di calcolo—più per l'apprendimento, più per la ricerca. Un buon modello pre-addestrato ti porta lontano, ma la potenza di calcolo in fase di test ti porta ancora più lontano. È importante riconoscere questo nuovo paradigma di scaling della potenza di calcolo in fase di test, anche per i modelli di embedding.
Han Xiao
Han Xiao • 11 minuti letti

Dal rilascio del modello O1 di OpenAI, uno dei temi più discussi nella comunità AI è stato lo scaling test-time compute. Questo si riferisce all'allocazione di risorse computazionali aggiuntive durante l'inferenza—la fase in cui un modello AI genera output in risposta agli input—piuttosto che durante il pre-addestramento. Un esempio ben noto è il ragionamento multi-step "chain of thought", che permette ai modelli di eseguire deliberazioni interne più estese, come valutare multiple risposte potenziali, pianificazione più approfondita, auto-riflessione prima di arrivare a una risposta finale. Questa strategia migliora la qualità delle risposte, in particolare nei compiti di ragionamento complesso. Il modello QwQ-32B-Preview recentemente rilasciato da Alibaba segue questa tendenza di migliorare il ragionamento AI attraverso l'aumento del test-time compute.

💡
In questo contesto, "scaling" significa principalmente aumentare la capacità computazionale (come potenza di elaborazione o tempo) disponibile durante l'inferenza. Non si riferisce allo scaling out (distribuire i compiti su più sistemi) o al raggiungimento di uno speedup (riduzione del tempo di elaborazione).
0:00
/0:10

Quando si utilizza il modello O1 di OpenAI, gli utenti possono notare chiaramente che l'inferenza multi-step richiede tempo aggiuntivo mentre il modello costruisce catene di ragionamento per risolvere i problemi.

A Jina AI, ci concentriamo più sugli embedding e i reranker che sui LLM, quindi per noi è naturale considerare lo scaling test-time compute in questo contesto: Come può essere applicato il "chain-of-thought" ai modelli di embedding? Anche se potrebbe non sembrare intuitivo all'inizio, questo articolo esplora una prospettiva innovativa e dimostra come lo scaling test-time compute può essere applicato a jina-clip per classificare immagini fuori distribuzione (OOD)—risolvendo compiti che altrimenti sarebbero impossibili.

Il nostro esperimento si è concentrato sul riconoscimento dei Pokemon, che presenta una sfida interessante per i modelli di embedding. Mentre i modelli tipo CLIP eccellono nel matching generale tra immagini e testo, potrebbero avere difficoltà con domini di nicchia o immagini OOD senza fine-tuning. Dando ai modelli più tempo per "pensare", abbiamo scoperto che la classificazione multi-target—analoga a una "chain of thought"—potrebbe migliorare l'accuratezza senza alcun tuning del modello di embedding stesso.

tagCaso Studio

Google Colab

Il nostro esperimento si è concentrato sulla classificazione dei Pokemon utilizzando il dataset TheFusion21/PokemonCards, che contiene migliaia di immagini di carte Pokemon. Il compito è la classificazione delle immagini dove l'input è l'artwork ritagliato di una carta Pokemon (con tutti i testi/descrizioni rimossi) e l'output è il nome corretto del Pokemon da un insieme predefinito di nomi. Questo compito presenta una sfida particolarmente interessante per i modelli di embedding CLIP perché:

  • I nomi e gli elementi visivi dei Pokemon rappresentano concetti di nicchia, fuori distribuzione per il modello, rendendo difficile la classificazione diretta
  • Ogni Pokemon ha caratteristiche visive chiare che possono essere decomposte in elementi base (forme, colori, pose) che CLIP potrebbe comprendere meglio
  • L'artwork delle carte fornisce un formato visivo consistente introducendo allo stesso tempo complessità attraverso sfondi, pose e stili artistici variabili
  • Il compito richiede l'integrazione simultanea di multiple caratteristiche visive, simile alle catene di ragionamento complesse nei modelli linguistici
Ritagliamo le immagini delle carte Pokemon per rimuovere tutte le informazioni testuali (intestazione, piè di pagina, descrizione) per evitare ipotesi banali dovute alla presenza dei nomi dei Pokemon in quei testi. Le etichette di classe di questi Pokemon sono [Absol G, Aerodactyl, Weedle, Caterpie, Azumarill, Bulbasaur, Venusaur, Absol, Aggron, Beedrill δ, Alakazam, Ampharos, Dratini, Ampharos, Ampharos, Arcanine, Blaine's Moltres, Aerodactyl, Celebi & Venusaur-GX, Caterpie]

tagBaseline

L'approccio baseline utilizza un semplice confronto diretto tra le illustrazioni delle carte Pokemon e i nomi. Prima, ritagliamo ogni immagine della carta Pokemon per rimuovere tutte le informazioni testuali (intestazione, piè di pagina, descrizione) per evitare che il modello CLIP faccia ipotesi banali basate sui nomi Pokemon che appaiono in quei testi. Poi codifichiamo sia le immagini ritagliate che i nomi Pokemon usando i modelli jina-clip-v1 e jina-clip-v2 per ottenere i rispettivi embedding. La classificazione viene effettuata calcolando la similarità del coseno tra questi embedding di immagini e testo - ogni immagine viene abbinata al nome che ha il punteggio di similarità più alto. Questo crea una corrispondenza uno a uno diretta tra l'illustrazione della carta e i nomi dei Pokémon, senza alcun contesto o informazione aggiuntiva sugli attributi. Lo pseudo-codice qui sotto riassume il metodo baseline.

# Preprocessing
cropped_images = [crop_artwork(img) for img in pokemon_cards]  # Remove text, keep only art
pokemon_names = ["Absol", "Aerodactyl", ...]  # Raw Pokemon names

# Get embeddings using jina-clip-v1
image_embeddings = model.encode_image(cropped_images)
text_embeddings = model.encode_text(pokemon_names)

# Classification by cosine similarity
similarities = cosine_similarity(image_embeddings, text_embeddings)
predicted_names = [pokemon_names[argmax(sim)] for sim in similarities]

# Evaluate
accuracy = mean(predicted_names == ground_truth_names)

tag"Chain of Thoughts" per la Classificazione

Invece di abbinare direttamente immagini a nomi, decomponiamo il riconoscimento dei Pokemon in un sistema strutturato di attributi visivi. Definiamo cinque gruppi chiave di attributi: colore dominante (es. "bianco", "blu"), forma primaria (es. "un lupo", "un rettile alato"), caratteristica principale (es. "un singolo corno bianco", "grandi ali"), forma del corpo (es. "simile a un lupo su quattro zampe", "alato e snello"), e scena di sfondo (es. "spazio esterno", "foresta verde").

Per ogni gruppo di attributi, creiamo prompt di testo specifici (es. "Questo Pokémon ha il corpo principalmente di colore {}") abbinati a opzioni pertinenti. Quindi usiamo il modello per calcolare i punteggi di similarità tra l'immagine e ciascuna opzione di attributo. Questi punteggi vengono convertiti in probabilità usando softmax per ottenere una misura più calibrata della confidenza.

La struttura completa Chain of Thought (CoT) consiste in due parti: classification_groups che descrive gruppi di prompt, e pokemon_rules che definisce quali opzioni di attributi dovrebbe corrispondere ogni Pokemon. Per esempio, Absol dovrebbe corrispondere a "bianco" per il colore e "simile a un lupo" per la forma. Il CoT completo è mostrato qui sotto (spiegheremo più avanti come viene costruito):

pokemon_system = {
    "classification_cot": {
        "dominant_color": {
            "prompt": "This Pokémon's body is mainly {} in color.",
            "options": [
                "white",    # Absol, Absol G
                "gray",     # Aggron
                "brown",    # Aerodactyl, Weedle, Beedrill δ
                "blue",     # Azumarill
                "green",    # Bulbasaur, Venusaur, Celebi&Venu, Caterpie
                "yellow",   # Alakazam, Ampharos
                "red",      # Blaine's Moltres
                "orange",   # Arcanine
                "light blue"# Dratini
            ]
        },
        "primary_form": {
            "prompt": "It looks like {}.",
            "options": [
                "a wolf",         # Absol, Absol G
                "an armored dinosaur",  # Aggron
                "a winged reptile",     # Aerodactyl
                "a rabbit-like creature", # Azumarill
                "a toad-like creature",   # Bulbasaur, Venusaur, Celebi&Venu
                "a caterpillar larva",    # Weedle, Caterpie
                "a wasp-like insect",     # Beedrill δ
                "a fox-like humanoid",     # Alakazam
                "a sheep-like biped",      # Ampharos
                "a dog-like beast",        # Arcanine
                "a flaming bird",          # Blaine's Moltres
                "a serpentine dragon"      # Dratini
            ]
        },
        "key_trait": {
            "prompt": "Its most notable feature is {}.",
            "options": [
                "a single white horn", # Absol, Absol G
                "metal armor plates",  # Aggron
                "large wings",         # Aerodactyl, Beedrill δ
                "rabbit ears",         # Azumarill
                "a green plant bulb",  # Bulbasaur, Venusaur, Celebi&Venu
                "a small red spike",   # Weedle
                "big green eyes",      # Caterpie
                "a mustache and spoons", # Alakazam
                "a glowing tail orb",  # Ampharos
                "a fiery mane",        # Arcanine
                "flaming wings",       # Blaine's Moltres
                "a tiny white horn on head" # Dratini
            ]
        },
        "body_shape": {
            "prompt": "The body shape can be described as {}.",
            "options": [
                "wolf-like on four legs",   # Absol, Absol G
                "bulky and armored",        # Aggron
                "winged and slender",       # Aerodactyl, Beedrill δ
                "round and plump",          # Azumarill
                "sturdy and four-legged",   # Bulbasaur, Venusaur, Celebi&Venu
                "long and worm-like",       # Weedle, Caterpie
                "upright and humanoid",     # Alakazam, Ampharos
                "furry and canine",         # Arcanine
                "bird-like with flames",    # Blaine's Moltres
                "serpentine"                # Dratini
            ]
        },
        "background_scene": {
            "prompt": "The background looks like {}.",
            "options": [
                "outer space",      # Absol G, Beedrill δ
                "green forest",     # Azumarill, Bulbasaur, Venusaur, Weedle, Caterpie, Celebi&Venu
                "a rocky battlefield", # Absol, Aggron, Aerodactyl
                "a purple psychic room", # Alakazam
                "a sunny field",     # Ampharos
                "volcanic ground",   # Arcanine
                "a red sky with embers", # Blaine's Moltres
                "a calm blue lake"   # Dratini
            ]
        }
    },
    
    "pokemon_rules": {
        "Absol": {
            "dominant_color": 0,      
            "primary_form": 0,   
            "key_trait": 0,      
            "body_shape": 0,    
            "background_scene": 2   
        },
        "Absol G": {
            "dominant_color": 0,      
            "primary_form": 0,   
            "key_trait": 0,       
            "body_shape": 0,     
            "background_scene": 0    
        },
        // ...
    }
}

La classificazione finale combina queste probabilità di attributi - invece di un singolo confronto di similarità, ora stiamo facendo molteplici confronti strutturati e aggregando le loro probabilità per prendere una decisione più informata.

# Classification process
def classify_pokemon(image):
   # Generate all text prompts
   all_prompts = []
   for group in classification_cot:
       for option in group["options"]:
           prompt = group["prompt"].format(option)
           all_prompts.append(prompt)

   # Get embeddings and similarities
   image_embedding = model.encode_image(image)
   text_embeddings = model.encode_text(all_prompts)
   similarities = cosine_similarity(image_embedding, text_embeddings)

   # Convert to probabilities per attribute group
   probabilities = {}
   for group_name, group_sims in group_similarities:
       probabilities[group_name] = softmax(group_sims)

   # Score each Pokemon based on matching attributes
   scores = {}
   for pokemon, rules in pokemon_rules.items():
       score = 0
       for group, target_idx in rules.items():
           score += probabilities[group][target_idx]
       scores[pokemon] = score

   return max(scores, key=scores.get)

tagAnalisi della Complessità

Supponiamo di voler classificare un'immagine in uno di N nomi di Pokémon. L'approccio baseline richiede di calcolare N embedding di testo (uno per ogni nome di Pokémon). Al contrario, il nostro approccio di calcolo scalato in fase di test richiede di calcolare Q embedding di testo, dove

Q è il numero totale di combinazioni domanda-opzione per tutte le domande. Entrambi i metodi richiedono il calcolo di un embedding dell'immagine e l'esecuzione di un passaggio finale di classificazione, quindi escludiamo queste operazioni comuni dal nostro confronto. In questo caso di studio, il nostro N=13 e Q=52.

In un caso estremo dove Q = N, il nostro approccio si ridurrebbe essenzialmente al baseline. Tuttavia, la chiave per scalare efficacemente il calcolo in fase di test è:

  • Costruire domande attentamente scelte che aumentino Q
  • Assicurarsi che ogni domanda fornisca indizi distinti e informativi sulla risposta finale
  • Progettare domande il più possibile ortogonali per massimizzare il loro guadagno informativo congiunto.

Questo approccio è analogo al gioco "Venti Domande", dove ogni domanda viene scelta strategicamente per restringere efficacemente le possibili risposte.

tagValutazione

La nostra valutazione è stata condotta su 117 immagini di test che coprono 13 diverse classi di Pokémon. E il risultato è il seguente:

Approach jina-clip-v1 jina-clip-v2
Baseline 31.36% 16.10%
CoT 46.61% 38.14%
Improvement +15.25% +22.04%

Si può notare che la stessa classificazione CoT offre miglioramenti significativi per entrambi i modelli (+15,25% e +22,04% rispettivamente) su questo compito non comune o OOD. Questo suggerisce anche che una volta costruito il pokemon_system, lo stesso sistema CoT può essere efficacemente trasferito tra diversi modelli; e non è richiesto alcun fine-tuning o post-training.

È degna di nota la performance baseline relativamente forte di v1 (31,36%) sulla classificazione dei Pokemon. Questo modello è stato addestrato su LAION-400M, che includeva contenuti relativi ai Pokemon. Al contrario, v2 è stato addestrato su DFN-2B (sottocampionando 400M istanze), un dataset di qualità superiore ma più filtrato che potrebbe aver escluso contenuti relativi ai Pokemon, spiegando la performance baseline inferiore di V2 (16,10%) su questo compito specifico.

tagCostruire pokemon_system Efficacemente

L'efficacia del nostro approccio di calcolo scalato in fase di test dipende fortemente da quanto bene costruiamo il pokemon_system. Ci sono diversi approcci per costruire questo sistema, dal manuale al completamente automatizzato.

Costruzione Manuale

L'approccio più diretto è analizzare manualmente il dataset Pokemon e creare gruppi di attributi, prompt e regole. Un esperto del dominio dovrebbe identificare gli attributi visivi chiave come colore, forma e caratteristiche distintive. Dovrebbe poi scrivere prompt in linguaggio naturale per ogni attributo, enumerare le possibili opzioni per ogni gruppo di attributi e mappare ogni Pokemon alle sue corrette opzioni di attributi. Mentre questo fornisce regole di alta qualità, richiede molto tempo e non scala bene con N più grandi.

Costruzione Assistita da LLM

Possiamo sfruttare gli LLM per accelerare questo processo sollecitandoli a generare il sistema di classificazione. Un prompt ben strutturato richiederebbe gruppi di attributi basati su caratteristiche visive, template di prompt in linguaggio naturale, opzioni complete e mutualmente esclusive e regole di mappatura per ogni Pokemon. L'LLM può generare rapidamente una prima bozza, anche se il suo output potrebbe necessitare di verifica.

I need help creating a structured system for Pokemon classification. For each Pokemon in this list: [Absol, Aerodactyl, Weedle, Caterpie, Azumarill, ...], create a classification system with:

1. Classification groups that cover these visual attributes:
   - Dominant color of the Pokemon
   - What type of creature it appears to be (primary form)
   - Its most distinctive visual feature
   - Overall body shape
   - What kind of background/environment it's typically shown in

2. For each group:
   - Create a natural language prompt template using "{}" for the option
   - List all possible options that could apply to these Pokemon
   - Make sure options are mutually exclusive and comprehensive

3. Create rules that map each Pokemon to exactly one option per attribute group, using indices to reference the options

Please output this as a Python dictionary with two main components:
- "classification_groups": containing prompts and options for each attribute
- "pokemon_rules": mapping each Pokemon to its correct attribute indices

Example format:
{
    "classification_groups": {
        "dominant_color": {
            "prompt": "This Pokemon's body is mainly {} in color",
            "options": ["white", "gray", ...]
        },
        ...
    },
    "pokemon_rules": {
        "Absol": {
            "dominant_color": 0,  # index for "white"
            ...
        },
        ...
    }
}

Un approccio più robusto combina la generazione LLM con la validazione umana. Prima, l'LLM genera un sistema iniziale. Poi, gli esperti umani rivedono e correggono i raggruppamenti degli attributi, la completezza delle opzioni e l'accuratezza delle regole. L'LLM perfeziona il sistema in base a questo feedback, e il processo si ripete fino al raggiungimento di una qualità soddisfacente. Questo approccio bilancia efficienza e accuratezza.

Costruzione Automatizzata con DSPy

Per un approccio completamente automatizzato, possiamo usare DSPy per ottimizzare iterativamente il pokemon_system. Il processo inizia con un semplice pokemon_system scritto manualmente o da LLM come prompt iniziale. Ogni versione viene valutata su un set di validazione, usando l'accuratezza come segnale di feedback per DSPy. Basandosi su questa performance, vengono generati prompt ottimizzati (cioè nuove versioni di pokemon_system). Questo ciclo si ripete fino alla convergenza, e durante l'intero processo, il modello di embedding rimane completamente fisso.

Uso di DSPy per trovare il miglior design CoT di pokemon_system; il processo di tuning deve essere fatto solo una volta per ogni task.

tagPerché Scalare il Calcolo in Fase di Test per i Modelli di Embedding?

Perché scalare il pre-training diventa alla fine economicamente intrattabile.

Dalla release della suite di embedding Jina—inclusi jina-embeddings-v1, v2, v3, jina-clip-v1, v2, e jina-ColBERT-v1, v2—ogni aggiornamento del modello attraverso il pre-training scalato è arrivato con costi maggiori. Per esempio, il nostro primo modello, jina-embeddings-v1, rilasciato a giugno 2023 con 110M parametri. Addestrarlo all'epoca costava tra 5.000e5.000 e 5.000e10.000 a seconda di come si misura. Con jina-embeddings-v3, i miglioramenti sono significativi, ma derivano principalmente dalle maggiori risorse investite. La traiettoria dei costi per i modelli di frontiera è passata da migliaia a decine di migliaia di dollari e, per le aziende AI più grandi, anche centinaia di milioni oggi. Mentre investire più soldi, risorse e dati nel pre-training produce modelli migliori, i rendimenti marginali rendono alla fine insostenibile economicamente un'ulteriore scalabilità.

Legge di scala dei modelli di embedding. La performance media MTEB sui task in inglese è tracciata contro il numero di parametri del modello. Ogni punto rappresenta un modello di embedding. La linea di tendenza, che rappresenta tutti i modelli, è evidenziata, con i modelli multilingue in punti ciano. Questo grafico è stato creato selezionando i primi 100 modelli di embedding dalla classifica MTEB, escludendo quelli senza informazioni sulla dimensione, tipicamente modelli closed-source o proprietari. Sono state anche filtrate le sottomissioni identificate come trolling evidente.

D'altra parte, i moderni modelli di embedding stanno diventando sempre più potenti: multilingue, multitask, multimodali e capaci di forte performance zero-shot e di seguire istruzioni. Questa versatilità lascia ampio spazio per miglioramenti algoritmici e scaling del calcolo in fase di test.

La domanda diventa quindi: qual è il costo che gli utenti sono disposti a pagare per una query che gli sta particolarmente a cuore? Se tollerare tempi di inferenza più lunghi per modelli pre-addestrati fissi migliora significativamente la qualità dei risultati, molti lo troverebbero utile. Dal nostro punto di vista, c'è un notevole potenziale non sfruttato nello scaling del calcolo in fase di test per i modelli di embedding. Questo rappresenta un cambiamento dal semplice aumento della dimensione del modello durante l'addestramento all'aumento dello sforzo computazionale durante la fase di inferenza per ottenere prestazioni migliori.

tagConclusione

Il nostro caso di studio sul calcolo in fase di test di jina-clip-v1/v2 mostra diversi risultati chiave:

  1. Abbiamo ottenuto prestazioni migliori su dati non comuni o out-of-distribution (OOD) senza alcun fine-tuning o post-training sugli embedding.
  2. Il sistema ha fatto distinzioni più sfumate raffinando iterativamente le ricerche di similarità e i criteri di classificazione.
  3. Incorporando aggiustamenti dinamici dei prompt e ragionamento iterativo, abbiamo trasformato il processo di inferenza del modello di embedding da una singola query in una catena di pensiero più sofisticata.

Questo caso di studio tocca appena la superficie di ciò che è possibile con il calcolo in fase di test. Rimane ampio spazio per lo scaling algoritmico. Per esempio, potremmo sviluppare metodi per selezionare iterativamente le domande che restringono più efficientemente lo spazio delle risposte, similmente alla strategia ottimale nel gioco "Venti Domande". Scalando il calcolo in fase di test, possiamo spingere i modelli di embedding oltre i loro attuali limiti e permettere loro di affrontare compiti più complessi e sfumati che una volta sembravano fuori portata.

Categorie:
Blog tecnico
rss_feed
Uffici
location_on
Sunnyvale, California
710 Lakeway Dr, Ste 200, Sunnyvale, CA 94085, Stati Uniti
location_on
Berlino, Germania (sede centrale)
Prinzessinnenstraße 19-20, 10969 Berlino, Germania
location_on
Pechino, Cina
Livello 5, Edificio 6, No.48 Haidian West St. Pechino, Cina
location_on
Shenzen, Cina
402 Piano 4, Fu'an Technology Building, Shenzhen, Cina
Fondazione di ricerca
Lettore
Incorporamenti
Riclassificazione
Ricerca profonda
Classificatore
Segmentatore
Documentazione API
Ottieni la chiave API Jina
Limite di velocità
Stato dell'API
Azienda
Chi siamo
Contatta le vendite
Sala stampa
Programma di stagista
Unisciti a noi
open_in_new
Scarica il logo
open_in_new
Termini
Sicurezza
Termini & Condizioni
Privacy
Gestisci i cookie
email
Jina AI © 2020-2025.