Vai al contenuto

Configurazione e route dell'addestramento di modelli

Ogni chiave del blocco model_training, come le esecuzioni vengono messe in coda, valutate e archiviate, e le route di amministrazione e agent, con rimedi agli errori più comuni.

Novità nella v2.14.0

Questa pagina è il riferimento per il blocco model_training di una configurazione di Potato e per ciò che accade a un'esecuzione dopo che l'hai avviata. La pagina è scritta per chi gestisce uno studio e vuole limitare le esecuzioni, inviarle a un'altra macchina, mostrare agli annotatori le predizioni di un modello o avviare l'addestramento da uno script. Ogni chiave, valore predefinito, route e messaggio qui sotto è stato verificato rispetto al codice di Potato. Per una prima esecuzione, inizia da Addestra il tuo primo modello. I trainer e i loro parametri sono elencati in Trainer.

Una configurazione completa

La configurazione seguente addestra un classificatore di sentiment su recensioni di prodotti. auto_retrain riadatta sklearn-text dopo ogni 25 nuove annotazioni. Con le feature TF-IDF predefinite, sklearn-text si addestra sulla CPU e non richiede nulla oltre a una normale installazione di Potato. Le esecuzioni automatiche frequenti costano quindi poco. Il write-back mostra agli annotatori ogni predizione con una confidenza di almeno 0.8. Con include_unlabeled, un'esecuzione predice anche sulle recensioni che nessuno ha ancora etichettato. I valori predefiniti di hf-text-classification e il backend gpu-server servono le esecuzioni avviate a mano dalla pagina Training:

yaml
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
  - "data/reviews.json"
item_properties:
  id_key: "id"
  text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels: ["positive", "negative"]
 
model_training:
  enabled: true
  split_seed: 0
  splits: {train: 0.7, val: 0.15, test: 0.15}
  aggregation: consensus
  retain_runs: 5
  queue_max: 10
  max_wall_seconds: 3600
  max_ram_mb: 8192
  num_threads: 4
  trainer_params:
    sklearn-text:
      classifier: sklearn.linear_model.LogisticRegression
      classifier_kwargs: {max_iter: 1000}
    hf-text-classification:
      model_name: answerdotai/ModernBERT-base
      epochs: 4
      lora: true
  auto_retrain:
    enabled: true
    trainer: sklearn-text
    schemas: [sentiment]
    min_interval_s: 600
    update_frequency: 25
  writeback:
    schemas: [sentiment]
    min_confidence: 0.8
    include_unlabeled: true
  backends:
    gpu-server:
      type: ssh
      host: gpu-server
      python: /opt/conda/bin/python3
      gpus: auto
      min_free_gpu_mb: 4000

Mantieni fisso split_seed per tutta la vita dello studio. Un nuovo seme riassegna ogni item, quindi gli item che erano esclusi dall'addestramento finiscono nell'addestramento e i punteggi successivi non sono più confrontabili con quelli precedenti. La soglia min_confidence di 0.8 è un punto di partenza, e la soglia giusta dipende dal primo punteggio held-out. Attiva include_unlabeled quando quel punteggio giustifica la visualizzazione delle pre-etichette, perché le pre-etichette ancorano gli annotatori alla risposta del modello.

Chiavi di model_training

Ogni chiave sta sotto model_training:

ChiavePredefinitoSignificato
enabledfalseRegistra la pagina Training, le route sotto /admin/training e le route degli agent sotto /api/training. Senza enabled: true le route non esistono.
retain_runs5Esecuzioni concluse conservate nel registro delle esecuzioni. Un'esecuzione più vecchia esce dal registro a meno che le sue predizioni siano ancora archiviate. Le directory delle esecuzioni restano su disco.
grace_seconds20Secondi concessi a un'esecuzione annullata per terminare prima che Potato uccida il processo. 0 o più, e inviato con il job ai backend di tipo ssh, slurm e agent.
queue_max10Esecuzioni che possono attendere dietro quella in corso.
split_seed0Seme per assegnare gli item alle partizioni train, val e test.
splits{train: 0.7, val: 0.15, test: 0.15}Frazioni delle partizioni, normalizzate in modo che la somma sia 1. I nomi sono train, val e test, e train è obbligatorio.
aggregationconsensusCome le etichette di più annotatori su un item diventano un'unica etichetta. consensus adatta il modello di Dawid-Skene quando lo studio ha più di un annotatore e ripiega sul voto di maggioranza se l'adattamento fallisce. majority prende il voto di maggioranza.
max_wall_secondsnon impostatoLimite di tempo per un'esecuzione. Potato controlla un'esecuzione locale a ogni evento che riporta, e un'esecuzione ssh o agent ogni secondo.
max_ram_mbnon impostatoLimite di spazio di indirizzamento per il processo di addestramento, impostato con setrlimit. Su una piattaforma senza il limite, l'esecuzione registra un avviso e continua.
deviceautoauto, cpu, cuda, cuda:N o mps. auto sceglie CUDA, poi Metal di Apple, poi la CPU.
num_threadsnon impostatoImposta OMP_NUM_THREADS, MKL_NUM_THREADS e OPENBLAS_NUM_THREADS per l'esecuzione, a meno che l'ambiente imposti già quelle variabili.
auto_retraindisattivatoRiaddestramento mentre arrivano le annotazioni. Vedi auto_retrain.
writebacknessunoPubblicazione delle predizioni come pre-etichette. Vedi writeback.
backendlocalIl backend per le esecuzioni che non ne indicano un altro.
backendsnessunoBackend ssh, slurm e agent con nome. Vedi Backend.
max_predictions_mb512Dimensione massima di predictions.jsonl che un agent remoto può caricare.
trainer_paramsnessunoValori predefiniti dei parametri, per nome del trainer.
tilingenabled: autoSuddivisione delle immagini grandi in tile per i trainer di rilevamento e segmentazione. Vedi tiling.

