YOLO Vision 2026:

Personalizzazione del Trainer#

La pipeline di addestramento di Ultralytics è basata su BaseTrainer e su trainer specifici per attività come DetectionTrainer. Queste classi gestiscono autonomamente il ciclo di addestramento, la convalida, il salvataggio dei checkpoint e la registrazione. Quando ti serve maggiore controllo — tracciare metriche personalizzate, regolare la ponderazione delle perdite o implementare la pianificazione del tasso di apprendimento — puoi creare una sottoclasse del trainer e sovrascrivere metodi specifici.

Questa guida illustra sette personalizzazioni comuni:

  1. Registrazione di metriche personalizzate (punteggio F1) alla fine di ogni epoca
  2. Aggiunta di pesi di classe per gestire lo sbilanciamento delle classi
  3. Salvataggio del modello migliore in base a una metrica differente
  4. Congelamento del backbone per le prime N epoche, seguito dallo sblocco
  5. Specifica di tassi di apprendimento per livello
  6. Sincronizzazione di BatchNorm tra GPU per l'addestramento multi-GPU
  7. Configurazione del clipping dei gradienti per la regolazione della stabilità
Prerequisiti

Prima di leggere questa guida, assicurati di avere familiarità con le nozioni di base sull'addestramento di modelli YOLO e con la pagina di Personalizzazione avanzata, che tratta l'architettura BaseTrainer.

Come funzionano i trainer personalizzati#

La classe del modello YOLO accetta un parametro trainer nel metodo train(). Ciò ti consente di passare la tua classe trainer personalizzata che estende il comportamento predefinito:

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

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

    # Add your customizations here

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

Il tuo trainer personalizzato eredita tutte le funzionalità da DetectionTrainer, quindi devi solo sovrascrivere i metodi specifici che desideri personalizzare.

Registrazione di metriche personalizzate#

Il passaggio di convalida calcola precisione, richiamo e mAP. Se ti servono metriche aggiuntive come il punteggio F1 per classe, sovrascrivi 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)

Questo registra la media dell'F1 score su tutte le classi e un dettaglio per singola classe dopo ogni esecuzione della validazione.

Metriche disponibili

Il validatore fornisce accesso a molte metriche tramite self.validator.metrics.box:

AttributoDescrizione
f1F1 score per classe
image_metricsDizionario delle metriche per immagine con precision, recall, F1, TP, FP e FN
pPrecision per classe
rRecall per classe
ap50AP a IoU 0.5 per classe
apAP a IoU 0.5:0.95 per classe
mp, mrPrecision e recall medie
map50, mapMetriche mAP medie

Aggiunta di pesi alle classi#

Se il tuo dataset presenta classi sbilanciate (ad esempio, un difetto raro nell'ispezione di produzione), puoi aumentare il peso delle classi sottorappresentate nella funzione di perdita. In questo modo il modello penalizza più pesantemente le classificazioni errate sulle classi rare.

Per personalizzare la loss, crea una sottoclasse delle classi di loss, del modello e del trainer:

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)
Calcolo dei pesi dal dataset

Puoi calcolare i pesi delle classi automaticamente dalla distribuzione delle etichette del tuo dataset. Un approccio comune è la ponderazione per frequenza inversa:

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]
Caricamento di un modello con classi personalizzate

Le classi personalizzate come WeightedDetectionModel vengono memorizzate nel checkpoint per riferimento. Quando definite in uno script di addestramento appartengono al modulo __main__, quindi il caricamento di best.pt da uno script differente genera AttributeError: Can't get attribute 'WeightedDetectionModel' on <module '__main__'>.

Definisci le classi personalizzate in un modulo dedicato in modo che rimangano importabili e assicurati che tale modulo si trovi sul tuo PYTHONPATH al momento del caricamento.

# weighted_model.py
from ultralytics.nn.tasks import DetectionModel

class WeightedDetectionModel(DetectionModel):
    """Detection model that uses class-weighted loss."""
# inference script
from weighted_model import WeightedDetectionModel  # noqa: F401 - must be importable at checkpoint load time

from ultralytics import YOLO

model = YOLO("runs/detect/train/weights/best.pt")
metrics = model.val()

Salvataggio del modello migliore tramite metrica personalizzata#

