Meet YOLO26: next-gen vision AI.

Link to this sectionAnpassen des Trainers#

Die Ultralytics Trainings-Pipeline basiert auf BaseTrainer und aufgabenspezifischen Trainern wie DetectionTrainer. Diese Klassen handhaben den Trainingszyklus, die Validierung, das Checkpointing und die Protokollierung bereits ab Werk. Wenn du mehr Kontrolle benötigst – etwa um benutzerdefinierte Metriken zu verfolgen, die Verlustgewichtung anzupassen oder Lernraten-Zeitpläne zu implementieren – kannst du vom Trainer ableiten und spezifische Methoden überschreiben.

Dieser Leitfaden führt durch sieben gängige Anpassungen:

  1. Protokollierung benutzerdefinierter Metriken (F1-Score) am Ende jeder Epoche
  2. Hinzufügen von Klassengewichten zur Behandlung von Klassenungleichgewichten
  3. Speichern des besten Modells basierend auf einer anderen Metrik
  4. Einfrieren des Backbones für die ersten N Epochen, dann Auftauen
  5. Festlegen von Lernraten pro Schicht
  6. Synchronisieren von BatchNorm über GPUs für Multi-GPU-Training
  7. Konfigurieren des Gradienten-Clippings zur Stabilitätsoptimierung
Voraussetzungen

Bevor du diesen Leitfaden liest, stelle sicher, dass du mit den Grundlagen des Trainierens von YOLO-Modellen und der Seite Erweiterte Anpassungen vertraut bist, welche die BaseTrainer-Architektur abdeckt.

Link to this sectionWie benutzerdefinierte Trainer funktionieren#

Die YOLO-Modellklasse akzeptiert einen trainer-Parameter in der train()-Methode. Dies ermöglicht es dir, deine eigene Trainerklasse zu übergeben, die das Standardverhalten erweitert:

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer

class CustomTrainer(DetectionTrainer):
    """A custom trainer that extends DetectionTrainer with additional functionality."""

    pass  # Add your customizations here

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=10, trainer=CustomTrainer)

Dein benutzerdefinierter Trainer erbt alle Funktionen vom DetectionTrainer, sodass du nur die spezifischen Methoden überschreiben musst, die du anpassen möchtest.

Link to this sectionProtokollierung benutzerdefinierter Metriken#

Der Validierungsschritt berechnet Präzision, Abruf und mAP. Wenn du zusätzliche Metriken wie den klassenspezifischen F1-Score benötigst, überschreibe validate():

import numpy as np

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer
from ultralytics.utils import LOGGER

class MetricsTrainer(DetectionTrainer):
    """Custom trainer that computes and logs F1 score at the end of each epoch."""

    def validate(self):
        """Run validation and compute per-class F1 scores."""
        metrics, fitness = super().validate()
        if metrics is None:
            return metrics, fitness

        if hasattr(self.validator, "metrics") and hasattr(self.validator.metrics, "box"):
            box = self.validator.metrics.box
            f1_per_class = box.f1
            class_indices = box.ap_class_index
            names = self.validator.names

            valid_f1 = f1_per_class[f1_per_class > 0]
            mean_f1 = np.mean(valid_f1) if len(valid_f1) > 0 else 0.0

            LOGGER.info(f"Mean F1 Score: {mean_f1:.4f}")
            per_class_str = [
                f"{names[i]}: {f1_per_class[j]:.3f}" for j, i in enumerate(class_indices) if f1_per_class[j] > 0
            ]
            LOGGER.info(f"Per-class F1: {per_class_str}")

        return metrics, fitness

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=5, trainer=MetricsTrainer)

Dies protokolliert den mittleren F1-Score über alle Klassen und eine Aufschlüsselung pro Klasse nach jedem Validierungslauf.

Verfügbare Metriken

Der Validator bietet Zugriff auf viele Metriken über self.validator.metrics.box:

AttributBeschreibung
f1F1-Score pro Klasse
image_metricsMetriken-Wörterbuch pro Bild mit Präzision, Abruf, F1, TP, FP und FN
pPräzision pro Klasse
rAbruf pro Klasse
ap50AP bei IoU 0,5 pro Klasse
apAP bei IoU 0,5:0,95 pro Klasse
mp, mrMittlere Präzision und mittlerer Abruf
map50, mapMittlere AP-Metriken

