Leitfaden zur Modell-YAML-Konfiguration#
Die Modell-YAML-Konfigurationsdatei dient als architektonische Blaupause für Ultralytics neuronale Netze. Sie definiert, wie Schichten verbunden sind, welche Parameter jedes Modul verwendet und wie das gesamte Netzwerk über verschiedene Modellgrößen hinweg skaliert.
Konfigurationsstruktur#
Modell-YAML-Dateien sind in drei Hauptabschnitte unterteilt, die zusammenarbeiten, um die Architektur zu definieren.
Abschnitt Parameter#
Der parameters-Abschnitt legt die globalen Eigenschaften und das Skalierungsverhalten des Modells fest:
# Parameters
nc: 80 # number of classes
scales: # compound scaling constants [depth, width, max_channels]
n: [0.50, 0.25, 1024] # nano: shallow layers, narrow channels
s: [0.50, 0.50, 1024] # small: shallow depth, standard width
m: [0.50, 1.00, 512] # medium: moderate depth, full width
l: [1.00, 1.00, 512] # large: full depth and width
x: [1.00, 1.50, 512] # extra-large: maximum performance
kpt_shape: [17, 3] # pose models onlynclegt die Anzahl der Klassen fest, die das Modell vorhersagt.scalesdefiniert zusammengesetzte Skalierungsfaktoren, die die Modelltiefe, -breite und die maximale Kanalanzahl anpassen, um verschiedene Größenvarianten (von nano bis extra-large) zu erzeugen.kpt_shapegilt für Pose-Modelle. Es kann[N, 2]für(x, y)Schlüsselpunkte oder[N, 3]für(x, y, visibility)sein.
Mit dem Parameter scales kannst du mehrere Modellgrößen aus einer einzigen Basis-YAML generieren. Wenn du beispielsweise yolo26n.yaml lädst, liest Ultralytics die Basis-yolo26.yaml und wendet die n-Skalierungsfaktoren (depth=0.50, width=0.25) an, um die Nano-Variante zu erstellen.
Wenn dein Datensatz einen anderen Wert für nc oder kpt_shape angibt, überschreibt Ultralytics die Modellkonfiguration zur Laufzeit automatisch, damit sie zur Dataset-YAML passt.
Backbone- und Head-Architektur#
Die Modellarchitektur besteht aus Backbone- (Merkmalsextraktion) und Head- (aufgabenspezifische) Abschnitten:
nc: 80
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0: Initial convolution
- [-1, 1, Conv, [128, 3, 2]] # 1: Downsample
- [-1, 3, C2f, [128, True]] # 2: Feature processing
head:
- [-1, 1, nn.Upsample, [None, 2, nearest]] # 3: Upsample
- [[-1, 0], 1, Concat, [1]] # 4: Spatially compatible skip connection
- [-1, 3, C2f, [256]] # 5: Process features
- [[5], 1, Detect, [nc]] # 6: Detection layerSchichtindizes laufen über das Backbone und den Head hinweg weiter, und verkettete Feature-Maps müssen übereinstimmende räumliche Dimensionen aufweisen.
Format der Schichtspezifikation#
Jede Schicht folgt dem einheitlichen Muster: [from, repeats, module, args]
| Komponente | Zweck | Beispiele |
|---|---|---|
| from | Eingangsverbindungen | -1 (vorherige), 6 (Schicht 6), [4, 6, 8] (Multi-Input) |
| repeats | Anzahl der Wiederholungen | 1 (einzeln), 3 (3 Mal wiederholen) |
| module | Modultyp | Conv, C2f, TorchVision, Detect |
| args | Modulargumente | [64, 3, 2] (Kanäle, Kernel, Schrittweite) |
Verbindungsmuster#
Das Feld from erzeugt flexible Datenflussmuster in deinem gesamten Netzwerk:
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layerSchichten werden beginnend bei 0 indiziert. Negative Indizes verweisen auf vorherige Schichten (-1 = vorherige Schicht), während positive Indizes auf bestimmte Schichten über ihre Position verweisen.
Modulwiederholung#
Der Parameter repeats erstellt tiefere Netzwerkabschnitte:
- [-1, 3, C2f, [128, True]] # Creates 3 consecutive C2f blocks
- [-1, 1, Conv, [64, 3, 2]] # Single convolution layerDie tatsächliche Wiederholungsanzahl wird mit dem Tiefenskalierungsfaktor aus deiner Modellgrößenkonfiguration multipliziert.
Verfügbare Module#
Module sind nach Funktionalität organisiert und im Ultralytics modules directory definiert. Die folgenden Tabellen zeigen häufig verwendete Module nach Kategorie, wobei viele weitere im Quellcode verfügbar sind:
Grundlegende Operationen#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
Conv | Konvolution + BatchNorm + Aktivierung | conv.py | [out_ch, kernel, stride, pad, groups] |
nn.Upsample | Räumliches Upsampling | PyTorch | [size, scale_factor, mode] |
nn.Identity | Pass-Through-Operation | PyTorch | [] |
Zusammengesetzte Blöcke#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
C2f | CSP-Bottleneck mit 2 Konvolutionen | block.py | [out_ch, shortcut, groups, expansion] |
SPPF | Spatial Pyramid Pooling (schnell) | block.py | [out_ch, kernel_size] |
Concat | Kanalweise Konkatenation | conv.py | [dimension] |
Spezialisierte Module#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
TorchVision | Lade ein beliebiges TorchVision-Modell | block.py | [out_ch, model_name, weights, unwrap, truncate, split] |
Index | Extrahiere einen spezifischen Tensor aus einer Liste | conv.py | [out_ch, index] |
Detect | YOLO-Erkennungs-Head | head.py | [nc] |
Dies stellt einen Ausschnitt der verfügbaren Module dar. Eine vollständige Liste der Module und ihrer Parameter findest du im modules directory.
Erweiterte Funktionen#
TorchVision-Integration#
Das TorchVision-Modul ermöglicht die nahtlose Integration jedes TorchVision model als Backbone:
from ultralytics import YOLO
# Model with ConvNeXt backbone
model = YOLO("convnext_backbone.yaml")
results = model.train(data="imagenet10", epochs=100)Setze den letzten Parameter auf True, um Zwischen-Feature-Maps für die Multiskalen-Erkennung zu erhalten.
Index-Modul zur Merkmalsauswahl#
Wenn du Modelle verwendest, die mehrere Feature-Maps ausgeben, wählt das Index-Modul spezifische Ausgaben aus:
nc: 80
backbone:
- [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]] # Multi-output
head:
- [0, 1, Index, [192, 4]] # Select 4th feature map (192 channels)
- [0, 1, Index, [384, 6]] # Select 6th feature map (384 channels)
- [0, 1, Index, [768, 8]] # Select 8th feature map (768 channels)
- [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detectionModulauflösungssystem#
Das Verständnis darüber, wie Ultralytics Module findet und importiert, ist entscheidend für Anpassungen:
Modul-Lookup-Prozess#
Ultralytics verwendet ein dreistufiges System in parse_model:
# Core resolution logic
m = (
getattr(torch.nn, m[3:])
if m.startswith("nn.")
else getattr(__import__("torchvision").ops, m[16:])
if m.startswith("torchvision.ops.")
else globals()[m]
) # get module- PyTorch-Module: Namen, die mit
'nn.'beginnen → Namensraumtorch.nn - TorchVision-Operationen: Namen, die mit
'torchvision.ops.'beginnen → Namensraumtorchvision.ops - Ultralytics-Module: Alle anderen Namen → globaler Namespace über Importe
Modul-Importkette#
Standardmodule werden über Importe in tasks.py verfügbar:
from ultralytics.nn.modules import ( # noqa: F401
SPPF,
C2f,
Conv,
Detect,
# ... many more modules
Index,
TorchVision,
)Integration benutzerdefinierter Module#
Änderung des Quellcodes#
Die Änderung des Quellcodes ist der flexibelste Weg, um deine eigenen Module zu integrieren, kann aber kompliziert sein. Um ein benutzerdefiniertes Modul zu definieren und zu verwenden, befolge diese Schritte:
-
Installiere Ultralytics im Entwicklungsmodus über die Git-Klon-Methode aus dem Quickstart guide.
-
Definiere dein Modul in
ultralytics/nn/modules/block.py:class CustomBlock(nn.Module): """Custom block with Conv-BatchNorm-ReLU sequence.""" def __init__(self, c1, c2): """Initialize CustomBlock with input and output channels.""" super().__init__() self.layers = nn.Sequential(nn.Conv2d(c1, c2, 3, 1, 1), nn.BatchNorm2d(c2), nn.ReLU()) def forward(self, x): """Forward pass through the block.""" return self.layers(x) -
Mache dein Modul auf Pakete-Ebene verfügbar in
ultralytics/nn/modules/__init__.py:from .block import CustomBlock # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock -
Zu Importen hinzufügen in
ultralytics/nn/tasks.py:from ultralytics.nn.modules import CustomBlock # noqa -
Füge das Modul zu
base_moduleshinzu innerhalb vonparse_model(). Module in diesem Set erhalten automatisch Eingabe- und Ausgabekanäle:base_modules = frozenset( { # Existing modules... CustomBlock, } ) -
Verwende das Modul in deinem Modell-YAML:
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]] -
Überprüfe die FLOPs, um sicherzustellen, dass der Forward-Pass funktioniert:
from ultralytics import YOLO model = YOLO("custom_model.yaml", task="classify") model.info() # should print non-zero FLOPs if working
Beispielkonfigurationen#
Einfaches Erkennungsmodell#
# Simple YOLO detection model
nc: 80
scales:
n: [0.33, 0.25, 1024]
backbone:
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]] # 2
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]] # 4
- [-1, 1, SPPF, [256, 5]] # 5
head:
- [-1, 1, Conv, [256, 3, 1]] # 6
- [[6], 1, Detect, [nc]] # 7TorchVision-Backbone-Modell#
# ConvNeXt backbone with YOLO head
nc: 80
backbone:
- [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]]
head:
- [0, 1, Index, [192, 4]] # P3 features
- [0, 1, Index, [384, 6]] # P4 features
- [0, 1, Index, [768, 8]] # P5 features
- [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detectionKlassifizierungsmodell#
# Simple classification model
nc: 1000
backbone:
- [-1, 1, Conv, [64, 7, 2, 3]]
- [-1, 1, nn.MaxPool2d, [3, 2, 1]]
- [-1, 4, C2f, [64, True]]
- [-1, 1, Conv, [128, 3, 2]]
- [-1, 8, C2f, [128, True]]
head:
- [-1, 1, Classify, [nc]]Classify führt bereits intern ein adaptives Average Pooling aus.
Best Practices#
Tipps für den Architekturentwurf#
Starte einfach: Beginne mit bewährten Architekturen, bevor du sie anpasst. Verwende bestehende YOLO-Konfigurationen als Vorlagen und nimm schrittweise Änderungen vor, anstatt von Grund auf neu zu bauen.
Teste schrittweise: Überprüfe jede Modifikation Schritt für Schritt. Füge jeweils ein benutzerdefiniertes Modul hinzu und stelle sicher, dass es funktioniert, bevor du zum nächsten Schritt übergehst.
Kanäle überwachen: Stelle sicher, dass die Kanaldimensionen zwischen verbundenen Schichten übereinstimmen. Die Ausgabekanäle (c2) einer Schicht müssen mit den Eingangskanälen (c1) der nächsten Schicht in der Sequenz übereinstimmen.
Skip-Verbindungen nutzen: Nutze die Wiederverwendung von Features mit [[-1, N], 1, Concat, [1]]-Mustern. Diese Verbindungen unterstützen den Gradientenfluss und ermöglichen es dem Modell, Merkmale aus verschiedenen Skalen zu kombinieren.
Angemessen skalieren: Wähle Modellskalen basierend auf deinen Rechenbeschränkungen. Verwende Nano (n) für Edge-Geräte, Klein (s) für ausgewogene Leistung und größere Skalen (m, l, x) für maximale Genauigkeit.
Überlegungen zur Leistung#
Tiefe vs. Breite: Tiefe Netzwerke erfassen komplexe hierarchische Merkmale durch mehrere Transformationsschichten, während breite Netzwerke mehr Informationen parallel pro Schicht verarbeiten. Wäge dies basierend auf deiner Aufgabenkomplexität ab.
Skip-Connections: Verbessern den Gradientenfluss während des Trainings und ermöglichen die Wiederverwendung von Merkmalen im gesamten Netzwerk. Sie sind besonders in tieferen Architekturen wichtig, um verschwindende Gradienten zu verhindern.
Bottleneck-Blöcke: Reduziere die Rechenkosten bei gleichzeitiger Beibehaltung der Modellausdruckskraft. Module wie C2f verwenden weniger Parameter als Standardkonvolutionen und bewahren gleichzeitig die Fähigkeit zum Merkmalslernen.
Multi-Scale-Merkmale: Essenziell für die Erkennung von Objekten unterschiedlicher Größe im selben Bild. Verwende Feature Pyramid Network (FPN)-Muster mit mehreren Detektionsköpfen auf verschiedenen Skalen.
Fehlerbehebung#
Häufige Probleme#
| Problem | Ursache | Lösung |
|---|---|---|
KeyError: 'ModuleName' | Modul nicht importiert | Zu den Importen von tasks.py hinzufügen |
| Kanalabmessungen stimmen nicht überein | Falsche Spezifikation von args | Kompatibilität der Ein-/Ausgabekanäle prüfen |
AttributeError: 'int' object has no attribute | Falscher Argumenttyp | Überprüfe die Moduldokumentation auf korrekte Argumenttypen |
| Modell lässt sich nicht erstellen | Ungültige Referenz für from | Stelle sicher, dass die referenzierten Schichten existieren |
Debugging-Tipps#
Bei der Entwicklung benutzerdefinierter Architekturen hilft systematisches Debugging, Probleme frühzeitig zu erkennen:
Verwende Identity Head zum Testen
Ersetze komplexe Köpfe durch nn.Identity, um Backbone-Probleme zu isolieren:
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debuggingDies ermöglicht die direkte Inspektion der Backbone-Ausgaben:
import torch
from ultralytics import YOLO
model = YOLO("debug_model.yaml", task="detect")
output = model.model(torch.randn(1, 3, 640, 640))
print(f"Output shape: {output.shape}") # Should match expected dimensionsInspektion der Modellarchitektur
Die Überprüfung der FLOPs-Anzahl und das Ausdrucken jeder Schicht können ebenfalls beim Debuggen von Problemen mit deiner benutzerdefinierten Modellkonfiguration helfen. Die FLOPs-Anzahl sollte bei einem gültigen Modell ungleich Null sein. Wenn sie Null ist, liegt wahrscheinlich ein Problem mit dem Forward-Pass vor. Die Ausführung eines einfachen Forward-Pass sollte den genauen Fehler anzeigen, auf den du stößt.
from ultralytics import YOLO
# Build model with verbose output to see layer details
model = YOLO("debug_model.yaml", task="detect", verbose=True)
# Check model FLOPs. Failed forward pass causes 0 FLOPs.
model.info()
# Inspect individual layers
for i, layer in enumerate(model.model.model):
print(f"Layer {i}: {layer}")Schritt-für-Schritt-Validierung
- Minimal starten: Teste zuerst mit der einfachsten möglichen Architektur
- Inkrementell hinzufügen: Baue die Komplexität Schicht für Schicht auf
- Dimensionen prüfen: Überprüfe die Kompatibilität von Kanal- und räumlicher Größe
- Skalierung validieren: Teste mit verschiedenen Modellskalen (
n,s,m)
FAQ#
Setze den Parameter
ncoben in deiner YAML-Datei, damit er mit der Anzahl der Klassen deines Datensatzes übereinstimmt.nc: 5 # 5 classesJa. Du kannst jedes unterstützte Modul verwenden, einschließlich TorchVision backbones, oder dein eigenes benutzerdefiniertes Modul definieren und es wie in Custom Module Integration beschrieben importieren.
Verwende den
scalessection in deiner YAML, um Skalierungsfaktoren für Tiefe, Breite und maximale Kanäle zu definieren. Das Modell wendet diese automatisch an, wenn du die Basis-YAML-Datei lädst und die Skala an den Dateinamen anhängst (z. B.yolo26n.yaml).Dieses Format legt fest, wie jede Schicht aufgebaut ist:
from: Eingangsquelle(n)repeats: Häufigkeit der Wiederholung des Modulsmodule: Der Schichttypargs: Argumente für das Modul
Überprüfe, ob die Ausgabekanäle einer Schicht mit den erwarteten Eingangskanälen der nächsten Schicht übereinstimmen. Verwende
print(model.model.model), um die Architektur deines Modells zu untersuchen.Überprüfe den Quellcode im
ultralytics/nn/modulesdirectory auf alle verfügbaren Module und deren Argumente.Definiere dein Modul im Quellcode, importiere es wie in Source Code Modification gezeigt und referenziere es namentlich in deiner YAML-Datei.
Ja, du kannst
model.load("path/to/weights")verwenden, um Gewichte aus einem vortrainierten Checkpoint zu laden. Allerdings werden nur Gewichte für Schichten, die übereinstimmen, erfolgreich geladen.Verwende
model.info(), um zu prüfen, ob die Anzahl der FLOPs ungleich Null ist. Ein gültiges Modell sollte eine FLOPs-Anzahl ungleich Null aufweisen. Wenn sie Null ist, befolge die Vorschläge in Debugging Tips, um das Problem zu finden.