Il trainer salva best.pt in base all'idoneità, che per il rilevamento è impostata per predefinizione su mAP@0.5:0.95 (pesi [0.0, 0.0, 0.0, 1.0] per [P, R, mAP@0.5, mAP@0.5:0.95]). Per utilizzare una metrica differente (come mAP@0.5 o il richiamo), sovrascrivi validate() e restituisci la metrica scelta come valore di idoneità. L'oggetto save_model() incorporato la utilizzerà quindi automaticamente:

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)
Metriche disponibili

Le metriche comuni disponibili in self.metrics dopo la convalida includono:

ChiaveDescrizione
metrics/precision(B)Precision
metrics/recall(B)Recall
metrics/mAP50(B)mAP a IoU 0.5
metrics/mAP50-95(B)mAP a IoU 0.5:0.95

Freezing e unfreezing della backbone#

I flussi di lavoro di apprendimento per trasferimento traggono spesso vantaggio dal congelamento del backbone preaddestrato per le prime N epoche, consentendo alla testa di rilevamento di adattarsi prima della messa a punto dell'intera rete. Ultralytics fornisce un parametro freeze per congelare i livelli all'inizio dell'addestramento e puoi utilizzare un callback per sbloccarli dopo N epoche:

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)

Il parametro freeze=10 congela i primi 10 livelli (indici 0-9) all'inizio dell'addestramento, coprendo la maggior parte del backbone YOLO26. Il backbone si estende dai livelli 0 al 10, quindi freeze=10 lascia l'ultimo blocco C2PSA (livello 10) addestrabile; usa freeze=11 per congelare l'intero backbone. Il callback on_train_epoch_start si attiva all'inizio di ogni epoca e scongela tutti i parametri una volta completato il periodo di congelamento.

Scegliere cosa bloccare
  • freeze=10 congela i primi 10 livelli, indici 0-9 (la maggior parte del backbone YOLO26; usa freeze=11 per includere l'ultimo blocco C2PSA al livello 10)
  • freeze=[0, 1, 2, 3] congela livelli specifici per indice
  • Valori più alti di FREEZE_EPOCHS danno alla testa più tempo per adattarsi prima che il backbone cambi

Learning rate per livello#

Parti differenti della rete possono trarre vantaggio da tassi di apprendimento differenti. Una strategia comune consiste nell'usare un tasso di apprendimento inferiore per il backbone preaddestrato per preservare le caratteristiche apprese, consentendo al contempo alla testa di rilevamento di adattarsi più rapidamente con un tasso superiore:

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 = []

        unwrapped = unwrap_model(model)
        backbone_len = len(unwrapped.yaml["backbone"])  # YOLO26 backbone spans layers 0-10 (C2PSA at layer 10)

        for k, v in unwrapped.named_parameters():
            if not v.requires_grad:
                continue
            is_backbone = any(k.startswith(f"model.{i}.") for i in range(backbone_len))
            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)

Variante RT-DETR#

Per RT-DETR lo schema è lo stesso con due perfezionamenti. La lunghezza del backbone viene letta da model.yaml["backbone"], così lo stesso trainer funziona su tutte le varianti di RT-DETR (backbone RT-DETR-L, RT-DETR-X, ResNet-50/101) senza dover inserire conteggi di livelli fissi. I parametri vengono inoltre suddivisi in gruppi di pesi, BatchNorm e bias all'interno di ciascuna sezione, in modo che il decadimento dei pesi sia escluso dai parametri BatchNorm e dai bias, rispettando la politica del trainer predefinito. Ciò è particolarmente utile per la messa a punto di RT-DETR, in cui la testa del decoder è solitamente inizializzata casualmente mentre il backbone trasporta caratteristiche preaddestrate che beneficiano di un tasso di apprendimento inferiore:

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)
Scegliere `backbone_lr_ratio`

Un punto di partenza comune è backbone_lr_ratio = 0.1, che corrisponde alla configurazione originale di RT-DETR con il suo backbone HGNetV2. La letteratura suggerisce di scalare il rapporto inversamente rispetto alle dimensioni del backbone e alla scala dei dati di preaddestramento: backbone grandi preaddestrati su dataset molto ampi (ad esempio ViT-L/H addestrati con DINO, CLIP o MAE su centinaia di milioni di immagini) utilizzano tipicamente rapporti inferiori come 0.01 o inferiori per preservare le caratteristiche ben apprese, mentre backbone più piccoli con preaddestramento più leggero tollerano rapporti maggiori come 0.5 o superiori.

Pianificatore del learning rate

Il pianificatore del tasso di apprendimento incorporato (cosine o linear) si applica comunque sopra i tassi di apprendimento di base per gruppo. Sia i tassi di apprendimento del backbone che quelli della testa seguiranno lo stesso programma di decadimento, mantenendo il rapporto tra loro per tutto l'addestramento.