Link to this sectionHinzufügen von Klassengewichten#

Wenn dein Datensatz unausgeglichene Klassen aufweist (z. B. ein seltener Defekt in der Fertigungsinspektion), kannst du unterrepräsentierte Klassen in der Verlustfunktion höher gewichten. Dies bewirkt, dass das Modell Fehlklassifizierungen bei seltenen Klassen stärker bestraft.

Um den Verlust anzupassen, leite von den Verlustklassen, dem Modell und dem Trainer ab:

import torch
from torch import nn

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer
from ultralytics.nn.tasks import DetectionModel
from ultralytics.utils import RANK
from ultralytics.utils.loss import E2ELoss, v8DetectionLoss

class WeightedDetectionLoss(v8DetectionLoss):
    """Detection loss with class weights applied to BCE classification loss."""

    def __init__(self, model, class_weights=None, tal_topk=10, tal_topk2=None):
        """Initialize loss with optional per-class weights for BCE."""
        super().__init__(model, tal_topk=tal_topk, tal_topk2=tal_topk2)
        if class_weights is not None:
            self.bce = nn.BCEWithLogitsLoss(
                pos_weight=class_weights.to(self.device),
                reduction="none",
            )

class WeightedE2ELoss(E2ELoss):
    """E2E Loss with class weights for YOLO26."""

    def __init__(self, model, class_weights=None):
        """Initialize E2E loss with weighted detection loss."""

        def weighted_loss_fn(model, tal_topk=10, tal_topk2=None):
            return WeightedDetectionLoss(model, class_weights=class_weights, tal_topk=tal_topk, tal_topk2=tal_topk2)

        super().__init__(model, loss_fn=weighted_loss_fn)

class WeightedDetectionModel(DetectionModel):
    """Detection model that uses class-weighted loss."""

    def init_criterion(self):
        """Initialize weighted loss criterion with per-class weights."""
        class_weights = torch.ones(self.nc)
        class_weights[0] = 2.0  # upweight class 0
        class_weights[1] = 3.0  # upweight rare class 1
        return WeightedE2ELoss(self, class_weights=class_weights)

class WeightedTrainer(DetectionTrainer):
    """Trainer that returns a WeightedDetectionModel."""

    def get_model(self, cfg=None, weights=None, verbose=True):
        """Return a WeightedDetectionModel."""
        model = WeightedDetectionModel(cfg, nc=self.data["nc"], verbose=verbose and RANK == -1)
        if weights:
            model.load(weights)
        return model

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=10, trainer=WeightedTrainer)
Berechnung von Gewichten aus dem Datensatz

Du kannst Klassengewichte automatisch aus der Label-Verteilung deines Datensatzes berechnen. Ein gängiger Ansatz ist die inverse Häufigkeitsgewichtung:

import numpy as np

# class_counts: number of instances per class
class_counts = np.array([5000, 200, 3000])
# Inverse frequency: rarer classes get higher weight
class_weights = max(class_counts) / class_counts
# Result: [1.0, 25.0, 1.67]

Link to this sectionSpeichern des besten Modells nach benutzerdefinierter Metrik#

The trainer saves best.pt based on fitness, which defaults to 0.9 × mAP@0.5:0.95 + 0.1 × mAP@0.5. To use a different metric (like mAP@0.5 or recall), override validate() and return your chosen metric as the fitness value. The built-in save_model() will then use it automatically:

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer

class CustomSaveTrainer(DetectionTrainer):
    """Trainer that saves the best model based on mAP@0.5 instead of default fitness."""

    def validate(self):
        """Override fitness to use mAP@0.5 for best model selection."""
        metrics, fitness = super().validate()
        if metrics:
            fitness = metrics.get("metrics/mAP50(B)", fitness)
            if self.best_fitness is None or fitness > self.best_fitness:
                self.best_fitness = fitness
        return metrics, fitness

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=20, trainer=CustomSaveTrainer)
Verfügbare Metriken

Gängige Metriken, die nach der Validierung in self.metrics verfügbar sind, umfassen:

SchlüsselBeschreibung
metrics/precision(B)Präzision
metrics/recall(B)Abruf
metrics/mAP50(B)mAP bei IoU 0,5
metrics/mAP50-95(B)mAP bei IoU 0,5:0,95