I params propri di un'esecuzione prevalgono su trainer_params, che prevale sui valori predefiniti del trainer. Un nome di parametro che il trainer non accetta viene rifiutato all'avvio del server quando il nome sta sotto trainer_params, e all'avvio dell'esecuzione negli altri casi. Trainer mostra l'ordine con un esempio.

auto_retrain

Il riaddestramento automatico controlla se serve una nuova esecuzione dopo ogni salvataggio di un'annotazione:

ChiavePredefinitoSignificato
enabledfalseAttiva il controllo.
trainernessunoNome del trainer. Obbligatorio.
schemasnessunoSchemi da addestrare. Obbligatorio.
min_interval_s600Secondi dalla fine dell'ultima esecuzione prima che ne parta un'altra.
update_frequency25Nuove annotazioni dall'ultima esecuzione automatica prima che ne parta un'altra.
params{}Parametri del trainer, come i params di un'esecuzione via API.
backendmodel_training.backendBackend per le esecuzioni automatiche.
accept_licencefalseConferma la licenza di un trainer che chiede conferma (ultralytics-detect, ultralytics-segment, layoutlmv3). Senza la conferma, le esecuzioni automatiche di quei trainer vengono saltate.

Quando un controllo decide contro un'esecuzione, il motivo compare nel campo skip_reason di GET /admin/training/api/status, per esempio "waiting for 3 more annotation(s)" o "a run is already in progress". Le esecuzioni automatiche non entrano mai nella coda delle esecuzioni. La prossima annotazione salvata dopo che la coda si è svuotata controlla di nuovo, con più annotazioni su cui addestrare. Potato tiene in memoria i conteggi delle annotazioni, quindi dopo un riavvio un progetto che si è già addestrato conta le nuove annotazioni a partire dal riavvio.

writeback

Il write-back decide quali predizioni vedono gli annotatori:

ChiavePredefinitoSignificato
schemas[]Schemi le cui predizioni vedono gli annotatori. Un elenco vuoto non ne mostra nessuna.
min_confidence0.0Le predizioni sotto la soglia vengono salvate e non mostrate. Una predizione senza confidenza passa.
fieldpredictionsCampo dell'item in cui vengono scritte le pre-etichette.
include_unlabeledfalsePredice anche sugli item che nessuno ha etichettato e pre-etichetta quegli item. Senza include_unlabeled, un'esecuzione predice solo sugli item val e test dell'esecuzione stessa.

tiling

I trainer di rilevamento e segmentazione ridimensionano ogni immagine a poche centinaia di pixel. A quella dimensione gli oggetti di un'immagine di vetrino intero o di una scena satellitare vanno persi. Per uno schema image_annotation, microscopy o geo_annotation, Potato taglia quindi ogni immagine grande in tile quando vengono costruiti i dati di addestramento dell'esecuzione. La partizione di un'immagine viene decisa prima che l'immagine sia tagliata, quindi i tile di uno stesso vetrino non finiscono mai in due partizioni. Le predizioni vengono rimappate sull'immagine intera, e i punteggi held-out sono calcolati su immagini intere. Il tutorial sui modelli per la visione tratta vetrini e mappe nella pratica.

