Vai al contenuto

Addestra il tuo primo modello dalle tue annotazioni

Esegui lo studio di esempio sulle recensioni di Potato su un portatile senza GPU, etichetta 120 recensioni con il simulatore, addestra sklearn-text e guarda le pre-etichette del modello.

Novità nella v2.14.0

Questo tutorial addestra un classificatore di sentiment sulle etichette di uno studio di esempio e mostra le risposte del classificatore al prossimo annotatore come pre-etichette. Il tutorial è scritto per il responsabile di uno studio che prova per la prima volta l'addestramento di modelli di Potato, e ogni passo gira su un portatile senza GPU e senza altre installazioni oltre a Potato. Avvii il progetto di esempio sulle recensioni di Potato, fai etichettare al simulatore di utenti 120 delle 160 recensioni del progetto, addestri sklearn-text dalla pagina Training dell'amministratore, leggi il punteggio held-out dell'esecuzione e accedi come nuovo annotatore per vedere le risposte del modello. Per sapere che cosa fa in generale ogni parte del ciclo, consulta la panoramica dell'addestramento di modelli.

Installare Potato e il progetto di esempio

Il tutorial usa sklearn-text, un trainer che trasforma ogni recensione in feature TF-IDF e adatta un classificatore a regressione logistica. sklearn-text non richiede installazioni aggiuntive perché scikit-learn è una delle dipendenze principali di Potato. Il progetto di esempio si trova nel repository GitHub di Potato e non nel pacchetto pip, quindi installa Potato e clona il repository:

bash
pip install --upgrade potato-annotation
git clone https://github.com/davidjurgens/potato.git
cd potato

Ogni comando seguente va eseguito dalla radice del repository. La cartella del progetto examples/ai-assisted/model-training/ contiene tre file:

  • config.yaml è la configurazione dello studio, con i comandi di questo tutorial nei commenti.
  • data/reviews.json contiene 160 recensioni di prodotti sintetiche, un oggetto JSON per riga con un id e un text.
  • data/gold.json indica l'etichetta corretta di ogni recensione. Il simulatore risponde a partire da questo file.

La configurazione di esempio

La configurazione definisce uno schema radio chiamato sentiment con le etichette positive e negative, e attiva l'addestramento di modelli. Il blocco seguente è il file distribuito senza i commenti, e il file supera python -m potato.validate_cli --strict senza modifiche:

yaml
annotation_task_name: "Review Sentiment (model training demo)"
 
data_files:
  - "data/reviews.json"
 
item_properties:
  id_key: "id"
  text_key: "text"
 
task_dir: "."
output_annotation_dir: "annotation_output"
 
require_password: false
admin_api_key: "demo-admin-key"
 
num_annotators_per_item: 1
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels:
      - "positive"
      - "negative"
    sequential_key_binding: true
 
model_training:
  enabled: true
  writeback:
    schemas: ["sentiment"]
    include_unlabeled: true
    min_confidence: 0.6

Quattro impostazioni danno forma al tutorial:

  • num_annotators_per_item: 1 assegna a ogni recensione una sola etichetta. Tre annotatori simulati con 40 recensioni ciascuno coprono allora 120 recensioni diverse e ne lasciano 40 senza etichetta per il modello.
  • require_password: false permette a un nuovo annotatore di accedere con il solo nome utente. L'ultimo passo accede in questo modo.
  • admin_api_key: "demo-admin-key" apre le pagine di amministrazione. Sostituisci la chiave su ogni server raggiungibile da altre persone.
  • model_training registra le route /admin/training. Il blocco writeback mostra agli annotatori le predizioni dello schema sentiment, e la sezione sul write-back più sotto spiega ogni chiave.

Avviare il server sulla porta 8000

Avvia Potato con la configurazione di esempio:

bash
potato start examples/ai-assisted/model-training/config.yaml -p 8000

Il server carica le 160 recensioni e serve la pagina di annotazione su http://localhost:8000. Se la porta 8000 è occupata sulla tua macchina, passa a -p un'altra porta e usala in ogni URL seguente.

Etichettare 120 recensioni con il simulatore

Il modello ha bisogno di etichette umane da cui imparare. Il simulatore di utenti sostituisce tre annotatori. Ogni annotatore simulato risponde a partire dal file gold e indovina la maggior parte delle risposte. Esegui il simulatore in un secondo terminale, dalla radice del repository:

bash
python -m potato.simulator --server http://localhost:8000 --users 3 \
  --strategy gold_standard --competence good=1.0 --max-annotations 40 \
  --gold-file examples/ai-assisted/model-training/data/gold.json \
  --sequential --fast-mode --no-export

--strategy gold_standard fa rispondere ogni annotatore simulato a partire da gold.json, e --competence good=1.0 assegna a tutti e tre gli annotatori il profilo good del simulatore. Un annotatore good estrae un'accuratezza tra 0,80 e 0,90 e risponde correttamente a ogni recensione con quella probabilità. Le etichette contengono quindi errori, come quelle di un vero team. --sequential esegue i tre annotatori uno dopo l'altro, --fast-mode elimina le pause tra le risposte e --no-export evita di scrivere i file di risultati del simulatore. Il simulatore termina in circa due secondi e chiude con un riepilogo. Controlla che il riepilogo riporti Total annotations: 120 prima di proseguire. Puoi anche etichettare le recensioni a mano su http://localhost:8000. sklearn-text si rifiuta di eseguire l'adattamento con meno di 10 item etichettati nella partizione train.