Link to this sectionEinfrieren und Auftauen des Backbones#

Transfer-Learning-Workflows profitieren oft davon, das vortrainierte Backbone für die ersten N Epochen einzufrieren, damit sich der Detektionskopf anpassen kann, bevor das gesamte Netzwerk feinabgestimmt wird. Ultralytics bietet einen freeze-Parameter an, um Schichten zu Beginn des Trainings einzufrieren, und du kannst einen Callback verwenden, um sie nach N Epochen aufzutauen:

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer
from ultralytics.utils import LOGGER

FREEZE_EPOCHS = 5

def unfreeze_backbone(trainer):
    """Callback to unfreeze all layers after FREEZE_EPOCHS."""
    if trainer.epoch == FREEZE_EPOCHS:
        LOGGER.info(f"Epoch {trainer.epoch}: Unfreezing all layers for fine-tuning")
        for name, param in trainer.model.named_parameters():
            if not param.requires_grad:
                param.requires_grad = True
                LOGGER.info(f"  Unfroze: {name}")
        trainer.freeze_layer_names = [".dfl"]

class FreezingTrainer(DetectionTrainer):
    """Trainer with backbone freezing for first N epochs."""

    def __init__(self, *args, **kwargs):
        """Initialize and register the unfreeze callback."""
        super().__init__(*args, **kwargs)
        self.add_callback("on_train_epoch_start", unfreeze_backbone)

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=20, freeze=10, trainer=FreezingTrainer)

Der Parameter freeze=10 gefriert die ersten 10 Schichten (das Backbone) zu Trainingsbeginn ein. Der on_train_epoch_start-Callback wird zu Beginn jeder Epoche ausgelöst und taut alle Parameter auf, sobald die Einfrierperiode abgeschlossen ist.

Auswahl dessen, was eingefroren werden soll
  • freeze=10 friert die ersten 10 Schichten ein (typischerweise das Backbone bei YOLO-Architekturen)
  • freeze=[0, 1, 2, 3] friert spezifische Schichten nach Index ein
  • Höhere FREEZE_EPOCHS-Werte geben dem Kopf mehr Zeit zur Anpassung, bevor sich das Backbone ändert

Link to this sectionLernraten pro Schicht#

Verschiedene Teile des Netzwerks können von unterschiedlichen Lernraten profitieren. Eine gängige Strategie besteht darin, eine niedrigere Lernrate für das vortrainierte Backbone zu verwenden, um gelernte Merkmale zu erhalten, während der Detektionskopf sich mit einer höheren Rate schneller anpassen kann:

import torch

from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer
from ultralytics.utils import LOGGER
from ultralytics.utils.torch_utils import unwrap_model

class PerLayerLRTrainer(DetectionTrainer):
    """Trainer with different learning rates for backbone and head."""

    def build_optimizer(self, model, name="auto", lr=0.001, momentum=0.9, decay=1e-5, iterations=1e5):
        """Build optimizer with separate learning rates for backbone and head."""
        backbone_params = []
        head_params = []

        for k, v in unwrap_model(model).named_parameters():
            if not v.requires_grad:
                continue
            is_backbone = any(k.startswith(f"model.{i}.") for i in range(10))
            if is_backbone:
                backbone_params.append(v)
            else:
                head_params.append(v)

        backbone_lr = lr * 0.1

        optimizer = torch.optim.AdamW(
            [
                {"params": backbone_params, "lr": backbone_lr, "weight_decay": decay},
                {"params": head_params, "lr": lr, "weight_decay": decay},
            ],
        )

        LOGGER.info(
            f"PerLayerLR optimizer: backbone ({len(backbone_params)} params, lr={backbone_lr}) "
            f"| head ({len(head_params)} params, lr={lr})"
        )
        return optimizer

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=20, trainer=PerLayerLRTrainer)

Link to this sectionRT-DETR-Variante#