ChiavePredefinitoSignificato
enabledautoauto divide in tile i formati di vetrino (.svs, .ndpi, .mrxs, .scn e altri) e le immagini il cui lato più lungo è almeno auto_min_side. true divide ogni immagine e false nessuna.
auto_min_side4096Lunghezza del lato più lungo, in pixel, da cui auto inizia a dividere un'immagine in tile.
tile_size1024Lato di un tile, nei pixel che vede il trainer.
overlap128Pixel condivisi dai tile vicini, al massimo metà di tile_size. Tieni la sovrapposizione almeno grande quanto gli oggetti, altrimenti un oggetto grande viene trovato a pezzi.
downsample1Pixel a piena risoluzione per pixel di tile.
mppnessunoMicron per pixel di tile. Prevale su downsample per un vetrino che registra la propria risoluzione.
background0.25Tile vuoti campionati per ogni tile con un oggetto. Imposta background: 0 per i vetrini annotati solo in parte.
max_predict_tiles2000Massimo di tile predetti per immagine. Vengono tenuti i tile con più tessuto.
min_visible0.4Quota di un oggetto che deve stare dentro un tile perché l'oggetto si addestri lì.
tissue_threshold0.05Quota di un tile di vetrino che deve essere tessuto perché il modello predica sul tile.

I vetrini vengono letti con openslide, installato da pip install "potato-annotation[wsi]", sulla macchina che costruisce i dati di addestramento. Un backend remoto scarica i tile e mai il vetrino.

La coda delle esecuzioni

Viene eseguita una sola esecuzione alla volta. Un'esecuzione avviata dalla pagina Training o dall'API mentre un'altra è in corso attende invece di essere rifiutata. La richiesta di avvio restituisce 202 con queued: true e la position dell'esecuzione, e la tabella Runs elenca l'esecuzione come waiting #N con un pulsante Cancel run. Quando l'esecuzione in corso termina, parte la più vecchia tra quelle in attesa.

Le esecuzioni in attesa sono record nel registro delle esecuzioni, quindi la coda sopravvive a un riavvio, e la prima esecuzione in attesa parte quando il server torna. Un'esecuzione in cui il server precedente si trovava a metà viene marcata interrupted nello stesso momento. I dati di addestramento di un'esecuzione in attesa vengono costruiti quando l'esecuzione parte, quindi l'esecuzione si addestra sulle annotazioni presenti in quel momento. Un avvio che verrebbe rifiutato, come un avvio che indica uno schema sconosciuto, viene rifiutato subito e non quando arriva il turno dell'esecuzione. Un'esecuzione il cui schema o trainer è uscito dalla configurazione mentre attendeva fallisce con invalid_when_dequeued, e parte l'esecuzione successiva.

Invia "queue": false nel corpo della richiesta per ottenere 409 invece di un posto in coda. Con queue_max esecuzioni già in attesa, un nuovo avvio ottiene 429. GET /admin/training/api/status elenca in ordine le esecuzioni in attesa sotto queue.

Controlli prima di un'esecuzione

potato validate segnala insieme ogni problema del blocco model_training, e il server rifiuta di avviarsi per gli stessi problemi:

bash
potato validate config.yaml --strict

I controlli coprono questi casi:

  • splits con un nome diverso da train, val e test, una frazione sotto 0 o non numerica, frazioni la cui somma è 0, oppure senza train.
  • Una chiave che writeback o auto_retrain non ha, una voce di writeback.schemas che non è uno schema, oppure un min_confidence fuori dall'intervallo da 0 a 1. accept_license viene segnalato come errore di battitura di accept_licence.
  • Un blocco pre_annotation attivo il cui field è diverso da writeback.field. Sotto un blocco del genere non comparirebbe alcuna pre-etichetta di addestramento.
  • Con auto_retrain.enabled, un trainer o uno schema che non esiste, uno schema che il trainer non può imparare, parametri che il trainer non accetta o di tipo sbagliato, un backend assente da backends, oppure decision-calibrate su un backend diverso da local.
  • Un parametro sotto trainer_params che il trainer non accetta, o di tipo sbagliato. Dentro dp, il controllo riguarda anche ogni chiave e il suo intervallo.
  • Un grace_seconds inferiore a 0 o non numerico, oppure un retain_runs o split_seed inferiore a 0 o non intero.
  • Sotto backends, un type mancante o sconosciuto, una chiave che il tipo non ha, un backend ssh senza host, un valore di gpus diverso da auto, none o indici di GPU, un backend remoto chiamato local, oppure un model_training.backend non definito.

potato training check verifica un backend prima che un'esecuzione lo usi. Per local, il comando stampa il dispositivo che un'esecuzione userebbe, per esempio local: this machine, Apple Metal (mps) su un Mac con Apple silicon. Per un backend ssh, il comando riporta la versione di Python, ogni GPU con la sua memoria libera, la GPU che un'esecuzione otterrebbe e i pacchetti di addestramento che mancano all'interprete remoto. Il pulsante Check della pagina Training esegue la stessa verifica, e --json stampa il report come JSON:

bash
potato training check local config.yaml
potato training check gpu-server config.yaml