Aprire la pagina Training con la chiave di amministrazione

La pagina Training richiede una sessione di amministrazione. Apri http://localhost:8000/admin, inserisci demo-admin-key quando la pagina chiede la chiave API, poi apri http://localhost:8000/admin/training.

La pagina Training di Potato con sklearn-text, lo schema sentiment e il backend locale selezionati, sopra una tabella Runs che elenca due esecuzioni concluse con punteggi held-out di 0.847 e 0.840La pagina Training dopo due esecuzioni di sklearn-text sul progetto di esempio

Il pannello Start a run in alto contiene tutta la configurazione. Schema elenca l'unico schema del progetto, sentiment (radio). Trainer elenca tutti i 38 trainer, e un trainer che il progetto non può eseguire riporta il motivo accanto al nome, per esempio "not installed". La pagina seleziona sklearn-text ogni volta che sklearn-text si adatta allo schema. Runs on mostra l'unico backend del progetto, local (this machine).

Addestrare sklearn-text

Lascia vuoto Parameters per usare i valori predefiniti del trainer e fai clic su Train now. L'esecuzione riduce le annotazioni a un'etichetta per recensione, divide le 120 recensioni etichettate nelle partizioni train, val e test e adatta il modello in un processo separato. La nostra esecuzione ha richiesto 1,5 secondi, e il pannello ha mostrato "Run finished." al termine.

sklearn-text usa per impostazione predefinita TfidfVectorizer di scikit-learn per le feature e LogisticRegression per il classificatore. Con 50 o più item nella partizione train, sklearn-text calibra anche le confidenze del classificatore. La calibrazione usa lo scaling di Platt sotto i 1.000 item di addestramento e la regressione isotonica da 1.000 item in su. Il modello calibrato viene tenuto solo se la calibrazione costa non più di 0,05 di accuratezza sull'addestramento. La calibrazione conta qui perché il passo di write-back confronta ogni confidenza con min_confidence.

Per avviare la stessa esecuzione da uno script, invia la chiave di amministrazione nell'intestazione X-API-Key:

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

La risposta contiene il nuovo run_id e "started": true.

La pagina dell'esecuzione e il punteggio held-out

L'esecuzione conclusa compare nella tabella Runs con le dimensioni di train e val e il suo Held-out score. Fai clic sull'ID dell'esecuzione per aprire la pagina dell'esecuzione in /admin/training/runs/<run_id>. La pagina elenca stato, trainer, backend, dimensioni delle partizioni, seme della partizione, punteggio held-out e parametri dell'esecuzione, poi una tabella di ogni metrica e il log dell'esecuzione.

Per impostazione predefinita un'esecuzione esclude dall'addestramento il 15% degli item etichettati per val e il 15% per test, e split_seed decide in quale partizione finisce ogni item. La partizione resta la stessa da un'esecuzione all'altra finché split_seed mantiene il valore, quindi due esecuzioni sulle stesse etichette vengono valutate sugli stessi item. Il punteggio held-out di un'esecuzione sklearn-text è il macro-F1 su val. Il macro-F1 fa la media del punteggio F1 di ciascuna etichetta, qui positive e negative. L'esecuzione registra anche l'accuratezza e il macro-F1 su test. L'accuratezza sulla partizione train è registrata come train_accuracy e non viene mai usata come punteggio. Nella nostra esecuzione, il log riportava:

text
[info] Read 76 labelled rows from the train split
[info] Applied sigmoid calibration over 5 folds
[info] Held-out val macro_f1: 0.725

La documentazione di Potato riporta un'esecuzione sullo stesso progetto, e la tabella la affianca alla nostra:

Documentazione di PotatoLa nostra esecuzione
Recensioni etichettate120120
Item di train, val e testnon indicati76, 19 e 25
Punteggio held-out (macro-F1 su val)0.840.725
Macro-F1 su testnon indicato0.826
Pre-etichette pubblicate8073
Predizioni sotto min_confidence411

I tuoi numeri differiranno da entrambe le colonne, perché ogni annotatore simulato estrae un'accuratezza a caso e commette errori diversi. Nella nostra esecuzione, le etichette simulate coincidevano con gold.json su 97 delle 120 recensioni e su 15 delle 19 recensioni di val. Il punteggio held-out misura l'accordo con le etichette dei tuoi annotatori e non con una chiave di risposta, quindi gli errori degli annotatori in val abbassano il punteggio. Ognuna delle 73 pre-etichette pubblicate dalla nostra esecuzione coincideva con gold.json. In uno studio reale senza file gold, leggi un punteggio held-out basso come un motivo per controllare l'accordo tra gli annotatori prima di dare la colpa al modello.

Attivare il write-back per lo schema