Für RT-DETR ist das Muster mit zwei Verfeinerungen identisch. Die Backbone-Länge wird aus model.yaml["backbone"] gelesen, sodass derselbe Trainer über RT-DETR-Varianten (RT-DETR-L, RT-DETR-X, ResNet-50/101 Backbones) hinweg funktioniert, ohne Schichtanzahlen hardcodieren zu müssen. Parameter werden innerhalb jedes Abschnitts zudem in Gewichtungs-, BatchNorm- und Bias-Gruppen aufgeteilt, sodass Weight Decay von BatchNorm-Parametern und Biases ausgeschlossen wird, was der Richtlinie des Standard-Trainers entspricht. Dies ist besonders nützlich für die Feinabstimmung von RT-DETR, bei der der Dekoder-Kopf typischerweise zufällig initialisiert wird, während das Backbone vortrainierte Merkmale trägt, die von einer niedrigeren Lernrate profitieren:

import torch
from torch import nn

from ultralytics import RTDETR
from ultralytics.models.rtdetr.train import RTDETRTrainer
from ultralytics.utils import LOGGER, colorstr
from ultralytics.utils.torch_utils import unwrap_model

class RTDETRBackboneLRTrainer(RTDETRTrainer):
    """RT-DETR trainer with a lower learning rate for backbone parameters."""

    backbone_lr_ratio = 0.1  # backbone learning rate as a fraction of head learning rate

    def build_optimizer(self, model, name="auto", lr=0.001, momentum=0.9, decay=1e-5, iterations=1e5):
        """Build an AdamW optimizer with six param groups: head and backbone x {weight, bn, bias}."""
        # Resolve optimizer name; "auto" maps to AdamW with RT-DETR-style defaults
        canonical = {"Adam", "Adamax", "AdamW", "NAdam", "RAdam", "auto"}
        name = {x.lower(): x for x in canonical}.get(name.lower(), name)
        if name == "auto":
            name, lr, momentum = "AdamW", 1e-4, 0.9
        self.args.warmup_bias_lr = 0.0  # RT-DETR warms biases from 0, unlike YOLO's 0.1
        if name not in {"Adam", "Adamax", "AdamW", "NAdam", "RAdam"}:
            raise NotImplementedError(f"This trainer only supports AdamW-family optimizers; got {name}")

        # Identify backbone parameters from model.yaml and route each param into a (section, kind) group
        unwrapped = unwrap_model(model)
        backbone_len = len(unwrapped.yaml["backbone"])
        norm_types = tuple(v for k, v in nn.__dict__.items() if "Norm" in k)
        groups = {f"{s}_{k}": [] for s in ("head", "backbone") for k in ("weight", "bn", "bias")}

        for module_name, module in unwrapped.named_modules():
            for param_name, param in module.named_parameters(recurse=False):
                if not param.requires_grad:
                    continue
                fullname = f"{module_name}.{param_name}" if module_name else param_name
                parts = fullname.split(".")
                section = (
                    "backbone"
                    if len(parts) > 1 and parts[0] == "model" and parts[1].isdigit() and int(parts[1]) < backbone_len
                    else "head"
                )
                if "bias" in param_name:
                    kind = "bias"
                elif isinstance(module, norm_types) or "logit_scale" in fullname:
                    kind = "bn"
                else:
                    kind = "weight"
                groups[f"{section}_{kind}"].append(param)

        # Build the optimizer with per-group lr and weight decay; backbone groups use lr * backbone_lr_ratio
        backbone_lr = lr * self.backbone_lr_ratio
        param_groups = [
            {"params": groups["head_weight"], "lr": lr, "weight_decay": decay, "param_group": "weight"},
            {"params": groups["head_bn"], "lr": lr, "weight_decay": 0.0, "param_group": "bn"},
            {"params": groups["head_bias"], "lr": lr, "weight_decay": 0.0, "param_group": "bias"},
            {"params": groups["backbone_weight"], "lr": backbone_lr, "weight_decay": decay, "param_group": "weight"},
            {"params": groups["backbone_bn"], "lr": backbone_lr, "weight_decay": 0.0, "param_group": "bn"},
            {"params": groups["backbone_bias"], "lr": backbone_lr, "weight_decay": 0.0, "param_group": "bias"},
        ]
        param_groups = [pg for pg in param_groups if pg["params"]]  # drop empty groups
        optimizer = getattr(torch.optim, name)(param_groups, betas=(momentum, 0.999))

        LOGGER.info(
            f"{colorstr('optimizer:')} {name}(lr={lr}, backbone_lr={backbone_lr}) with parameter groups\n"
            f"  Head:     {len(groups['head_bn'])} bn, {len(groups['head_weight'])} weight(decay={decay}), "
            f"{len(groups['head_bias'])} bias (lr={lr})\n"
            f"  Backbone: {len(groups['backbone_bn'])} bn, {len(groups['backbone_weight'])} weight(decay={decay}), "
            f"{len(groups['backbone_bias'])} bias (lr={backbone_lr})"
        )
        return optimizer