Un'esecuzione avviata dalla pagina Training o dall'API viene controllata di nuovo quando parte. I codici di stato sono elencati in Route.

Backend

Un'esecuzione gira su un backend, e il menu Runs on della pagina Training elenca i backend configurati. model_training.backend imposta il valore predefinito, e un'esecuzione via API o auto_retrain può indicare un backend diverso con backend. Potato ha quattro tipi di backend:

TipoDove gira il trainerChi avvia il trainer
localQuesta macchina, in un sottoprocesso. Sempre disponibile, ed è il valore predefinito.Potato
sshUn'altra macchina che Potato può raggiungere via ssh, come un server GPU.Potato, via ssh
slurmUn nodo di calcolo di un cluster, come job batch.Potato, con ssh al nodo di login e poi sbatch
agentUna macchina che Potato non può raggiungere, come una workstation dietro NAT.Una persona, con potato training agent

Un backend ssh usa l'autenticazione a chiave con BatchMode attivo, quindi una richiesta di password fallisce invece di restare in attesa. Un backend slurm usa solo sbatch, squeue e scancel, più scontrol sui cluster che forniscono scontrol, e richiede una remote_dir su uno storage condiviso dai nodi di calcolo. Un backend agent non richiede alcuna porta in ingresso, perché l'agent apre ogni connessione. Il nome local è riservato a questa macchina, e decision-calibrate gira solo su local. Addestrare su un server GPU, un cluster SLURM o una macchina dietro NAT percorre tutti e tre i tipi remoti con le loro chiavi.

Punteggi held-out

Ogni esecuzione valuta le proprie predizioni sugli item val e test rispetto alle etichette umane risolte. I nomi delle metriche portano la partizione, come in val_macro_f1 o test_f1. Un item con un'etichetta e senza predizione conta come sbagliato, quindi escludere gli item difficili non può alzare il punteggio di un trainer. <split>_coverage riporta la quota di item che hanno ricevuto una predizione.

Il punteggio principale compare nella colonna Held-out score della tabella Runs, con la partizione e la metrica nel tooltip. Il punteggio principale è la metrica principale del primo schema sulla prima tra val e test che ha item. Quando un trainer ha scelto il miglior checkpoint in base al punteggio val, Potato prova prima test, perché il trainer ha già visto il punteggio val. I trainer di fine-tuning che tengono l'epoca migliore, per esempio hf-text-classification, torchvision-detect e llm-sft, prendono il punteggio principale da test. sklearn-text, setfit, rdkit-property, i trainer di modelli decisionali e i bridge di inferenza non scelgono nulla su val, e un'esecuzione di uno di quei trainer prende il punteggio principale da val ogni volta che val ha item. Un'esecuzione senza item val o test viene mostrata come "not scored".

La metrica principale dipende dal tipo di annotazione dello schema, come mostra la tabella seguente per i tipi più comuni:

Tipo di annotazioneMetrica principale
radio, select, likertmacro-F1 (anche accuratezza ed errore assoluto medio per le etichette likert numeriche)
multiselectmicro-F1 (anche macro-F1 e corrispondenza esatta)
spanF1 sugli span che coincidono per inizio, fine ed etichetta
textF1 sui token (anche corrispondenza esatta)
pairwise in modalità binaryaccuratezza sugli item non risposti come parità
rankingtau di Kendall
image_annotation, microscopy, geo_annotationmAP COCO a IoU 0.5 (map_50), con map_50_95 registrata anch'essa
audio_annotationF1 sui segmenti con la stessa etichetta a IoU 0.5 o superiore
speech_transcriptword_accuracy, 1 meno il tasso di errore sulle parole
volume_annotationmean_dice

L'F1 sui token accredita una risposta che usa le parole giuste nell'ordine sbagliato, quindi leggi l'F1 sui token insieme alla corrispondenza esatta. La metrica principale del rilevamento usa IoU 0.5 e non la media da 0.5 a 0.95, perché i box di due annotatori per uno stesso oggetto raramente si sovrappongono a IoU 0.9. La tabella upstream dei punteggi held-out elenca le metriche di ogni tipo di annotazione.

Write-back

Dopo un'esecuzione riuscita, Potato salva le predizioni dell'esecuzione e scrive le predizioni che superano quattro controlli nel campo predictions di ogni item, o nel campo indicato da writeback.field. I controlli si svolgono in quest'ordine, e il report del write-back dell'esecuzione conta ogni esclusione:

  1. Gli item della partizione train non vengono mai pre-etichettati. Il controllo copre la partizione train di ogni esecuzione ancora nel registro, e una pre-etichetta lasciata su un item da un'esecuzione precedente viene tolta quando un'esecuzione successiva si addestra su quell'item.
  2. Vengono pubblicati solo gli schemi in writeback.schemas. L'elenco è vuoto per impostazione predefinita, quindi attivare l'addestramento non cambia nulla per gli annotatori.
  3. Le coppie rifiutate vengono saltate. Una coppia item-schema con un verdetto reject nella revisione del modello non viene più mostrata.
  4. Si applica la soglia di confidenza. Una predizione sotto min_confidence viene salvata e non pubblicata.

