Trainer'ı Özelleştirme#
Ultralytics eğitim işlem hattı, BaseTrainer ve DetectionTrainer gibi göreve özgü trainer'lar etrafında oluşturulmuştur. Bu sınıflar eğitim döngüsünü, doğrulamayı, kontrol noktası kaydetmeyi ve günlük kaydını kullanıma hazır şekilde yönetir. Özel metrikleri izlemek, kayıp ağırlıklandırmasını ayarlamak veya öğrenme hızı zamanlamaları uygulamak gibi daha fazla denetime ihtiyaç duyduğunda trainer sınıfından türetebilir ve belirli yöntemleri geçersiz kılabilirsin.
Bu kılavuzda yaygın yedi özelleştirme ele alınır:
- Her epoch sonunda özel metrikleri (F1 skoru) günlüğe kaydetme
- Sınıf dengesizliğini ele almak için sınıf ağırlıkları ekleme
- Farklı bir metriğe göre en iyi modeli kaydetme
- İlk N epoch boyunca omurgayı dondurma, ardından buzunu çözme
- Katman başına öğrenme hızlarını belirtme
- Çoklu GPU eğitimi için BatchNorm'u GPU'lar arasında eşzamanlama
- Kararlılık ayarı için gradyan kırpmayı yapılandırma
Bu kılavuzu okumadan önce YOLO modellerini eğitmenin temellerine ve BaseTrainer mimarisini ele alan Gelişmiş Özelleştirme sayfasına aşina olduğundan emin ol.
Özel Trainer'lar Nasıl Çalışır#
YOLO model sınıfı, train() yönteminde bir trainer parametresi kabul eder. Bu, varsayılan davranışı genişleten kendi trainer sınıfını aktarmana 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."""
# Add your customizations here
model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=10, trainer=CustomTrainer)Özel trainer'ın DetectionTrainer sınıfındaki tüm işlevleri devralır; bu nedenle yalnızca özelleştirmek istediğin belirli yöntemleri geçersiz kılman gerekir.
Özel Metrikleri Günlüğe Kaydetme#
Doğrulama adımı precision, recall ve mAP değerlerini hesaplar. Sınıf başına F1 skoru gibi ek metriklere ihtiyacın varsa validate() yöntemini geçersiz kıl:
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
mean_f1 = float(np.mean(f1_per_class)) if len(f1_per_class) 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)]
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 işlem, doğrulamada temsil edilen tüm sınıflardaki ortalama F1 skorunu ve her doğrulama çalışmasından sonra sınıf başına ayrıntıları günlüğe kaydeder.
Doğrulayıcı, self.validator.metrics.box üzerinden birçok metriğe erişim sağlar:
| Öznitelik | Açıklama |
|---|---|
f1 | Sınıf başına F1 skoru |
image_metrics | Precision, recall, F1, TP, FP ve FN değerlerini içeren görüntü başına metrik sözlüğü |
p | Sınıf başına precision |
r | Sınıf başına recall |
ap50 | Sınıf başına IoU 0.5 değerindeki AP |
ap | Sınıf başına IoU 0.5:0.95 değerindeki AP |
mp, mr | Ortalama precision ve recall |
map50, map | Ortalama AP metrikleri |
Sınıf Ağırlıkları Ekleme#
Sınıflandırma kaybına normalize edilmiş ters frekans ağırlıkları uygulamak için cls_pw değerini 0.0 ile 1.0 arasına ayarla. Mevcut ağırlık hesaplamasını yalnızca elle belirlenmiş oranlara ihtiyaç duyduğunda geçersiz kıl:
import numpy as np
from ultralytics import YOLO
from ultralytics.models.yolo.detect import DetectionTrainer
class WeightedTrainer(DetectionTrainer):
"""Detection trainer with hand-picked class-weight ratios."""
def compute_class_weights(self, class_counts):
"""Return custom per-class weights for the production loss owner."""
weights = np.ones_like(class_counts)
weights[0] = 2.0
weights[1] = 3.0
return weights
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=10, cls_pw=1.0, trainer=WeightedTrainer)set_class_weights() bu değerleri ortalaması 1.0 olacak şekilde normalleştirir ve model üzerinde saklar; mevcut algılama kaybı da bu değerleri uygular. Yukarıdaki indisler için en az iki sınıfa sahip bir veri kümesi gerekir.
Özel Metrikle En İyi Modeli Kaydetme#
Trainer, best.pt değerini uygunluk değerine göre kaydeder; algılama için bu değer varsayılan olarak mAP@0.5:0.95 olur ([0.0, 0.0, 0.0, 1.0], [P, R, mAP@0.5, mAP@0.5:0.95] değerlerine ağırlık verir). Farklı bir metrik (örneğin mAP@0.5 veya recall) kullanmak için validate() yöntemini geçersiz kıl ve seçtiğin metriği uygunluk değeri olarak döndür. Yerleşik save_model() bunu otomatik olarak kullanı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."""
previous_best = self.best_fitness
metrics, fitness = super().validate()
if metrics is None:
return metrics, fitness
fitness = metrics["metrics/mAP50(B)"]
self.best_fitness = fitness if previous_best is None else max(previous_best, fitness)
return metrics, fitness
model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=20, trainer=CustomSaveTrainer)BaseTrainer.validate(), varsayılan metriği kullanarak best_fitness değerini günceller; bu nedenle yöntemi çağırmadan önce önceki değerini al.
Doğrulama sonrasında self.metrics içinde kullanılabilen yaygın metrikler şunlardır:
| Anahtar | Açıklama |
|---|---|
metrics/precision(B) | Precision |
metrics/recall(B) | Recall |
metrics/mAP50(B) | IoU 0.5 değerinde mAP |
metrics/mAP50-95(B) | IoU 0.5:0.95 değerinde mAP |
Omurgayı Dondurma ve Buzunu Çözme#
Transfer öğrenimi iş akışları, ilk N epoch boyunca önceden eğitilmiş omurganın dondurulmasından ve algılama başlığının tüm ağda ince ayar yapılmadan önce uyum sağlamasına izin verilmesinden sıklıkla yararlanır. Ultralytics, eğitimin başında katmanları dondurmak için bir freeze parametresi sağlar; N epoch sonrasında bunların buzunu çözmek için bir geri çağırma kullanabilirsin:
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 the user-requested layers after FREEZE_EPOCHS."""
if trainer.epoch == FREEZE_EPOCHS:
user_freeze = [x for x in trainer.freeze_layer_names if x not in {".dfl", "teacher_model."}]
LOGGER.info(f"Epoch {trainer.epoch}: Unfreezing requested layers for fine-tuning")
for name, param in trainer.model.named_parameters():
if (
not param.requires_grad
and ".dfl" not in name
and "teacher_model." not in name
and any(x in name for x in user_freeze)
):
param.requires_grad = True
LOGGER.info(f" Unfroze: {name}")
trainer.freeze_layer_names = [x for x in trainer.freeze_layer_names if x not in user_freeze]
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 parametresi, eğitimin başlangıcında ilk 10 katmanı (0-9 indisleri) dondurur; bu, YOLO26 omurgasının çoğunu kapsar. Omurga 0-10 katmanlarını kapsar; dolayısıyla freeze=10, son C2PSA bloğunu (10. katman) eğitilebilir bırakır. Omurganın tamamını dondurmak için freeze=11 kullan. on_train_epoch_start geri çağırması her epoch'un başında çalışır ve dondurma süresi tamamlandığında istenen katmanların buzunu çözer; kalıcı olarak dondurulmuş DFL ve damıtma öğreticisi parametrelerini korur.
freeze=10, 0-9 indislerindeki ilk 10 katmanı dondurur (YOLO26 omurgasının çoğu; 10. katmandaki son C2PSA bloğunu dahil etmek içinfreeze=11kullan)freeze=[0, 1, 2, 3], belirli katmanları indislerine göre dondurur- Daha yüksek
FREEZE_EPOCHSdeğerleri, omurga değişmeden önce başlığa uyum sağlaması için daha fazla zaman tanır
Katman Başına Öğrenme Hızları#
Ağın farklı bölümleri farklı öğrenme hızlarından yararlanabilir. Yaygın bir strateji, öğrenilmiş özellikleri korumak için önceden eğitilmiş omurgada daha düşük bir öğrenme hızı kullanırken algılama başlığının daha yüksek bir hızla daha hızlı uyum sağlamasına izin vermektir:
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."""
backbone_lr_ratio = 0.1
def build_optimizer(self, model, name="auto", lr=0.001, momentum=0.9, decay=1e-5, iterations=1e5):
"""Reuse the trainer optimizer and lower its backbone parameter-group rates."""
optimizer = super().build_optimizer(model, name, lr, momentum, decay, iterations)
unwrapped = unwrap_model(model)
backbone_len = len(unwrapped.yaml["backbone"])
backbone = {
id(p)
for name, p in unwrapped.named_parameters()
if any(name.startswith(f"model.{i}.") for i in range(backbone_len))
}
groups = []
for group in optimizer.param_groups:
head_params = [p for p in group["params"] if id(p) not in backbone]
backbone_params = [p for p in group["params"] if id(p) in backbone]
if head_params:
groups.append({**group, "params": head_params})
if backbone_params:
groups.append({**group, "params": backbone_params, "lr": group["lr"] * self.backbone_lr_ratio})
optimizer.param_groups = groups
LOGGER.info(f"PerLayerLR: {len(backbone)} backbone params at {self.backbone_lr_ratio}x the head rate")
return optimizer
model = YOLO("yolo26n.pt")
model.train(data="coco8.yaml", epochs=20, trainer=PerLayerLRTrainer)RT-DETR Varyantı#
RT-DETR için üst sınıf olarak RTDETRTrainer ile aynı geçersiz kılma yöntemini kullan ve kontrol noktasını RTDETR("rtdetr-l.pt") ile yükle.
Çoklu GPU Eğitimi için Eşzamanlanmış BatchNorm#
DistributedDataParallel ile birden fazla GPU üzerinde eğitim yaparken varsayılan BatchNorm2d katmanları istatistikleri her GPU'da bağımsız olarak hesaplar. RT-DETR ince ayarı ve GPU başına küçük toplu iş boyutları kullanan diğer tariflerde GPU başına toplu iş istatistikleri gürültülü olabilir. PyTorch'un SyncBatchNorm bileşeni, tek bir küresel toplu iş istatistiği için ortalama ve varyansı tüm rank'ler arasında eşzamanlar; bu işlem, GPU'lar arası iletişim ek yükünün küçük bir maliyeti karşılığında yakınsamayı sıklıkla iyileştirir.
Dönüştürme, model GPU'ya alındıktan sonra ancak DDP modeli sarmalamadan önce gerçekleşmelidir. Bunun için en temiz kanca set_model_attributes()'dır; BaseTrainer bu kancayı tam olarak söz konusu aralıkta çağırır:
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)world_size > 1 koruması, trainer'ın tek GPU çalıştırmalarında da güvenle kullanılmasını sağlar; tek GPU'da dönüştürme atlanır ve eğitim normal BatchNorm2d ile devam eder. Üst sınıfı DetectionTrainer olarak değiştirerek aynı yaklaşım YOLO için de çalışır.
| Senaryo | Öneri |
|---|---|
| Çoklu GPU eğitimi, GPU başına küçük toplu iş (≤ 16) | Etkinleştir |
| Çoklu GPU eğitimi, GPU başına büyük toplu iş (≥ 32) | İsteğe bağlı; küçük fayda |
| Tek GPU eğitimi | Geçerli değil (atlanır) |
Yapılandırılabilir Gradyan Kırpma#
Varsayılan trainer, gradyanları optimizer_step() içinde max_norm=10.0 değerine kırpar; bu, gradyanların nadiren aştığı YOLO modelleri için ayarlanmış gevşek bir değerdir. DETR ailesi dedektörleri (RT-DETR, DEIM, DINO), gradyan büyüklüklerinin sıçrayabildiği decoder'ın çapraz dikkat katmanlarını kararlı hâle getirmek için genellikle 0.1 gibi çok daha sıkı değerler kullanır. Kırpma değerini geçersiz kılmak için trainer sınıfından türet ve optimizer_step() yöntemini geçersiz kıl:
import torch
from ultralytics import RTDETR
from ultralytics.models.rtdetr.train import RTDETRTrainer
from ultralytics.utils.torch_utils import TORCH_2_0
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:
kwargs = {"foreach": False} if self.device.type == "npu" and TORCH_2_0 else {}
torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=self.clip_grad_norm, **kwargs)
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)Üst sınıfı DetectionTrainer (from ultralytics.models.yolo.detect import DetectionTrainer) olarak değiştirerek aynı trainer YOLO için de çalışır; YOLO kontrol noktasını YOLO("yolo26n.pt") ile yükle. optimizer_step gövdesi değişmeden kalır.
| Mimari ailesi | Tipik max_norm |
|---|---|
| RT-DETR / DEIM / DETR ailesi | 0.1 |
| YOLO (Ultralytics varsayılanı) | 10.0 |
| Kırpmayı devre dışı bırak | 0 |
SSS#
Özel trainer sınıfını (bir örneğini değil)
model.train()içindekitrainerparametresine aktar:from ultralytics import YOLO from ultralytics.models.yolo.detect import DetectionTrainer class MyCustomTrainer(DetectionTrainer): """A custom trainer that extends DetectionTrainer.""" model = YOLO("yolo26n.pt") model.train(data="coco8.yaml", trainer=MyCustomTrainer)YOLOsınıfı trainer örneği oluşturma işlemini dahili olarak yönetir. Trainer mimarisi hakkında daha fazla bilgi için Gelişmiş Özelleştirme sayfasına bak.Özelleştirme için kullanılabilen temel yöntemler:
Yöntem Amaç validate()Doğrulamayı çalıştırır ve metrikleri döndürür build_optimizer()Optimizer'ı oluşturur save_model()Eğitim kontrol noktalarını kaydeder get_model()Model örneğini döndürür get_validator()Doğrulayıcı örneğini döndürür get_dataloader()Veri yükleyiciyi oluşturur preprocess_batch()Girdi toplu işini ön işler label_loss_items()Kayıp öğelerini günlük kaydı için biçimlendirir Eksiksiz API referansı için
BaseTrainerbelgelerine bak.Evet, daha basit özelleştirmeler için geri çağırmalar genellikle yeterlidir. Kullanılabilir geri çağırma olayları arasında
on_train_start,on_train_epoch_start,on_train_epoch_end,on_fit_epoch_endveon_model_savebulunur. Bunlar, trainer sınıfından türetmeden eğitim döngüsüne bağlanmana olanak tanır. Yukarıdaki omurga dondurma örneği bu yaklaşımı gösterir.Değişikliğin daha basitse (örneğin kayıp katsayılarını ayarlamak), hiperparametreleri doğrudan değiştirebilirsin:
from ultralytics import YOLO model = YOLO("yolo26n.pt") model.train(data="coco8.yaml", box=10.0, cls=1.5, dfl=2.0)YOLO26'da
dfl, algılama başlığıreg_max: 1kullandığı için günlüğe kaydedilenl1_lossdeğerini ölçeklendirir;reg_max > 1kullanan modellerde isedfl_lossdeğerini ölçeklendirir.