model = RTDETR("rtdetr-l.pt")
model.train(data="coco8.yaml", epochs=20, trainer=RTDETRBackboneLRTrainer)
Auswahl von `backbone_lr_ratio`

Ein gängiger Ausgangspunkt ist backbone_lr_ratio = 0.1, was dem ursprünglichen RT-DETR-Setup mit seinem HGNetV2-Backbone entspricht. Die Literatur schlägt vor, das Verhältnis umgekehrt zur Backbone-Größe und zur Skalierung der Vortrainingsdaten zu skalieren: Große Backbones, die auf sehr großen Datensätzen vortrainiert wurden (zum Beispiel ViT-L/H, trainiert mit DINO, CLIP oder MAE auf hunderten Millionen Bildern), verwenden typischerweise kleinere Verhältnisse wie 0.01 oder niedriger, um gut gelernte Merkmale zu erhalten, während kleinere Backbones mit leichterem Vortraining größere Verhältnisse wie 0.5 oder höher tolerieren.

Lernraten-Scheduler

Der integrierte Lernraten-Scheduler (cosine oder linear) findet weiterhin Anwendung auf die Basis-Lernraten der jeweiligen Gruppe. Sowohl die Backbone- als auch die Kopf-Lernrate folgen demselben Zeitplan für den Zerfall, wodurch das Verhältnis zwischen ihnen während des gesamten Trainings beibehalten wird.

Kombination von Techniken

Diese Anpassungen können in einer einzigen Trainerklasse kombiniert werden, indem mehrere Methoden überschrieben und bei Bedarf Callbacks hinzugefügt werden.

Link to this sectionSynchronisiertes BatchNorm für Multi-GPU-Training#

Beim Training auf mehreren GPUs mit DistributedDataParallel berechnen die Standard-BatchNorm2d-Schichten Statistiken unabhängig auf jeder GPU. Bei der Feinabstimmung von RT-DETR und anderen Rezepten, die kleine Batch-Größen pro GPU verwenden, können die Batch-Statistiken pro GPU verrauscht sein. PyTtorchs SyncBatchNorm synchronisiert Mittelwert und Varianz über alle Ränge für eine einzelne globale Batch-Statistik, was oft die Konvergenz verbessert, jedoch auf Kosten eines geringen Overheads bei der Inter-GPU-Kommunikation.

Die Konvertierung muss erfolgen, nachdem sich das Modell auf der GPU befindet, aber bevor DDP es umschließt. Der sauberste Hook hierfür ist set_model_attributes(), den BaseTrainer genau in diesem Fenster aufruft:

from torch import nn

from ultralytics import RTDETR
from ultralytics.models.rtdetr.train import RTDETRTrainer

class SyncBNTrainer(RTDETRTrainer):
    """RT-DETR trainer that converts BatchNorm to SyncBatchNorm for multi-GPU training."""

    def set_model_attributes(self):
        """Run the parent setup, then convert BN to SyncBatchNorm when training on multiple GPUs."""
        super().set_model_attributes()
        if self.world_size > 1:
            self.model = nn.SyncBatchNorm.convert_sync_batchnorm(self.model)

model = RTDETR("rtdetr-l.pt")
model.train(data="coco8.yaml", epochs=20, device=[0, 1], trainer=SyncBNTrainer)

Die world_size > 1-Absicherung stellt sicher, dass der Trainer auch bei Single-GPU-Läufen sicher verwendet werden kann; auf einer einzelnen GPU wird die Konvertierung übersprungen und das Training fährt mit regulärem BatchNorm2d fort. Dasselbe Muster funktioniert für YOLO, indem die Elternklasse auf DetectionTrainer umgestellt wird.

Wann man SyncBatchNorm verwenden sollte
SzenarioEmpfehlung
Multi-GPU-Training, kleiner Batch pro GPU (≤ 16)Aktivieren
Multi-GPU-Training, großer Batch pro GPU (≥ 32)Optional; geringer Nutzen
Single-GPU-TrainingNicht anwendbar (übersprungen)

