Konfiguration und Routen des Modelltrainings
Jeder Schlüssel des Blocks model_training, wie Läufe eingereiht, bewertet und gespeichert werden, und die Admin- und Agent-Routen, dazu Lösungen für häufige Laufzeitfehler.
Neu in v2.14.0
Diese Seite ist die Referenz für den Block model_training einer Potato-Konfiguration und dafür, was mit einem Lauf geschieht, nachdem du ihn gestartet hast. Die Seite richtet sich an Personen, die eine Studie betreiben und Läufe begrenzen, Läufe an eine andere Maschine schicken, die Vorhersagen eines Modells Annotatoren zeigen oder das Training aus einem Skript starten wollen. Jeder Schlüssel, jeder Standardwert, jede Route und jede Meldung unten wurde am Code von Potato geprüft. Für einen ersten Lauf beginne mit Dein erstes Modell trainieren. Die Trainer und ihre Parameter sind in Trainer aufgelistet.
Eine vollständige Konfiguration
Die folgende Konfiguration trainiert einen Sentiment-Klassifikator auf Produktrezensionen. auto_retrain passt sklearn-text nach je 25 neuen Annotationen neu an. Mit den standardmäßigen TF-IDF-Features trainiert sklearn-text auf der CPU und braucht nichts außer einer einfachen Installation von Potato. Häufige automatische Läufe kosten deshalb wenig. Das Rückschreiben zeigt Annotatoren jede Vorhersage mit einer Konfidenz von mindestens 0,8. Mit include_unlabeled sagt ein Lauf auch an den Rezensionen voraus, die noch niemand gelabelt hat. Die Standardwerte von hf-text-classification und das Backend gpu-server bedienen Läufe, die von Hand auf der Training-Seite gestartet werden:
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: 4000Halte split_seed für die gesamte Lebensdauer der Studie fest. Ein neuer Seed weist jedes Item neu zu, sodass zurückgehaltene Items im Training landen und spätere Scores nicht mehr mit früheren vergleichbar sind. Die Konfidenzschwelle min_confidence von 0,8 ist ein Ausgangspunkt, und die richtige Schwelle hängt vom ersten Holdout-Score ab. Schalte include_unlabeled erst ein, wenn dieser Score das Anzeigen von Vorlabels trägt, denn Vorlabels verankern Annotatoren bei der Antwort des Modells.
Schlüssel in model_training
Jeder Schlüssel steht unter model_training:
| Schlüssel | Standard | Bedeutung |
|---|---|---|
enabled | false | Registriert die Training-Seite, die Routen unter /admin/training und die Agent-Routen unter /api/training. Ohne enabled: true gibt es die Routen nicht. |
retain_runs | 5 | Abgeschlossene Läufe, die im Lauf-Ledger bleiben. Ein älterer Lauf verlässt das Ledger, sofern seine Vorhersagen nicht mehr gespeichert sind. Lauf-Verzeichnisse bleiben auf der Platte. |
grace_seconds | 20 | Sekunden, die ein abgebrochener Lauf zum Beenden bekommt, bevor Potato den Prozess beendet. 0 oder mehr, und mit dem Auftrag an Backends vom Typ ssh, slurm und agent gesendet. |
queue_max | 10 | Läufe, die hinter dem laufenden Lauf warten dürfen. |
split_seed | 0 | Seed für die Zuweisung der Items zu den Splits train, val und test. |
splits | {train: 0.7, val: 0.15, test: 0.15} | Anteile der Splits, so normiert, dass sie sich zu 1 summieren. Die Namen sind train, val und test, und train ist erforderlich. |
aggregation | consensus | Wie die Labels mehrerer Annotatoren zu einem Item zu einem Label werden. consensus passt das Dawid-Skene-Modell an, wenn die Studie mehr als einen Annotator hat, und fällt auf Mehrheitsentscheid zurück, wenn die Anpassung fehlschlägt. majority nimmt den Mehrheitsentscheid. |
max_wall_seconds | nicht gesetzt | Zeitlimit für einen Lauf. Potato prüft einen lokalen Lauf bei jedem gemeldeten Ereignis und einen ssh- oder Agent-Lauf jede Sekunde. |
max_ram_mb | nicht gesetzt | Limit des Adressraums für den Trainingsprozess, gesetzt mit setrlimit. Auf einer Plattform ohne dieses Limit schreibt der Lauf eine Warnung ins Log und läuft weiter. |
device | auto | auto, cpu, cuda, cuda:N oder mps. auto nimmt CUDA, dann Apples Metal, dann die CPU. |
num_threads | nicht gesetzt | Setzt OMP_NUM_THREADS, MKL_NUM_THREADS und OPENBLAS_NUM_THREADS für den Lauf, sofern die Umgebung diese Variablen nicht schon setzt. |
auto_retrain | aus | Erneutes Training, während Annotationen eintreffen. Siehe auto_retrain. |
writeback | keiner | Veröffentlichung von Vorhersagen als Vorlabels. Siehe writeback. |
backend | local | Das Backend für Läufe, die kein anderes nennen. |
backends | keine | Benannte Backends vom Typ ssh, slurm und agent. Siehe Backends. |
max_predictions_mb | 512 | Größte predictions.jsonl, die ein Remote-Agent hochladen darf. |
trainer_params | keine | Standardwerte für Parameter, nach Trainername geordnet. |
tiling | enabled: auto | Zerlegen großer Bilder in Kacheln für die Detektions- und Segmentierungstrainer. Siehe tiling. |
Die eigenen params eines Laufs überschreiben trainer_params, und diese überschreiben die Standardwerte des Trainers. Ein Parametername, den der Trainer nicht kennt, wird beim Serverstart abgewiesen, wenn der Name unter trainer_params steht, und sonst beim Start des Laufs. Trainer zeigt die Reihenfolge an einem Beispiel.
auto_retrain
Das automatische erneute Training prüft nach jedem Speichern einer Annotation, ob ein neuer Lauf fällig ist:
| Schlüssel | Standard | Bedeutung |
|---|---|---|
enabled | false | Schaltet die Prüfung ein. |
trainer | keiner | Trainername. Erforderlich. |
schemas | keine | Zu trainierende Schemas. Erforderlich. |
min_interval_s | 600 | Sekunden seit dem Ende des letzten Laufs, bevor ein weiterer Lauf startet. |
update_frequency | 25 | Neue Annotationen seit dem letzten automatischen Lauf, bevor ein weiterer Lauf startet. |
params | {} | Trainerparameter, wie die params eines API-Laufs. |
backend | model_training.backend | Backend für automatische Läufe. |
accept_licence | false | Bestätigt die Lizenz eines Trainers, der eine Bestätigung verlangt (ultralytics-detect, ultralytics-segment, layoutlmv3). Ohne die Bestätigung werden automatische Läufe dieser Trainer übersprungen. |
Entscheidet eine Prüfung gegen einen Lauf, erscheint der Grund im Feld skip_reason von GET /admin/training/api/status, z. B. „waiting for 3 more annotation(s)“ oder „a run is already in progress“. Automatische Läufe treten nie in die Lauf-Warteschlange ein. Die nächste Annotation, die nach dem Leeren der Warteschlange gespeichert wird, löst die Prüfung erneut aus, mit mehr Annotationen zum Trainieren. Potato hält die Annotationszahlen im Arbeitsspeicher, sodass ein Projekt, das schon einmal trainiert hat, nach einem Neustart neue Annotationen ab dem Neustart zählt.
writeback
Das Rückschreiben entscheidet, welche Vorhersagen Annotatoren sehen:
| Schlüssel | Standard | Bedeutung |
|---|---|---|
schemas | [] | Schemas, deren Vorhersagen Annotatoren sehen. Eine leere Liste zeigt keine. |
min_confidence | 0.0 | Vorhersagen unter dieser Schwelle werden gespeichert und nicht angezeigt. Eine Vorhersage ohne Konfidenz passiert. |
field | predictions | Item-Feld, in das die Vorlabels geschrieben werden. |
include_unlabeled | false | Sagt auch an Items voraus, die noch niemand gelabelt hat, und versieht diese Items mit Vorlabels. Ohne include_unlabeled sagt ein Lauf nur an den eigenen val- und test-Items voraus. |
tiling
Die Detektions- und Segmentierungstrainer skalieren jedes Bild auf einige hundert Pixel. Bei dieser Größe gehen die Objekte auf einem Whole-Slide-Bild oder einer Satellitenszene verloren. Für ein image_annotation-, microscopy- oder geo_annotation-Schema zerlegt Potato deshalb jedes große Bild in Kacheln, wenn die Trainingsdaten des Laufs aufgebaut werden. Der Split eines Bildes wird festgelegt, bevor das Bild zerlegt wird, sodass Kacheln eines Slides nie in zwei Splits landen. Vorhersagen werden auf das ganze Bild zurückabgebildet, und Holdout-Scores werden an ganzen Bildern berechnet. Das Vision-Tutorial behandelt Slides und Karten in der Praxis.
| Schlüssel | Standard | Bedeutung |
|---|---|---|
enabled | auto | auto zerlegt Slide-Formate (.svs, .ndpi, .mrxs, .scn und andere) und Bilder, deren längere Seite mindestens auto_min_side misst. true zerlegt jedes Bild und false keines. |
auto_min_side | 4096 | Länge der längeren Seite in Pixeln, ab der auto ein Bild zu zerlegen beginnt. |
tile_size | 1024 | Seitenlänge einer Kachel, in den Pixeln, die der Trainer sieht. |
overlap | 128 | Pixel, die benachbarte Kacheln gemeinsam haben, höchstens die Hälfte von tile_size. Halte die Überlappung mindestens so groß wie die Objekte, sonst wird ein großes Objekt in Stücken gefunden. |
downsample | 1 | Pixel in voller Auflösung pro Kachelpixel. |
mpp | keiner | Mikrometer pro Kachelpixel. Überschreibt downsample bei einem Slide, das seine Auflösung angibt. |
background | 0.25 | Leere Kacheln, die pro Kachel mit einem Objekt gezogen werden. Setze background: 0 für Slides, die nur teilweise annotiert sind. |
max_predict_tiles | 2000 | Höchste Zahl an Kacheln, die pro Bild vorhergesagt werden. Die Kacheln mit dem meisten Gewebe bleiben erhalten. |
min_visible | 0.4 | Anteil eines Objekts, der in einer Kachel liegen muss, damit das Objekt dort trainiert wird. |
tissue_threshold | 0.05 | Anteil einer Slide-Kachel, der Gewebe sein muss, damit das Modell auf der Kachel vorhersagt. |
Slides werden mit openslide gelesen, das pip install "potato-annotation[wsi]" installiert, und zwar auf der Maschine, die die Trainingsdaten aufbaut. Ein Remote-Backend lädt die Kacheln herunter und nie das Slide.
Die Lauf-Warteschlange
Es wird immer nur ein Lauf ausgeführt. Ein Lauf, der von der Training-Seite oder über die API gestartet wird, während ein anderer Lauf läuft, wartet, statt abgewiesen zu werden. Die Startanfrage liefert 202 mit queued: true und der position des Laufs, und die Runs-Tabelle listet den Lauf als waiting #N mit einer Schaltfläche Cancel run. Wenn der laufende Lauf endet, startet der älteste wartende Lauf.
Wartende Läufe sind Einträge im Lauf-Ledger, sodass die Warteschlange einen Neustart überlebt, und der erste wartende Lauf startet, wenn der Server zurückkommt. Ein Lauf, den der vorige Server gerade ausführte, wird zur selben Zeit als interrupted markiert. Die Trainingsdaten eines wartenden Laufs werden erst aufgebaut, wenn der Lauf startet, sodass der Lauf auf den Annotationen trainiert, die in diesem Moment vorliegen. Ein Start, der abgewiesen würde, etwa mit einem unbekannten Schema, wird sofort abgewiesen und nicht erst, wenn der Lauf an der Reihe ist. Ein Lauf, dessen Schema oder Trainer während des Wartens aus der Konfiguration verschwand, schlägt mit invalid_when_dequeued fehl, und der nächste Lauf startet.
Sende "queue": false im Anfragekörper, um 409 statt eines Platzes in der Warteschlange zu erhalten. Warten bereits queue_max Läufe, erhält ein neuer Start 429. GET /admin/training/api/status listet die wartenden Läufe der Reihe nach unter queue.
Prüfungen vor einem Lauf
potato validate meldet jedes Problem im Block model_training auf einmal, und der Server verweigert bei denselben Problemen den Start:
potato validate config.yaml --strictDie Prüfungen decken diese Fälle ab:
splitsmit einem anderen Namen alstrain,valundtest, einem Anteil unter 0 oder keiner Zahl, Anteilen, die sich zu 0 summieren, oder ohnetrain.- Ein Schlüssel, den
writebackoderauto_retrainnicht hat, ein Eintrag inwriteback.schemas, der kein Schema ist, oder einmin_confidenceaußerhalb von 0 bis 1.accept_licensewird als Tippfehler vonaccept_licencegemeldet. - Ein aktivierter
pre_annotation-Block, dessenfieldsich vonwriteback.fieldunterscheidet. Unter einem solchen Block würde kein Trainings-Vorlabel erscheinen. - Bei
auto_retrain.enabledein Trainer oder Schema, das nicht existiert, ein Schema, aus dem der Trainer nicht lernen kann, Parameter, die der Trainer nicht kennt oder die den falschen Typ haben, einbackend, das inbackendsfehlt, oderdecision-calibrateauf einem anderen Backend alslocal. - Ein Parameter unter
trainer_params, den der Trainer nicht kennt oder der den falschen Typ hat. Innerhalb vondpprüft die Kontrolle auch jeden Schlüssel und dessen Wertebereich. - Ein
grace_secondsunter 0 oder keine Zahl, oder einretain_runsodersplit_seedunter 0 oder keine ganze Zahl. - Unter
backendsein fehlender oder unbekanntertype, ein Schlüssel, den der Typ nicht hat, ein ssh-Backend ohnehost, eingpus-Wert außerauto,noneoder GPU-Indizes, ein Remote-Backend namenslocaloder einmodel_training.backend, das nicht definiert ist.
potato training check testet ein Backend, bevor ein Lauf es nutzt. Für local gibt der Befehl das Gerät aus, das ein Lauf nutzen würde, z. B. local: this machine, Apple Metal (mps) auf einem Mac mit Apple Silicon. Für ein ssh-Backend meldet der Befehl die Python-Version, jede GPU mit ihrem freien Speicher, die GPU, die ein Lauf erhielte, und die Trainingspakete, die dem entfernten Interpreter fehlen. Die Schaltfläche Check auf der Training-Seite führt denselben Test aus, und --json gibt den Bericht als JSON aus:
potato training check local config.yaml
potato training check gpu-server config.yamlEin Lauf, der von der Training-Seite oder über die API gestartet wird, wird beim Start erneut geprüft. Die Statuscodes stehen unter Routen.
Backends
Ein Lauf wird auf einem Backend ausgeführt, und das Menü Runs on der Training-Seite listet die konfigurierten Backends. model_training.backend setzt den Standard, und ein API-Lauf oder auto_retrain kann mit backend ein anderes Backend nennen. Potato kennt vier Backend-Typen:
| Typ | Wo der Trainer läuft | Wer den Trainer startet |
|---|---|---|
local | Diese Maschine, in einem Subprozess. Immer verfügbar und der Standard. | Potato |
ssh | Eine andere Maschine, die Potato per ssh erreichen kann, etwa ein GPU-Server. | Potato, über ssh |
slurm | Der Rechenknoten eines Clusters, als Batch-Job. | Potato, per ssh zum Login-Knoten und dann sbatch |
agent | Eine Maschine, die Potato nicht erreichen kann, etwa eine Workstation hinter NAT. | Eine Person, mit potato training agent |
Ein ssh-Backend nutzt schlüsselbasierte Authentifizierung mit eingeschaltetem BatchMode, sodass eine Passwortabfrage fehlschlägt, statt zu hängen. Ein slurm-Backend nutzt nur sbatch, squeue und scancel, dazu scontrol auf Clustern, die scontrol bereitstellen, und braucht ein remote_dir auf Speicher, den die Rechenknoten gemeinsam nutzen. Ein Agent-Backend braucht keinen eingehenden Port, weil der Agent jede Verbindung öffnet. Der Name local ist für diese Maschine reserviert, und decision-calibrate läuft nur auf local. Auf einem GPU-Server, SLURM-Cluster oder einer Maschine hinter NAT trainieren führt durch alle drei Remote-Typen mit ihren Schlüsseln.
Holdout-Scores
Jeder Lauf bewertet die eigenen Vorhersagen an den Items val und test gegen die aufgelösten menschlichen Labels. Metriknamen tragen den Split, wie in val_macro_f1 oder test_f1. Ein Item mit einem Label und ohne Vorhersage zählt als falsch, sodass das Auslassen schwieriger Items den Score eines Trainers nicht erhöhen kann. <split>_coverage meldet den Anteil der Items, die eine Vorhersage erhalten haben.
Der Hauptscore erscheint in der Spalte Held-out score der Runs-Tabelle, mit Split und Metrik im Tooltip. Der Hauptscore ist die Hauptmetrik des ersten Schemas auf dem ersten der Splits val und test, der Items hat. Hat ein Trainer den besten Checkpoint anhand des val-Scores gewählt, versucht Potato zuerst test, weil der Trainer den val-Score bereits gesehen hat. Die Fine-Tuning-Trainer, die die beste Epoche behalten, z. B. hf-text-classification, torchvision-detect und llm-sft, nehmen den Hauptscore von test. sklearn-text, setfit, rdkit-property, die Trainer für Entscheidungsmodelle und die Inference-Bridges wählen auf val nichts aus, und ein Lauf eines dieser Trainer nimmt den Hauptscore von val, sobald val Items hat. Ein Lauf ohne val- oder test-Items wird als „not scored“ angezeigt.
Die Hauptmetrik hängt vom Annotationstyp des Schemas ab, wie die folgende Tabelle für gängige Typen zeigt:
| Annotationstyp | Hauptmetrik |
|---|---|
radio, select, likert | Macro-F1 (auch Genauigkeit, und mittlerer absoluter Fehler bei numerischen likert-Labels) |
multiselect | Micro-F1 (auch Macro-F1 und exakte Übereinstimmung) |
span | F1 über Spans, die in Anfang, Ende und Label übereinstimmen |
text | Token-F1 (auch exakte Übereinstimmung) |
pairwise im Modus binary | Genauigkeit über Items, die nicht als Unentschieden beantwortet wurden |
ranking | Kendalls Tau |
image_annotation, microscopy, geo_annotation | COCO-mAP bei IoU 0,5 (map_50), wobei auch map_50_95 aufgezeichnet wird |
audio_annotation | F1 über Segmente mit demselben Label bei IoU ab 0,5 |
speech_transcript | word_accuracy, 1 minus die Wortfehlerrate |
volume_annotation | mean_dice |
Der Token-F1 belohnt eine Antwort, die die richtigen Wörter in falscher Reihenfolge nutzt, also lies den Token-F1 zusammen mit der exakten Übereinstimmung. Der Hauptscore der Detektion nutzt IoU 0,5 statt des Mittels von 0,5 bis 0,95, weil die Boxen zweier Annotatoren für ein Objekt sich selten bei IoU 0,9 überlappen. Die Upstream-Tabelle der Holdout-Scores listet die Metriken für jeden Annotationstyp.
Rückschreiben
Nach einem erfolgreichen Lauf speichert Potato die Vorhersagen des Laufs und schreibt die Vorhersagen, die vier Prüfungen bestehen, in das Feld predictions jedes Items oder in das Feld, das writeback.field nennt. Die Prüfungen laufen in dieser Reihenfolge, und der Bericht zum Rückschreiben des Laufs zählt jedes Überspringen:
- Items im Train-Split erhalten nie ein Vorlabel. Die Prüfung deckt den Train-Split jedes Laufs ab, der noch im Ledger steht, und ein Vorlabel, das ein früherer Lauf auf einem Item hinterlassen hat, wird entfernt, wenn ein späterer Lauf auf dem Item trainiert.
- Nur Schemas in
writeback.schemaswerden veröffentlicht. Die Liste ist standardmäßig leer, sodass das Einschalten des Trainings nichts ändert, was Annotatoren sehen. - Abgelehnte Paare werden übersprungen. Ein Paar aus Item und Schema mit dem Urteil
rejectin der Modellprüfung wird nicht erneut angezeigt. - Die Konfidenzschwelle gilt. Eine Vorhersage unter
min_confidencewird gespeichert und nicht veröffentlicht.
Das Rückschreiben ändert nie ein menschliches Label, weil Vorhersagen in die Item-Daten gehen und Annotationen im Benutzerzustand jedes Annotators leben. Ein Vorlabel erscheint als vorausgefüllte Antwort, die der Annotator bearbeiten kann, z. B. eine Auswahl als gewählte Option und eine Freitextantwort im Textfeld des Schemas, und ein pre_annotation-Block ist nicht nötig. Das Vorlabel wird erst dann zur Antwort des Annotators, wenn der Annotator das Vorlabel bearbeitet oder weitergeht. Ein Vorlabel, das niemand bearbeitet oder übergangen hat, wird deshalb nie zu einem Trainingslabel. Ein Paar aus Annotator und Item, das ai_support.holdout in die Vergleichsgruppe der Studie ohne Unterstützung einordnet, zeigt kein Vorlabel, und die für dieses Paar gesendeten Item-Daten lassen sowohl das writeback.field als auch das pre_annotation.field aus. Der Bericht zum Rückschreiben ist das Feld writeback von GET /admin/training/api/status, und die summary des Berichts nennt den Grund, warum ein Lauf nichts veröffentlicht hat.
Potato hält pro Item und Schema eine Vorhersage, und die Vorhersage eines neueren Laufs ersetzt die eines älteren. Wird die neuere Vorhersage gespeichert, aber nicht angezeigt, weil sie unter min_confidence liegt, leer ist oder abgelehnt wurde, wird das Vorlabel des älteren Laufs sofort vom Item entfernt, und der Bericht zum Rückschreiben zählt das Item in n_superseded_cleared. Vorlabels, die mit den Daten geliefert wurden, bleiben unberührt. Beim Start werden die gespeicherten Vorhersagen für die Schemas in writeback.schemas unter denselben vier Prüfungen wieder in die Item-Daten geschrieben, sodass Vorlabels einen Neustart überleben. Um die Vorlabels eines Laufs zurückzuziehen, sende DELETE /admin/training/api/runs/<run_id>/predictions. Die Anfrage entfernt die gespeicherten Vorhersagen und nimmt die Vorlabels von den Items.
Korrekturen und angeheftete Items trainieren immer mit
Zwei Arten von Items gehen in den train-Split jedes späteren Laufs, gleichgültig, welchen Platz das Item im stabilen Split hat:
- Items, die ein Reviewer korrigiert hat. Ein Urteil
correctin der Modellprüfung bedeutet, dass eine Person die Antwort des Modells korrigiert hat. Korrekturen stammen von den Items, bei denen das Modell am schlechtesten war, sodass ein korrigiertes Item invalodertestdas Modell an einer Stichprobe seiner eigenen Fehler bewerten würde. Die Urteileacceptundrejectlassen ein Item dort, wo es war. - Angeheftete Items. Train on these neben einem Slice auf der Seite Catalog heftet die Items an, auf die der Slice passt, z. B. der eingebaute Slice
model-found-nothing. Ein angeheftetes Item wird trainiert, sobald jemand das Item gelabelt hat.
Ein Lauf, der zurückgehaltene Items nach train verschoben hat, schreibt eine Warnung mit der Anzahl ins Log. Der Holdout-Score des Laufs wird dann ohne diese Items berechnet und ist nicht direkt mit dem Score eines früheren Laufs vergleichbar. Die Anzahlen stehen unter stats.forced_train in der manifest.json der Trainingsdaten.
Einen Split als Datensatzversion speichern
Keep this split as a dataset auf der Seite eines Laufs speichert die val-, test- oder train-Items des Laufs mit ihren abgestimmten menschlichen Labels als neue Version eines Datensatzes. Eine Datensatzversion ändert sich danach nie mehr, sodass spätere Modelle und LLM-Prompts an genau diesen Items verglichen werden können. Die Funktion braucht datasets.enabled: true. Jede gespeicherte Version enthält einen Split und beginnt bei null, statt zur letzten Version des Datensatzes hinzuzufügen. Die val-Items von Lauf 2, zu denen von Lauf 1 hinzugefügt, würden sonst Items enthalten, auf denen Lauf 2 trainiert hat. Die inputs jedes Beispiels lassen das Vorlabel-Feld aus, sodass eine Auswertung die Antwort des Modells nicht lesen kann.
Woher ein Vorlabel stammt
GET /admin/model-review enthält provenance für jedes Item in der Prüfwarteschlange, dessen Vorlabel ein Trainingslauf geschrieben hat. Für jedes Schema nennt der Eintrag die Lauf-ID, den Trainer und den Holdout-Score des Laufs. Vorlabels, die mit den Daten geliefert wurden, haben keinen Eintrag.
Wo Läufe gespeichert werden
Jeder Lauf hat ein Verzeichnis unter <task_dir>/<output_annotation_dir>/training/runs/<run_id>/:
| Pfad | Inhalt |
|---|---|
bundle/ | Die Trainingsdaten: train.jsonl, val.jsonl, test.jsonl, unlabeled.jsonl mit include_unlabeled, labels.json, manifest.json und media/. |
artifacts/ | model_card.json, predictions.jsonl und das Modell, z. B. model.pkl für sklearn-text oder ein Verzeichnis model/ für die Transformer-Trainer. |
spec.json | Was dem Lauf aufgetragen wurde. |
events.jsonl, stdout.log, stderr.log | Die Fortschrittsereignisse und die Ausgabe des Laufs. |
agent.log | Die eigene Ausgabe des Remote-Agents, bei ssh-Backends. |
bundle.tar.gz | Die Trainingsdaten, wie der Agent sie heruntergeladen hat, einschließlich Medien, bei Remote-Backends. |
Das Lauf-Ledger liegt in der Projektdatenbank <task_dir>/project.sqlite und hält die Läufe, den Split jedes Items pro Lauf, die auf Training festgelegten Items, die gespeicherten Vorhersagen, Agent-Token und Pushes auf den Hugging Face Hub fest. retain_runs beschneidet das Ledger und beschneidet nie einen Lauf, dessen Vorhersagen noch gespeichert sind, sodass sich jedes Vorlabel auf den Lauf zurückführen lässt, der es geschrieben hat. Das Beschneiden lässt Lauf-Verzeichnisse auf der Platte.
Ein LoRA-Lauf speichert nur den Adapter, einige bis einige hundert Megabyte, und lädt das Basismodell über model_name, wenn der Lauf vorhersagt. Ein vollständiges Fine-Tuning speichert das ganze Modell. Setze die Umgebungsvariable POTATO_MODEL_CACHE auf ein Verzeichnis, und der Trainingsprozess nutzt dieses Verzeichnis für HF_HOME, TRANSFORMERS_CACHE und SENTENCE_TRANSFORMERS_HOME, sofern diese Variablen nicht schon gesetzt sind. Lege auf einer Air-Gap-Maschine die Modelle, die die Trainer nennen, vorab in diesem Verzeichnis ab.
Routen
Die Training-Seite und ihre JSON-Routen liegen unter /admin/training und brauchen Admin-Zugriff. Admin-Zugriff bedeutet eine Admin-Sitzung oder den Header X-API-Key. POST- und DELETE-Anfragen aus einem Browser müssen von derselben Origin stammen. Die OpenAPI-Spezifikation von Potato kennzeichnet alle 26 Trainings-Operationen mit x-potato-requires-config: model_training.enabled: true:
| Route | Zweck |
|---|---|
GET /admin/training | Die Training-Seite, mit Lauf-Formular, Lauf-Liste und Trainern. |
GET /admin/training/runs/<run_id> | Die Seite eines Laufs, mit Status, Metriken, Ereignissen und dem Split jedes Items. |
GET /admin/training/api/trainers | Jeder Trainer, mit seinen Arten, Modalitäten, seiner Lizenz und seinem Installationsstatus. |
GET /admin/training/api/schemas | Die Schemas der Studie, die Art jedes Schemas und die Trainer, die zu jedem Schema passen. |
GET /admin/training/api/status | Der aktuelle oder letzte Lauf, mit Zustand, Fortschritt, Metriken, Warnungen, skip_reason, writeback und queue. |
GET /admin/training/api/runs | Lauf-Verlauf. ?limit= hat den Standardwert 50 und das Maximum 500. |
POST /admin/training/api/runs | Startet einen Lauf. 200, wenn der Lauf startet, und 202 mit queued: true und position, wenn der Lauf wartet. |
GET /admin/training/api/runs/<run_id> | Der Eintrag eines Laufs, dazu review, die Präzision der Vorhersagen des Laufs unter Prüfurteilen. |
GET /admin/training/api/runs/<run_id>/events | Das Ereignislog des Laufs. ?limit= hat den Standardwert 200. |
POST /admin/training/api/runs/<run_id>/cancel | Bricht den laufenden oder einen wartenden Lauf ab. 400 für jede andere Lauf-ID. |
DELETE /admin/training/api/runs/<run_id>/predictions | Zieht die gespeicherten Vorhersagen und Vorlabels des Laufs zurück. |
POST /admin/training/api/runs/<run_id>/push-to-hub | Veröffentlicht das Modell des Laufs auf dem Hugging Face Hub. Siehe Auf dem Hugging Face Hub veröffentlichen. |
POST /admin/training/api/runs/<run_id>/pin-split | Speichert einen Split als Datensatzversion, mit dem Körper {"dataset": name, "split": "val"}. |
GET /admin/training/api/backends | Die konfigurierten Backends. |
POST /admin/training/api/backends/<name>/check | Testet ein Backend, wie es potato training check tut. |
GET /admin/training/api/pinned | Angeheftete Items, nach Grund gruppiert. |
POST /admin/training/api/pinned | Heftet Items an train, mit {"slice": name} oder {"instance_ids": [...]}. |
DELETE /admin/training/api/pinned | Löst die aufgelisteten instance_ids, oder jedes angeheftete Item, wenn der Körper keine auflistet. |
Eine Lauf-Anfrage nimmt trainer, schemas (eine Liste oder einen Namen), params, backend, accept_licence und queue entgegen. Jeder Trainer passt nur das erste genannte Schema an. Die folgende Anfrage startet einen sklearn-text-Lauf auf dem Schema sentiment des Beispiels:
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"]}'Ein abgewiesener Start nennt den Grund in error:
| Status | Wann |
|---|---|
400 | Kein Trainer oder kein Schema im Körper, ein unbekannter Trainer oder ein unbekanntes Schema, ein Schema, aus dem der Trainer nicht lernen kann, ein Trainer, den das Projekt nicht ausführen kann, oder ein Trainer, dessen Lizenz bestätigt werden muss, mit needs_licence_ack: true, bis die Anfrage accept_licence: true setzt |
409 | Ein Parameter, den der Trainer nicht kennt oder der den falschen Typ oder Wertebereich hat, ein unbekanntes Backend, decision-calibrate auf einem anderen Backend als local oder ein bereits laufender Lauf bei "queue": false |
429 | Es warten bereits queue_max Läufe |
Agent-Protokoll
model_training.enabled registriert auch die Routen, die ein Trainings-Agent aufruft, unter /api/training. Ein Agent sendet sein Token als Authorization: Bearer <token>, und ein fehlendes oder ungültiges Token erhält 401. Das Registrieren eines Backends braucht stattdessen den Admin-API-Schlüssel. potato/training/protocol.py beschreibt das Protokoll für alle, die einen neuen Agent schreiben, und potato/training/agent.py ist die Referenzimplementierung:
| Route | Zweck |
|---|---|
POST /api/training/backends/register | Stellt ein Agent-Token für einen Backend-Namen aus, mit X-API-Key. potato training register ruft diese Route auf. |
POST /api/training/backends/<name>/heartbeat | Ein untätiger Agent meldet, dass er lebt. 403 für ein Token, das für ein anderes Backend ausgestellt wurde. |
GET /api/training/jobs/next?wait=30 | Long Poll. 200 mit einem Job oder 204, wenn innerhalb von wait Sekunden kein Job eintrifft. |
GET /api/training/jobs/<run_id> | Der Job, die Spezifikation des Jobs und ob der Job abgebrochen wurde. |
GET /api/training/jobs/<run_id>/bundle | Die Trainingsdaten als tar.gz, einschließlich Medien. Die Route beantwortet Range-Anfragen, sodass ein Agent einen abgebrochenen Download bis zu fünfmal fortsetzt. 410, sobald das Bundle weg ist. |
POST /api/training/jobs/<run_id>/progress | Fortschrittsereignisse. Ein Abbruch kommt in der Antwort zurück. |
POST /api/training/jobs/<run_id>/predictions | predictions.jsonl. 413 oberhalb von max_predictions_mb. |
POST /api/training/jobs/<run_id>/complete | Exit-Code und letzte Ereignisse. |
QLoRA
llm-sft, llm-dpo, hf-text-classification, vlm-sft und reward-model nehmen lora: {quantize: 4bit} entgegen, das Setup von QLoRA (Dettmers et al., 2023). Das Basismodell wird mit 4-Bit-NF4-Gewichten und doppelter Quantisierung geladen, und ein LoRA-Adapter wird darauf in bf16 trainiert, wo die GPU bf16 unterstützt. quantize: 8bit ist die Zwischenstufe, und Vorhersagen laden das Basismodell auf dieselbe Weise.
model_training:
trainer_params:
llm-sft:
model_name: Qwen/Qwen2.5-7B-Instruct
lora: {quantize: 4bit}Mit 4 Bit brauchen die Basisgewichte ein Viertel des Speichers, den dieselben Gewichte in bf16 brauchen, und Aktivierungen, der Adapter und der Optimizer-Zustand kommen obendrauf. Potato hat den Speicherbedarf eines QLoRA-Laufs auf einer GPU noch nicht gemessen, plane also anhand der eigenen Zeile „Peak GPU memory“ des Laufs. Jeder Transformer-Lauf schreibt diese Zeile am Ende ins Log. QLoRA braucht eine CUDA-GPU und einen bitsandbytes-Build für das CUDA dieser Maschine. Der Lauf prüft beides vor dem Laden des Modells, indem er auf der GPU einige Zahlen quantisiert, und wenn die beiden Versionen nicht zusammenpassen, nennt der Fehler beide Versionen. Das Tutorial zum Fine-Tuning von LLMs setzt QLoRA bei SFT- und DPO-Läufen ein.
Auf dem Hugging Face Hub veröffentlichen
Ein erfolgreicher Lauf, dessen Modell auf dem Potato-Server liegt, hat auf der Seite des Laufs Publish to the Hugging Face Hub. Der Push lädt das Modell und eine README.md als Modellkarte hoch, die aus dem Lauf erzeugt wird und Trainer, Basismodell und Adapter, Schemas und Labels, Split-Größen, den Holdout-Score samt dem Split, an dem er gemessen wurde, sowie Lauf- und Bundle-ID nennt. Die Karte eines dp-Laufs hat außerdem eine Zeile „Differential privacy“ mit dem verbrauchten Epsilon gegenüber dem Ziel, dem Delta und dem Train-Split, den die Garantie abdeckt. Die Zeile lässt das Ziel oder das Delta weg, wenn der Lauf den Wert nicht festgehalten hat.
Der Upload ist eine feste Liste von Dateien und nicht das ganze Verzeichnis artifacts/. Die Liste enthält die Gewichtsdateien, z. B. .safetensors, .bin, .pt und .pkl, die Konfigurations- und Tokenizer-Dateien im gespeicherten Verzeichnis model/, model_card.json mit lokalen Pfaden, die durch Dateinamen ersetzt sind, und calibration.json. Die Antworten des Modells auf den Items des Projekts (predictions.jsonl und raw_answers.jsonl bei den Entscheidungsmodellen) bleiben auf dem Server. Checkpoints, Optimizer-Zustand, die Kopien der Trainingsdaten, die einige Trainer anlegen (yolo_data/, wev_data/, laya_data/), und jeder Symlink, der aus artifacts/ hinauszeigt, bleiben ebenfalls außen vor.
Das Formular schützt auf mehrere Arten vor einem versehentlichen oder öffentlichen Push:
- Du tippst den Repository-Namen zweimal ein, und der Push läuft nur, wenn beide Namen übereinstimmen.
- Private ist standardmäßig angehakt. Solange Private angehakt ist, pusht Potato nicht in ein bestehendes öffentliches Repository, und die API antwortet
409. - Das Formular nennt eine Umgebungsvariable auf dem Server, standardmäßig
HF_TOKEN, die ein Hugging-Face-Schreibtoken enthält. Das Token selbst wird nie in die Seite getippt. Der Name der Variable mussTOKENenthalten oder mitHF_beginnen, und der Wert muss mithf_beginnen, sodass der Wert keiner anderen Variable den Hub erreichen kann. - Kann der Hub nicht sagen, ob das Repository existiert, wird nichts gepusht, und ein Repository, das der Push angelegt hat, wird wieder gelöscht, wenn der Upload danach fehlschlägt.
- Die Lizenz der Modellkarte ist die Hub-Lizenz-ID, die du angibst, etwa
apache-2.0. Ohne Angabe sagt die Karte, dass die Lizenz des Basismodells gilt. Ein Trainer, dessen Lizenz bestätigt werden muss, etwaultralytics-detect(AGPL-3.0), braucht dieselbe Bestätigung für den Push. - Ein Modell, das mit
fetch_artifacts: falseauf einem Remote-Host liegt oder auf einem Agent-Backend trainiert wurde, lässt sich nicht vom Server pushen, und der Fehler nennt, wo das Modell liegt.
Jeder Push ist ein Commit. Die Lauf-Seite listet jeden Push mit Repository, Sichtbarkeit und Commit, und das Ledger hält fest, wer den Push ausgeführt hat. Über die API nimmt der Körper von POST /admin/training/api/runs/<run_id>/push-to-hub die Felder repo_id, confirm_repo_id, private (Standard true), token_env (Standard HF_TOKEN), licence und accept_licence entgegen. Die Route liefert 201 mit dem Commit, 400 bei einer Abweichung, einer fehlenden Token-Variable, fehlenden Modelldateien oder einer unbestätigten Lizenz und 502, wenn der Hub ablehnt.
Fehlerbehebung
Die Einträge unten decken die Fehler ab, die bei einem ersten Setup am wahrscheinlichsten sind. Die Upstream-Liste zur Fehlerbehebung behandelt GPU-Treiber, CUDA-Builds und die trainerspezifischen Meldungen.
/admin/trainingliefert 404.model_training.enabledist nichttrue, und Potato registriert die Routen nur, wenn der Schlüsseltrueist.- „Only N items in the train split“. Annotiere mehr Items oder senke
min_instancesin denparamsdes Laufs. Der Train-Split enthält standardmäßig 70 % der gelabelten Items. - „Schema 'x' has 1 distinct label(s) in the data“. Ein Klassifikator braucht mindestens zwei verwendete Labels.
- „No resolved annotations to train on“. Das im Lauf genannte Schema unterscheidet sich vom annotierten Schema, oder bisher hat niemand etwas annotiert.
- Der Lauf hat keine Vorlabels veröffentlicht. Lies den Bericht
writebackinGET /admin/training/api/status. „No predictions were published: write-back is not enabled for any schema“ bedeutet, dasswriteback.schemasleer ist, und die Zähler der übersprungenen Vorhersagen zeigen, wie viele Vorhersagen jede Prüfung entfernt hat. <trainer> does not take <name>. Ein Parameter im Lauf oder untertrainer_paramsist falsch geschrieben oder gehört zu einem anderen Trainer. Die Meldung listet die Namen auf, die der Trainer akzeptiert.- Der Lauf wurde beendet, nachdem der Maschine der Speicher ausgegangen war. Der Prozess endete mit SIGKILL, meist durch den Out-of-Memory-Killer. Nutze ein kleineres Modell oder weniger Items, oder setze
max_ram_mb, damit der Lauf innerhalb seines eigenen Limits fehlschlägt. - „Stopped: the run took longer than model_training.max_wall_seconds“. Der Lauf hat das Zeitlimit erreicht. Erhöhe
max_wall_secondsoder trainiere auf weniger Items. - „The GPU ran out of memory“. Senke
batch_sizeund erhöhegradient_accumulation, um den effektiven Batch zu halten, setzelora: trueoderlora: {quantize: 4bit}, oder setze fürllm-sftgradient_checkpointing: trueoder wähle ein kleineres Modell. - „ssh to host failed: Permission denied“. Potato führt
sshmitBatchMode=yesaus, daher mussssh <host> truevom Konto des Servers aus ohne Abfrage gelingen. Ein Schlüssel mit Passphrase funktioniert, wennssh-agentden Schlüssel hält. - Ein Lauf auf einem Agent-Backend bleibt in der Warteschlange. Kein Agent mit diesem Backend-Namen fragt ab. Starte einen Agent mit
potato training agent --backend <name>und prüfe das Token mit Check auf der Training-Seite.
Weiterführende Lektüre
- Modelltraining auf den eigenen Annotationen: der Trainingskreislauf, die Training-Seite und ein Schnellstart.
- Trainer: jeder Trainer, die Schemas, aus denen er lernt, und die Installationsbefehle.
- Auf einem GPU-Server, SLURM-Cluster oder einer Maschine hinter NAT trainieren: ssh-, SLURM- und Polling-Agent-Backends Schritt für Schritt.
- Modell im Kreislauf: Rückschreiben, Prüfung,
auto_retrainund Datensatzversionen in einer Studie. - Active Learning: Items nach Modellunsicherheit ordnen.
- Durchgewunkene Vorlabels erkennen: prüfen, ob Annotatoren Vorlabels akzeptieren, ohne sie zu lesen.
- Upstream-Referenz: die vollständigen Parametertabellen für jeden Trainer.
Literatur
- Dawid, A. P., and Skene, A. M. (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. Applied Statistics, 28(1). https://doi.org/10.2307/2346806
- Dettmers, T., Pagnoni, A., Holtzman, A., and Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. Advances in Neural Information Processing Systems 36 (NeurIPS 2023). https://proceedings.neurips.cc/paper_files/paper/2023/hash/1feb87871436031bdc0f2beaa62a049b-Abstract-Conference.html