Combinazione di tecniche

Queste personalizzazioni possono essere combinate in un'unica classe trainer sovrascrivendo più metodi e aggiungendo callback secondo necessità.

Synchronized BatchNorm per l'addestramento multi-GPU#

Quando si effettua l'addestramento su più GPU con DistributedDataParallel, i livelli predefiniti di BatchNorm2d calcolano le statistiche in modo indipendente su ciascuna GPU. Per la messa a punto di RT-DETR e altre ricette che utilizzano batch di dimensioni ridotte per GPU, le statistiche dei batch per GPU possono risultare rumorose. Il comando SyncBatchNorm di PyTorch sincronizza media e varianza tra tutti i ranghi per una statistica batch globale singola, il che spesso migliora la convergenza a scapito di un piccolo sovraccarico di comunicazione inter-GPU.

La conversione deve avvenire dopo che il modello si trova sulla GPU ma prima che DDP lo avvolga. Il gancio più pulito per questo è set_model_attributes(), che BaseTrainer chiama esattamente in quella finestra:

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)

La protezione world_size > 1 garantisce che il trainer sia sicuro da usare anche in esecuzioni su GPU singola; su una singola GPU la conversione viene saltata e l'addestramento procede con il normale BatchNorm2d. Lo stesso schema funziona per YOLO passando la classe genitore a DetectionTrainer.

Quando usare SyncBatchNorm
ScenarioRaccomandazione
Addestramento multi-GPU, batch ridotto per GPU (≤ 16)Abilita
Addestramento multi-GPU, batch grande per GPU (≥ 32)Opzionale; beneficio minimo
Addestramento su singola GPUNon applicabile (saltato)

Gradient clipping configurabile#

Il trainer predefinito ritaglia i gradienti a max_norm=10.0 in optimizer_step(), un valore flessibile ottimizzato per i modelli YOLO in cui i gradienti raramente lo superano. I rilevatori della famiglia DETR (RT-DETR, DEIM, DINO) utilizzano solitamente valori molto più ristretti come 0.1 per stabilizzare i livelli di attenzione incrociata del decoder, dove le grandezze dei gradienti possono subire picchi. Per sovrascrivere il valore di ritaglio, crea una sottoclasse del trainer e sovrascrivi 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)

Lo stesso trainer funziona per YOLO passando la classe genitore a DetectionTrainer (from ultralytics.models.yolo.detect import DetectionTrainer) e caricando un checkpoint YOLO con YOLO("yolo26n.pt"). Il corpo di optimizer_step rimane invariato.

Valori tipici di `clip_grad_norm`
Famiglia di architettureTipico max_norm
Famiglia RT-DETR / DEIM / DETR0.1
YOLO (Predefinito Ultralytics)10.0
Disabilita clipping0

FAQ#

  • Passa la tua classe trainer personalizzata (non un'istanza) al parametro trainer in model.train():

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

    La classe YOLO gestisce internamente l'istanziazione del trainer. Consulta la pagina di Personalizzazione avanzata per maggiori dettagli sull'architettura del trainer.

  • Metodi chiave disponibili per la personalizzazione:

    MetodoScopo
    validate()Esegui la validazione e restituisci le metriche
    build_optimizer()Costruisci l'ottimizzatore
    save_model()Salva i checkpoint dell'addestramento
    get_model()Restituisci l'istanza del modello
    get_validator()Restituisci l'istanza del validatore
    get_dataloader()Costruisci il dataloader
    preprocess_batch()Pre-elabora il batch di input
    label_loss_items()Formatta gli elementi della loss per il logging

    Per il riferimento completo dell'API, consulta la documentazione di BaseTrainer.

  • Sì, per personalizzazioni più semplici, i callback sono spesso sufficienti. Gli eventi di callback disponibili includono on_train_start, on_train_epoch_start, on_train_epoch_end, on_fit_epoch_end e on_model_save. Questi ti consentono di collegarti al ciclo di addestramento senza creare sottoclassi. L'esempio di congelamento del backbone sopra illustra questo approccio.

  • Se la tua modifica è più semplice (come la regolazione dei guadagni di perdita), puoi modificare direttamente gli iperparametri:

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

    Per modifiche strutturali alla perdita (come l'aggiunta di pesi di classe), devi creare una sottoclasse della perdita e del modello come mostrato nella sezione sui pesi di classe.

Commenti