Il write-back non modifica mai un'etichetta umana, perché le predizioni vanno nei dati dell'item mentre le annotazioni stanno nello stato utente di ciascun annotatore. Una pre-etichetta compare come risposta precompilata che l'annotatore può modificare, per esempio una scelta come opzione selezionata e una risposta a testo libero nella casella di testo dello schema, e non serve alcun blocco pre_annotation. La pre-etichetta diventa la risposta dell'annotatore solo quando l'annotatore la modifica o passa oltre. Una pre-etichetta che nessuno ha modificato né superato non diventa quindi mai un'etichetta di addestramento. Una coppia annotatore-item che ai_support.holdout colloca nel gruppo di confronto senza assistenza dello studio non mostra alcuna pre-etichetta, e i dati dell'item inviati per quella coppia escludono sia writeback.field sia pre_annotation.field. Il report del write-back è il campo writeback di GET /admin/training/api/status, e il summary del report spiega perché un'esecuzione non ha pubblicato nulla.

Potato tiene una predizione per item e schema, e la predizione di un'esecuzione più recente sostituisce quella di un'esecuzione più vecchia. Quando la predizione più recente è salvata ma non mostrata, perché è sotto min_confidence, vuota o rifiutata, la pre-etichetta dell'esecuzione più vecchia viene tolta subito dall'item, e il report del write-back conta l'item in n_superseded_cleared. Le pre-etichette fornite con i dati restano intatte. All'avvio le predizioni salvate per gli schemi in writeback.schemas vengono riscritte nei dati degli item con gli stessi quattro controlli, quindi le pre-etichette sopravvivono a un riavvio. Per ritirare le pre-etichette di un'esecuzione, invia DELETE /admin/training/api/runs/<run_id>/predictions. La richiesta rimuove le predizioni salvate e toglie le pre-etichette dagli item.

Le correzioni e gli item fissati si addestrano sempre

Due tipi di item vanno nella partizione train di ogni esecuzione successiva, qualunque sia il posto dell'item nella partizione stabile:

  • Gli item corretti da un revisore. Un verdetto correct nella revisione del modello significa che una persona ha corretto la risposta del modello. Le correzioni vengono dagli item su cui il modello era peggiore, quindi un item corretto in val o test misurerebbe il modello su un campione dei suoi stessi errori. I verdetti accept e reject lasciano un item dove si trovava.
  • Gli item fissati. Train on these accanto a uno slice nella pagina Catalog fissa gli item che lo slice individua, per esempio lo slice predefinito model-found-nothing. Un item fissato si addestra una volta che qualcuno lo ha etichettato.

Un'esecuzione che ha spostato item esclusi dall'addestramento in train registra un avviso con il conteggio. Il punteggio held-out dell'esecuzione viene allora calcolato senza quegli item e non è direttamente confrontabile con il punteggio di un'esecuzione precedente. I conteggi si trovano in stats.forced_train nel manifest.json dei dati di addestramento.

Salvare una partizione come versione del dataset

Keep this split as a dataset nella pagina di un'esecuzione salva gli item val, test o train dell'esecuzione con le loro etichette umane concordate come nuova versione di un dataset. Una versione di un dataset non cambia più in seguito, quindi modelli e prompt LLM successivi possono essere confrontati esattamente su quegli item. La funzione richiede datasets.enabled: true. Ogni versione salvata contiene una sola partizione e riparte da zero invece di aggiungersi all'ultima versione del dataset. Gli item val dell'esecuzione 2 aggiunti a quelli dell'esecuzione 1 includerebbero altrimenti item su cui l'esecuzione 2 si è addestrata. Gli inputs di ogni esempio escludono il campo delle pre-etichette, quindi una valutazione non può leggere la risposta del modello.

Da dove viene una pre-etichetta

GET /admin/model-review include provenance per ogni item della coda di revisione la cui pre-etichetta è stata scritta da un'esecuzione di addestramento. Per ogni schema, la voce indica l'id dell'esecuzione, il trainer e il punteggio held-out dell'esecuzione. Le pre-etichette fornite con i dati non hanno una voce.

Dove vengono archiviate le esecuzioni

Ogni esecuzione ha una directory in <task_dir>/<output_annotation_dir>/training/runs/<run_id>/:

