İçeriğe geç

Eğiticiyi Özelleştirme

Ultralytics eğitim hattı şunun etrafında inşa edilmiştir: BaseTrainer ve şunun gibi göreve özel eğiticiler: DetectionTrainer. Bu sınıflar, eğitim döngüsünü, doğrulamayı, kontrol noktası oluşturmayı ve günlük kaydını hazır olarak yönetir. Daha fazla kontrole ihtiyacınız olduğunda — özel metrikleri track etme, kayıp ağırlığını ayarlama veya öğrenme oranı çizelgeleri uygulama — eğiticiyi alt sınıflandırabilir ve belirli yöntemleri geçersiz kılabilirsiniz.

Bu kılavuz, beş yaygın özelleştirmeyi ele almaktadır:

  1. Özel metrikleri (F1 skoru) kaydetme her epoch sonunda
  2. Sınıf ağırlıkları ekleme sınıf dengesizliğini ele almak için
  3. En iyi modeli kaydetme farklı bir metriğe göre
  4. Backbone'u dondurma ilk N epoch için, sonra çözme
  5. Katman başına öğrenme oranlarını belirtme

Ön koşullar

Bu kılavuzu okumadan önce, şunların temellerine aşina olduğunuzdan emin olun: YOLO modellerini eğitme ve Gelişmiş Özelleştirme sayfası, şunları kapsar: BaseTrainer mimarisi.

Özel Eğiticiler Nasıl Çalışır?

YOLO model sınıfı bir trainer parametresi içinde train() metodunu kabul eder. Bu, varsayılan davranışı genişleten kendi eğitici sınıfınızı geçirmenize olanak tanır:

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)

Özel eğiticiniz tüm işlevselliği şuradan devralır: DetectionTrainer, bu nedenle yalnızca özelleştirmek istediğiniz belirli metotları geçersiz kılmanız gerekir.

Özel Metrikleri Günlüğe Kaydetme

doğrulama adımı hesaplar kesinlik, duyarlılık (recall)ve mAP. Sınıf başına gibi ek metrikler gerekiyorsa F1 skoru, geçersiz kılın 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)

Bu, her doğrulama çalıştırmasından sonra tüm sınıflar genelindeki ortalama F1 skorunu ve sınıf başına dökümü kaydeder.

Mevcut Metrikler

Doğrulayıcı, birçok metriğe şunlar aracılığıyla erişim sağlar: self.validator.metrics.box:

ÖzellikAçıklama
f1Sınıf başına F1 skoru
pSınıf başına kesinlik (Precision)
rSınıf başına duyarlılık (Recall)
ap50Sınıf başına IoU 0.5'teki AP
apSınıf başına IoU 0.5:0.95'teki AP
mp, mrOrtalama kesinlik ve duyarlılık
map50, mapOrtalama AP metrikleri

Sınıf Ağırlıkları Ekleme

Veri setiniz dengesiz sınıflara sahipse (örneğin, üretim denetiminde nadir bir kusur), az temsil edilen sınıfları kayıp fonksiyonunda ağırlıklandırabilirsiniz. Bu, modelin nadir sınıflardaki yanlış sınıflandırmaları daha ağır bir şekilde cezalandırmasını sağlar.

Kaybı özelleştirmek için kayıp sınıflarını, modeli ve eğiticiyi alt sınıflara ayırın:

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)

Veri Setinden Ağırlık Hesaplama

Sınıf ağırlıklarını veri setinizin etiket dağılımından otomatik olarak hesaplayabilirsiniz. Yaygın bir yaklaşım ters frekans ağırlıklandırmasıdır:

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]

Özel Metriğe Göre En İyi Modeli Kaydetme

Eğitici kaydeder best.pt varsayılan olarak uygunluğa göre 0.9 × mAP@0.5:0.95 + 0.1 × mAP@0.5. Farklı bir metrik kullanmak için (örneğin mAP@0.5 veya duyarlılık), geçersiz kılın validate() ve seçtiğiniz metriği uygunluk değeri olarak döndürün. Yerleşik save_model() daha sonra otomatik olarak kullanacaktır:

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)

Mevcut Metrikler

Şurada bulunan yaygın metrikler: self.metrics doğrulama sonrası şunları içerir:

AnahtarAçıklama
metrics/precision(B)Kesinlik
metrics/recall(B)Duyarlılık (Recall)
metrics/mAP50(B)0.5 IoU'da mAP
metrics/mAP50-95(B)0.5:0.95 IoU'da mAP