Le predizioni di un'esecuzione raggiungono gli annotatori solo tramite il write-back, cioè la scrittura delle predizioni negli item. La configurazione di esempio attiva già il write-back per lo schema sentiment. Per il tuo progetto, aggiungi questo blocco sotto model_training nella configurazione e riavvia il server:

yaml
model_training:
  enabled: true
  writeback:
    schemas: ["sentiment"]
    include_unlabeled: true
    min_confidence: 0.6

writeback.schemas indica gli schemi le cui predizioni vedono gli annotatori. L'elenco è vuoto per impostazione predefinita, quindi attivare l'addestramento non cambia nulla nella pagina di annotazione finché non indichi uno schema. include_unlabeled: true fa predire a ogni esecuzione anche le recensioni che nessuno ha etichettato, oltre a quelle di val e test. Senza include_unlabeled, un'esecuzione predice solo le recensioni di val e test, e queste hanno già un'etichetta umana. min_confidence: 0.6 tiene una predizione fuori dalla pagina di annotazione quando la confidenza del modello scende sotto 0,6. Potato memorizza comunque la predizione.

Il write-back gira dopo ogni esecuzione riuscita e salta ogni item della partizione train dell'esecuzione. Nella nostra esecuzione, il modello ha predetto 84 recensioni (19 di val, 25 di test e le 40 senza etichetta), 11 predizioni sono scese sotto 0,6 e l'esecuzione ha pubblicato le altre 73. Il campo writeback di GET /admin/training/api/status fornisce gli stessi conteggi, con il riepilogo "Published 73 prediction(s) as prelabels." Le predizioni memorizzate vengono scritte di nuovo all'avvio del server, quindi le pre-etichette sopravvivono a un riavvio. Per togliere dagli item le pre-etichette di un'esecuzione, invia DELETE /admin/training/api/runs/<run_id>/predictions.

Una pre-etichetta vista da un nuovo annotatore

Apri http://localhost:8000 in una finestra privata del browser e accedi con un nome utente che nessuno ha usato, come newannotator. Ogni recensione etichettata ha già la sua etichetta, quindi al nuovo annotatore vengono assegnate le 40 recensioni senza etichetta, e il contatore di avanzamento nella nostra esecuzione indicava 0/40. La nostra prima recensione era "The toaster: Disappointed, it stopped working within a week. Much smaller than the photos suggest." con Negative già selezionato a una confidenza di 0,68.

Una pagina di annotazione di Potato per la recensione di un tostapane con l'opzione Positive già selezionata dal modello e l'item ancora contrassegnato come Not labeledUna recensione che si apre con la risposta del modello selezionata, prima che l'annotatore abbia salvato qualcosa

La pre-etichetta non viene salvata finché l'annotatore si limita a guardare la recensione, e l'indicatore di stato riporta "Not labeled" finché l'annotatore non salva una risposta. La risposta del modello diventa la risposta dell'annotatore quando l'annotatore cambia la selezione o fa clic su Next. Nella nostra esecuzione, le 5 recensioni senza etichetta la cui predizione era sotto min_confidence si sono aperte senza nulla di selezionato. Un annotatore escluso dall'aiuto della macchina con ai_support.holdout non vede alcuna pre-etichetta. Le pre-etichette spingono gli annotatori verso la risposta del modello, quindi attiva il write-back quando il punteggio held-out è abbastanza alto da fidarsene, e individua gli annotatori che accettano ogni pre-etichetta con i controlli descritti in individuare le pre-etichette approvate senza verifica.

Passi successivi

Lo stesso progetto permette ancora qualche esperimento prima di passare ai tuoi dati:

  • Cambia un parametro. Digita {"vectorizer_kwargs": {"ngram_range": [1, 2]}} in Parameters e addestra di nuovo per aggiungere coppie di parole alle feature. La nostra seconda esecuzione con le coppie di parole ha ottenuto 0,774 di macro-F1 su val sulla stessa partizione e ha pubblicato 74 pre-etichette. Un nome di parametro che sklearn-text non accetta viene rifiutato con l'elenco dei nomi che il trainer accetta.
  • Prova un transformer. hf-text-classification (pip install "potato-annotation[train-text]") e setfit (pip install "potato-annotation[embeddings]") imparano lo stesso schema, e la pagina dei trainer indica i parametri di ciascun trainer.
  • Chiudi il ciclo. Il modello nel ciclo aggiunge la coda di revisione, il riaddestramento man mano che arrivano le annotazioni con auto_retrain e il salvataggio della partizione di un'esecuzione come versione del dataset.
  • Sposta l'addestramento su una GPU. Addestra su un server GPU, un cluster SLURM o una macchina dietro NAT invia le stesse esecuzioni a un'altra macchina.
  • Addestra altri tipi di modello. I tutorial su fine-tuning di LLM, modelli di visione, modelli audio e modelli scientifici seguono gli stessi passi con altri trainer e schemi.

Ogni chiave usata qui è elencata nel riferimento di configurazione dell'addestramento di modelli. Avvia la prima esecuzione del tuo progetto copiando nella configurazione il blocco model_training qui sopra e indicando il tuo schema in writeback.schemas.

Ulteriori letture