PercorsoContenuto
bundle/I dati di addestramento: train.jsonl, val.jsonl, test.jsonl, unlabeled.jsonl con include_unlabeled, labels.json, manifest.json e media/.
artifacts/model_card.json, predictions.jsonl e il modello, per esempio model.pkl per sklearn-text o una directory model/ per i trainer transformer.
spec.jsonCiò che è stato chiesto all'esecuzione.
events.jsonl, stdout.log, stderr.logGli eventi di avanzamento e l'output dell'esecuzione.
agent.logL'output proprio dell'agent remoto, sui backend ssh.
bundle.tar.gzI dati di addestramento come li ha scaricati l'agent, media inclusi, sui backend remoti.

Il registro delle esecuzioni risiede nel database del progetto, <task_dir>/project.sqlite, e registra le esecuzioni, la partizione di ogni item per esecuzione, gli item fissati per l'addestramento, le predizioni salvate, i token degli agent e i push su Hugging Face Hub. retain_runs pota il registro e non pota mai un'esecuzione le cui predizioni sono ancora archiviate, così ogni pre-etichetta può essere ricondotta all'esecuzione che l'ha scritta. La potatura lascia su disco le directory delle esecuzioni.

Un'esecuzione LoRA salva solo l'adattatore, da pochi a qualche centinaio di megabyte, e carica il modello di base indicato da model_name quando l'esecuzione predice. Un fine-tuning completo salva l'intero modello. Imposta la variabile d'ambiente POTATO_MODEL_CACHE su una directory, e il processo di addestramento usa quella directory per HF_HOME, TRANSFORMERS_CACHE e SENTENCE_TRANSFORMERS_HOME, a meno che quelle variabili siano già impostate. Su una macchina isolata dalla rete, metti in anticipo in quella directory i modelli che i trainer indicano.

Route

La pagina Training e le route JSON della pagina stanno sotto /admin/training e richiedono l'accesso da amministratore. L'accesso da amministratore significa una sessione da amministratore o l'header X-API-Key. Le richieste POST e DELETE da un browser devono essere della stessa origine. La specifica OpenAPI di Potato marca tutte le 26 operazioni di addestramento con x-potato-requires-config: model_training.enabled: true:

RouteScopo
GET /admin/trainingLa pagina Training, con il modulo di esecuzione, l'elenco delle esecuzioni e i trainer.
GET /admin/training/runs/<run_id>La pagina di una esecuzione, con stato, metriche, eventi e la partizione di ogni item.
GET /admin/training/api/trainersOgni trainer, con i tipi, le modalità, la licenza e lo stato di installazione del trainer.
GET /admin/training/api/schemasGli schemi dello studio, il tipo di ciascuno e i trainer adatti a ciascuno.
GET /admin/training/api/statusL'esecuzione corrente o l'ultima, con stato, avanzamento, metriche, avvisi, skip_reason, writeback e queue.
GET /admin/training/api/runsStorico delle esecuzioni. ?limit= vale 50 per impostazione predefinita, con un massimo di 500.
POST /admin/training/api/runsAvvia un'esecuzione. 200 quando l'esecuzione parte, e 202 con queued: true e position quando l'esecuzione attende.
GET /admin/training/api/runs/<run_id>Il record di una esecuzione, più review, la precisione delle predizioni dell'esecuzione rispetto ai verdetti di revisione.
GET /admin/training/api/runs/<run_id>/eventsIl log degli eventi dell'esecuzione. ?limit= vale 200 per impostazione predefinita.
POST /admin/training/api/runs/<run_id>/cancelAnnulla l'esecuzione in corso o una in attesa. 400 per qualsiasi altro id di esecuzione.
DELETE /admin/training/api/runs/<run_id>/predictionsRitira le predizioni salvate e le pre-etichette dell'esecuzione.
POST /admin/training/api/runs/<run_id>/push-to-hubPubblica il modello dell'esecuzione su Hugging Face Hub. Vedi Pubblicazione su Hugging Face Hub.
POST /admin/training/api/runs/<run_id>/pin-splitSalva una partizione come versione del dataset, con il corpo {"dataset": name, "split": "val"}.
GET /admin/training/api/backendsI backend configurati.
POST /admin/training/api/backends/<name>/checkVerifica un backend, come fa potato training check.
GET /admin/training/api/pinnedGli item fissati, raggruppati per motivo.
POST /admin/training/api/pinnedFissa degli item a train, con {"slice": name} o {"instance_ids": [...]}.
DELETE /admin/training/api/pinnedRimuove il fissaggio degli instance_ids elencati, o di ogni item fissato quando il corpo non ne elenca.

Una richiesta di esecuzione accetta trainer, schemas (un elenco o un solo nome), params, backend, accept_licence e queue. Ogni trainer adatta solo il primo schema indicato. La richiesta seguente avvia un'esecuzione sklearn-text sullo schema sentiment dell'esempio:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'