Link to this sectionKonfigurierbares Gradienten-Clipping#

Der Standard-Trainer schneidet Gradienten bei max_norm=10.0 in optimizer_step() ab, ein lockerer Wert, der für YOLO-Modelle optimiert ist, bei denen Gradienten ihn selten überschreiten. Detektoren der DETR-Familie (RT-DETR, DEIM, DINO) verwenden typischerweise viel engere Werte wie 0.1, um die Cross-Attention-Schichten des Dekoders zu stabilisieren, wo Gradientenamplituden ausschlagen können. Um den Clipping-Wert zu überschreiben, leite vom Trainer ab und überschreibe optimizer_step():

import torch

from ultralytics import RTDETR
from ultralytics.models.rtdetr.train import RTDETRTrainer

class CustomClipTrainer(RTDETRTrainer):
    """RT-DETR trainer with configurable gradient clipping."""

    clip_grad_norm = 0.1  # max gradient norm; set to 0 to disable clipping

    def optimizer_step(self):
        """Run an optimizer step with a configurable gradient-norm clip."""
        self.scaler.unscale_(self.optimizer)
        if self.clip_grad_norm > 0:
            torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=self.clip_grad_norm)
        self.scaler.step(self.optimizer)
        self.scaler.update()
        self.optimizer.zero_grad()
        if self.ema:
            self.ema.update(self.model)

model = RTDETR("rtdetr-l.pt")
model.train(data="coco8.yaml", epochs=20, trainer=CustomClipTrainer)

Derselbe Trainer funktioniert für YOLO, indem die Elternklasse auf DetectionTrainer umgestellt wird (from ultralytics.models.yolo.detect import DetectionTrainer) und ein YOLO-Checkpoint mit YOLO("yolo26n.pt") geladen wird. Der Körper von optimizer_step bleibt unverändert.

Typische `clip_grad_norm`-Werte
ArchitekturfamilieTypische max_norm
RT-DETR / DEIM / DETR-Familie0.1
YOLO (Ultralytics-Standard)10.0
Clipping deaktivieren0

Link to this sectionFAQ#

Link to this sectionWie übergebe ich einen benutzerdefinierten Trainer an YOLO?#

Übergebe deine benutzerdefinierte Trainerklasse (keine Instanz) an den trainer-Parameter in model.train():

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", trainer=MyCustomTrainer)

Die YOLO-Klasse übernimmt die Trainer-Instanziierung intern. Siehe die Seite Erweiterte Anpassungen für weitere Details zur Trainer-Architektur.

Link to this sectionWhich BaseTrainer methods can I override?#

Wichtige Methoden zur Anpassung:

MethodeZweck
validate()Validierung ausführen und Metriken zurückgeben
build_optimizer()Den Optimierer konstruieren
save_model()Speichere Trainings-Checkpoints
get_model()Gib die Modellinstanz zurück
get_validator()Gib die Validator-Instanz zurück
get_dataloader()Erstelle den Dataloader
preprocess_batch()Eingabe-Batch vorverarbeiten
label_loss_items()Formatiere Loss-Elemente für die Protokollierung

Die vollständige API-Referenz findest du in der BaseTrainer-Dokumentation.

Link to this sectionKann ich Callbacks verwenden, anstatt den Trainer zu unterklassen?#

Ja, für einfachere Anpassungen sind Callbacks oft ausreichend. Zu den verfügbaren Callback-Ereignissen gehören on_train_start, on_train_epoch_start, on_train_epoch_end, on_fit_epoch_end und on_model_save. Diese ermöglichen es dir, ohne Unterklassenbildung in die Trainingsschleife einzugreifen. Das obige Beispiel zum Einfrieren des Backbones demonstriert diesen Ansatz.

Link to this sectionWie kann ich die Loss-Funktion anpassen, ohne das Modell zu unterklassen?#

Wenn deine Änderung einfacher ist (wie das Anpassen von Loss-Gewichtungen), kannst du die Hyperparameter direkt modifizieren:

model.train(data="coco8.yaml", box=10.0, cls=1.5, dfl=2.0)

Für strukturelle Änderungen am Loss (wie das Hinzufügen von Klassengewichten) musst du den Loss und das Modell unterklassen, wie im Abschnitt Klassengewichte gezeigt.

Kommentare