Backbone'u Dondurma ve Çözme

Aktarım öğrenimi İş akışları, genellikle önceden eğitilmiş backbone'u ilk N epoch boyunca dondurmaktan faydalanır; bu, detection head'in uyum sağlamasına olanak tanır, ardından ince ayar tüm ağı. Ultralytics bir freeze parametre sağlar ve bir geri çağırma (callback) N epoch sonra dondurmayı çözmek için:

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)

freeze=10 parametre, eğitimin başlangıcında ilk 10 katmanı (backbone'u) dondurur. Bu on_train_epoch_start callback, her epoch'un başlangıcında tetiklenir ve dondurma süresi tamamlandığında tüm parametrelerin dondurmasını çözer.

Neyi Donduracağınızı Seçmek

  • freeze=10 ilk 10 katmanı (genellikle YOLO mimarilerindeki backbone'u) dondurur
  • freeze=[0, 1, 2, 3] belirli katmanları indekse göre dondurur
  • Daha Yüksek FREEZE_EPOCHS değerleri, backbone değişmeden önce head'e uyum sağlaması için daha fazla zaman tanır

Katman Başına Öğrenme Oranları

Ağın farklı bölümleri, farklı öğrenme oranlarından faydalanabilir. Yaygın bir strateji, öğrenilmiş özellikleri korumak için önceden eğitilmiş backbone için daha düşük bir öğrenme oranı kullanırken, detection head'in daha yüksek bir oranla daha hızlı uyum sağlamasına olanak tanımaktır:

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)

Öğrenme Oranı Zamanlayıcısı

Dahili öğrenme oranı zamanlayıcısı (cosine veya linear) grup başına temel öğrenme oranlarının üzerinde hala uygulanır. Hem backbone hem de head öğrenme oranları aynı düşüş programını takip edecek ve eğitim boyunca aralarındaki oranı koruyacaktır.

Teknikleri Birleştirmek

Bu özelleştirmeler, birden fazla yöntemi geçersiz kılarak ve gerektiğinde callback'ler ekleyerek tek bir eğitici sınıfında birleştirilebilir.

SSS

YOLO'ya özel bir eğiticiyi nasıl iletirim?

Özel eğitici sınıfınızı (bir örnek değil) şuraya iletin: trainer parametresi içinde model.train():

from ultralytics import YOLO

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

YOLO sınıfı, eğitici örneklendirmesini dahili olarak yönetir. Daha fazla bilgi için Gelişmiş Özelleştirme eğitici mimarisi hakkında daha fazla ayrıntı için sayfasına bakın.

Hangi BaseTrainer yöntemlerini geçersiz kılabilirim?

Özelleştirme için mevcut temel yöntemler:

MetotAmaç
validate()Doğrulamayı çalıştırın ve metrikleri döndürün
build_optimizer()Optimizer'ı oluştur
save_model()Eğitim kontrol noktalarını kaydet
get_model()Model örneğini döndür
get_validator()Doğrulayıcı örneğini döndür
get_dataloader()Dataloader'ı oluştur
preprocess_batch()Giriş batch'ini ön işle
label_loss_items()Loglama için kayıp öğelerini biçimlendir

Tam API referansı için şuraya bakın: BaseTrainer belgeleme.

Eğiticiyi alt sınıflandırmak yerine geri çağırmaları (callbacks) kullanabilir miyim?

Evet, daha basit özelleştirmeler için, callback'ler genellikle yeterlidir. Mevcut callback olayları şunları içerir: on_train_start, on_train_epoch_start, on_train_epoch_end, on_fit_epoch_endve on_model_save. Bunlar, alt sınıflandırma yapmadan eğitim döngüsüne müdahale etmenizi sağlar. Yukarıdaki backbone dondurma örneği bu yaklaşımı göstermektedir.

Modeli alt sınıflandırmadan kayıp fonksiyonunu nasıl özelleştiririm?

Değişikliğiniz daha basitse (kayıp kazançlarını ayarlamak gibi), hiperparametreleri doğrudan değiştirebilirsiniz:

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

Kayba yapısal değişiklikler için (sınıf ağırlıkları eklemek gibi), sınıf ağırlıkları bölümünde gösterildiği gibi kaybı ve modeli alt sınıflamanız gerekir.



📅 26 gün önce oluşturuldu ✏️ 19 gün önce güncellendi
raimbekovmonuralpszr

Yorumlar