Un avvio rifiutato indica il motivo in error:

StatoQuando
400Nessun trainer o nessuno schema nel corpo, un trainer o uno schema sconosciuto, uno schema che il trainer non può imparare, un trainer che il progetto non può eseguire, oppure un trainer la cui licenza richiede conferma, con needs_licence_ack: true, finché la richiesta non imposta accept_licence: true
409Un parametro che il trainer non accetta o di tipo o intervallo sbagliato, un backend sconosciuto, decision-calibrate su un backend diverso da local, oppure un'esecuzione già in corso con "queue": false
429queue_max esecuzioni già in attesa

Protocollo degli agent

model_training.enabled registra anche le route che un agent di addestramento chiama, sotto /api/training. Un agent invia il proprio token come Authorization: Bearer <token>, e un token mancante o non valido ottiene 401. La registrazione di un backend richiede invece la chiave API dell'amministratore. potato/training/protocol.py descrive il protocollo per chi scrive un nuovo agent, e potato/training/agent.py è l'implementazione di riferimento:

RouteScopo
POST /api/training/backends/registerEmette un token dell'agent per il nome di un backend, con X-API-Key. potato training register chiama questa route.
POST /api/training/backends/<name>/heartbeatUn agent inattivo segnala di essere vivo. 403 per un token emesso per un altro backend.
GET /api/training/jobs/next?wait=30Long poll. 200 con un job, oppure 204 quando nessun job arriva entro wait secondi.
GET /api/training/jobs/<run_id>Il job, la specifica del job e se il job è stato annullato.
GET /api/training/jobs/<run_id>/bundleI dati di addestramento come tar.gz, media inclusi. La route risponde alle richieste Range, quindi un agent riprende un download interrotto, fino a cinque tentativi. 410 quando il bundle non esiste più.
POST /api/training/jobs/<run_id>/progressEventi di avanzamento. Un annullamento torna nella risposta.
POST /api/training/jobs/<run_id>/predictionspredictions.jsonl. 413 oltre max_predictions_mb.
POST /api/training/jobs/<run_id>/completeCodice di uscita ed eventi finali.

QLoRA

llm-sft, llm-dpo, hf-text-classification, vlm-sft e reward-model accettano lora: {quantize: 4bit}, l'impostazione di QLoRA (Dettmers et al., 2023). Il modello di base viene caricato con pesi NF4 a 4 bit e doppia quantizzazione, e sopra si addestra un adattatore LoRA in bf16 dove la GPU supporta bf16. quantize: 8bit è l'opzione intermedia, e le predizioni caricano il modello di base nello stesso modo.

yaml
model_training:
  trainer_params:
    llm-sft:
      model_name: Qwen/Qwen2.5-7B-Instruct
      lora: {quantize: 4bit}

A 4 bit i pesi di base occupano un quarto della memoria che gli stessi pesi occupano in bf16, e a questa si sommano attivazioni, adattatore e stato dell'ottimizzatore. Potato non ha ancora misurato la memoria di un'esecuzione QLoRA su una GPU, quindi pianifica a partire dalla riga "Peak GPU memory" dell'esecuzione stessa. Ogni esecuzione transformer registra quella riga alla fine. QLoRA richiede una GPU CUDA e una build di bitsandbytes per la CUDA di quella macchina. L'esecuzione controlla entrambe prima di caricare il modello, quantizzando alcuni numeri sulla GPU, e quando le due versioni non corrispondono, l'errore indica entrambe le versioni. Il tutorial sul fine-tuning di LLM mette QLoRA al lavoro su esecuzioni SFT e DPO.

Pubblicazione su Hugging Face Hub

Un'esecuzione riuscita il cui modello si trova sul server Potato ha Publish to the Hugging Face Hub nella propria pagina. Il push carica il modello e un README.md con la model card scritta a partire dall'esecuzione, che indica il trainer, il modello di base e l'adattatore, gli schemi e le etichette, le dimensioni delle partizioni, il punteggio held-out e la partizione su cui il punteggio è stato misurato, più gli id dell'esecuzione e del bundle. La card di un'esecuzione dp ha anche una riga "Differential privacy" con l'epsilon speso rispetto all'obiettivo, il delta e la partizione train che la garanzia copre. La riga omette l'obiettivo o il delta quando l'esecuzione non ha registrato il valore.

Il caricamento è un elenco fisso di file e non l'intera directory artifacts/. L'elenco contiene i file dei pesi, per esempio .safetensors, .bin, .pt e .pkl, i file di configurazione e del tokenizer nella directory model/ salvata, model_card.json con i percorsi locali sostituiti da nomi di file, e calibration.json. Le risposte del modello sugli item del progetto (predictions.jsonl, e raw_answers.jsonl per i modelli decisionali) restano sul server. Restano fuori anche i checkpoint, lo stato dell'ottimizzatore, le copie dei dati di addestramento che alcuni trainer creano (yolo_data/, wev_data/, laya_data/) e qualsiasi collegamento simbolico che punti fuori da artifacts/.

Il modulo protegge da un push accidentale o pubblico in diversi modi:

  • Digiti due volte il nome del repository, e il push procede solo se i due nomi coincidono.
  • Private è selezionato per impostazione predefinita. Finché Private è selezionato, Potato non fa push su un repository pubblico esistente, e l'API risponde 409.
  • Il modulo indica una variabile d'ambiente sul server, HF_TOKEN per impostazione predefinita, che contiene un token di scrittura di Hugging Face. Il token stesso non viene mai digitato nella pagina. Il nome della variabile deve contenere TOKEN o iniziare con HF_, e il valore deve iniziare con hf_, così il valore di nessun'altra variabile può raggiungere l'Hub.
  • Quando l'Hub non sa dire se il repository esiste, non viene inviato nulla, e un repository creato dal push viene cancellato di nuovo se il caricamento poi fallisce.
  • La licenza della model card è l'id di licenza dell'Hub che indichi, come apache-2.0. Senza indicazione, la card dice che si applica la licenza del modello di base. Un trainer la cui licenza richiede conferma, come ultralytics-detect (AGPL-3.0), richiede la stessa conferma per il push.
  • Un modello lasciato su un host remoto con fetch_artifacts: false, o addestrato su un backend agent, non può essere pubblicato dal server, e l'errore indica dove si trova il modello.

Ogni push è un commit. La pagina dell'esecuzione elenca ogni push con repository, visibilità e commit, e il registro annota chi ha fatto il push. Tramite l'API, il corpo di POST /admin/training/api/runs/<run_id>/push-to-hub accetta repo_id, confirm_repo_id, private (predefinito true), token_env (predefinito HF_TOKEN), licence e accept_licence. La route restituisce 201 con il commit, 400 per un nome non coincidente, una variabile del token mancante, nessun file del modello o una licenza non confermata, e 502 quando l'Hub rifiuta.

Risoluzione dei problemi

Le voci seguenti coprono gli errori più probabili alla prima impostazione. L'elenco upstream di risoluzione dei problemi copre driver GPU, build CUDA e i messaggi specifici dei trainer.

  • /admin/training restituisce 404. model_training.enabled non è true, e Potato registra le route solo quando la chiave è true.
  • "Only N items in the train split". Annota più item, oppure abbassa min_instances nei params dell'esecuzione. La partizione train contiene per impostazione predefinita il 70% degli item etichettati.
  • "Schema 'x' has 1 distinct label(s) in the data". Un classificatore richiede almeno due etichette in uso.
  • "No resolved annotations to train on". Lo schema indicato nell'esecuzione è diverso da quello che si sta annotando, oppure nessuno ha ancora annotato nulla.
  • L'esecuzione non ha pubblicato pre-etichette. Leggi il report writeback in GET /admin/training/api/status. "No predictions were published: write-back is not enabled for any schema" significa che writeback.schemas è vuoto, e i conteggi delle esclusioni mostrano quante predizioni ha rimosso ogni controllo.
  • <trainer> does not take <name>. Un parametro nell'esecuzione o sotto trainer_params è scritto male oppure appartiene a un altro trainer. Il messaggio elenca i nomi che il trainer accetta.
  • L'esecuzione è stata uccisa dopo che la macchina ha esaurito la memoria. Il processo è uscito con SIGKILL, di solito per l'out-of-memory killer. Usa un modello più piccolo o meno item, oppure imposta max_ram_mb in modo che l'esecuzione fallisca entro il proprio limite.
  • "Stopped: the run took longer than model_training.max_wall_seconds". L'esecuzione ha raggiunto il limite di tempo. Alza max_wall_seconds, oppure addestra su meno item.
  • "The GPU ran out of memory". Abbassa batch_size e alza gradient_accumulation per mantenere il batch effettivo, imposta lora: true o lora: {quantize: 4bit}, oppure per llm-sft imposta gradient_checkpointing: true o scegli un modello più piccolo.
  • "ssh to host failed: Permission denied". Potato esegue ssh con BatchMode=yes, quindi ssh <host> true deve riuscire dall'account del server senza alcuna richiesta. Una chiave con passphrase funziona quando ssh-agent tiene la chiave.
  • Un'esecuzione su un backend agent resta in coda. Nessun agent con quel nome di backend sta interrogando il server. Avvia un agent con potato training agent --backend <name> e controlla il token con Check nella pagina Training.

Ulteriori letture

Riferimenti