Leitfaden zur YAML-Konfiguration von Modellen#
Die YAML-Konfigurationsdatei des Modells dient als architektonischer Bauplan für neuronale Netzwerke von Ultralytics. Sie legt fest, wie Layer verbunden sind, welche Parameter die einzelnen Module verwenden und wie das gesamte Netzwerk über verschiedene Modellgrößen hinweg skaliert wird.
Konfigurationsstruktur#
YAML-Dateien von Modellen sind in drei Hauptabschnitte gegliedert, die gemeinsam die Architektur definieren.
Abschnitt „Parameter“#
Der Abschnitt parameters 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 kombinierte Skalierungsfaktoren, die Tiefe, Breite und die maximale Kanalanzahl des Modells anpassen, um Varianten verschiedener Größen zu erzeugen (von Nano bis Extra-Large).kpt_shapegilt für Posenschätzungsmodelle. Der Wert kann für(x, y)Keypoints[N, 2]oder für(x, y, visibility)[N, 3]sein.
Mit dem Parameter scales kannst du aus einer einzigen Basis-YAML mehrere Modellgrößen erzeugen. Wenn du beispielsweise yolo26n.yaml lädst, liest Ultralytics die Basisdatei yolo26.yaml ein und wendet die Skalierungsfaktoren n (depth=0.50, width=0.25) an, um die Nano-Variante zu erstellen.
Wenn dein Datensatz ein anderes nc oder kpt_shape festlegt, überschreibt Ultralytics die Modellkonfiguration zur Laufzeit automatisch, damit sie zur YAML-Datei des Datensatzes passt.
Architektur von Backbone und Kopf#
Die Modellarchitektur besteht aus den Abschnitten Backbone (Merkmalsextraktion) und Kopf (aufgabenspezifisch):
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 layerDie Indizes der Layer werden über Backbone und Kopf hinweg fortgeführt, und verkettete Merkmalskarten müssen übereinstimmende räumliche Dimensionen haben.
Format der Layer-Spezifikation#
Jeder Layer folgt dem einheitlichen Muster: [from, repeats, module, args]
| Komponente | Zweck | Beispiele |
|---|---|---|
| from | Eingangsverbindungen | -1 (vorheriger Layer), 6 (Layer 6), [4, 6, 8] (mehrere Eingänge) |
| 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 ermöglicht flexible Datenflussmuster in deinem gesamten Netzwerk:
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layerDie Indizierung der Layer beginnt bei 0. Negative Indizes verweisen auf vorherige Layer (-1 = vorheriger Layer), während positive Indizes anhand ihrer Position auf bestimmte Layer verweisen.
Wiederholung von Modulen#
Der Parameter repeats erzeugt tiefere Netzwerkabschnitte:
- [-1, 3, C2f, [128, True]] # Creates 3 consecutive C2f blocks
- [-1, 1, Conv, [64, 3, 2]] # Single convolution layerDie tatsächliche Anzahl der Wiederholungen wird mit dem Tiefenskalierungsfaktor aus der Konfiguration deiner Modellgröße multipliziert.
Verfügbare Module#
Module sind nach Funktionalität organisiert und im Ultralytics-Modulverzeichnis definiert. Die folgenden Tabellen zeigen häufig verwendete Module nach Kategorie. Im Quellcode sind viele weitere verfügbar:
Grundlegende Operationen#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
Conv | Convolution + BatchNorm + Aktivierung | conv.py | [out_ch, kernel, stride, pad, groups] |
nn.Upsample | Räumliches Upsampling | PyTorch | [size, scale_factor, mode] |
nn.Identity | Durchleitungsoperation | PyTorch | [] |
Zusammengesetzte Blöcke#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
C2f | CSP-Bottleneck mit 2 Convolution-Layern | block.py | [out_ch, shortcut, groups, expansion] |
SPPF | Räumliches Pyramid Pooling (schnell) | block.py | [out_ch, kernel_size] |
Concat | Verkettung entlang der Kanäle | conv.py | [dimension] |
Spezialisierte Module#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
TorchVision | Beliebiges torchvision-Modell laden | block.py | [out_ch, model_name, weights, unwrap, truncate, split] |
Index | Bestimmten Tensor aus einer Liste extrahieren | conv.py | [out_ch, index] |
Detect | YOLO-Erkennungskopf | head.py | [nc] |
Dies stellt eine Auswahl der verfügbaren Module dar. Eine vollständige Liste der Module und ihrer Parameter findest du im Modulverzeichnis.
Erweiterte Funktionen#
TorchVision-Integration#
Das TorchVision-Modul ermöglicht die nahtlose Integration jedes TorchVision-Modells 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 Zwischenmerkmalskarten für die Erkennung auf mehreren Maßstabsebenen zu erhalten.
Index-Modul zur Merkmalsauswahl#
Bei Modellen, die mehrere Merkmalskarten ausgeben, wählt das Index-Modul bestimmte 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 detectionSystem zur Modulauflösung#
Für Anpassungen ist es entscheidend zu verstehen, wie Ultralytics Module findet und importiert:
Prozess zur Modulsuche#
Ultralytics verwendet in parse_model ein dreistufiges System:
# 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 → Namespacetorch.nn - TorchVision-Operationen: Namen, die mit
'torchvision.ops.'beginnen → Namespacetorchvision.ops - Ultralytics-Module: Alle anderen Namen → globaler Namespace über Importe
Importkette für Module#
Standardmodule werden durch 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 die vielseitigste Möglichkeit, eigene Module zu integrieren, kann aber knifflig sein. Um ein benutzerdefiniertes Modul zu definieren und zu verwenden, befolge diese Schritte:
-
Ultralytics im Entwicklungsmodus installieren mithilfe der Git-Klonmethode aus dem Schnellstartleitfaden.
-
Dein Modul definieren 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) -
Dein Modul auf Paketebene verfügbar machen in
ultralytics/nn/modules/__init__.py:from .block import CustomBlock # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock -
Zu den Importen hinzufügen in
ultralytics/nn/tasks.py:from ultralytics.nn.modules import CustomBlock # noqa -
Das Modul zu
base_moduleshinzufügen inparse_model(). Module in dieser Gruppe erhalten automatisch Eingangs- und Ausgangskanäle:base_modules = frozenset( { # Existing modules... CustomBlock, } ) -
Das Modul in deiner Modell-YAML verwenden:
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]] -
FLOPs überprüfen, 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#
Grundlegendes 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]] # 7Modell mit TorchVision-Backbone#
# 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 detectionKlassifikationsmodell#
# 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 intern bereits ein adaptives Average Pooling aus.
Bewährte Vorgehensweisen#
Tipps zur Architekturentwicklung#
Einfach anfangen: Beginne mit bewährten Architekturen, bevor du Anpassungen vornimmst. Verwende vorhandene YOLO-Konfigurationen als Vorlagen und ändere sie schrittweise, anstatt von Grund auf neu zu beginnen.
Schrittweise testen: Überprüfe jede Änderung Schritt für Schritt. Füge jeweils nur ein benutzerdefiniertes Modul hinzu und stelle sicher, dass es funktioniert, bevor du mit der nächsten Änderung fortfährst.
Kanäle überwachen: Stelle sicher, dass die Kanalabmessungen zwischen verbundenen Schichten übereinstimmen. Die Ausgangskanäle (c2) einer Schicht müssen mit den Eingangskanälen (c1) der nächsten Schicht in der Sequenz übereinstimmen.
Skip Connections verwenden: Nutze die Wiederverwendung von Merkmalen mit Mustern wie [[-1, N], 1, Concat, [1]]. Diese Verbindungen verbessern den Gradientenfluss und ermöglichen es dem Modell, Merkmale aus verschiedenen Maßstäben zu kombinieren.
Passend skalieren: Wähle die Modellskalierung entsprechend deinen Rechenressourcen. Verwende Nano (n) für Edge-Geräte, Small (s) für ein ausgewogenes Verhältnis von Leistung und Genauigkeit sowie größere Skalierungen (m, l, x) für maximale Genauigkeit.
Überlegungen zur Leistung#
Tiefe vs. Breite: Tiefe Netzwerke erfassen komplexe hierarchische Merkmale über mehrere Transformationsschichten, während breite Netzwerke auf jeder Schicht mehr Informationen parallel verarbeiten. Stimme beides auf die Komplexität deiner Aufgabe ab.
Skip Connections: Sie verbessern den Gradientenfluss während des Trainings und ermöglichen die Wiederverwendung von Merkmalen im gesamten Netzwerk. In tieferen Architekturen sind sie besonders wichtig, um verschwindende Gradienten zu verhindern.
Bottleneck-Blöcke: Sie verringern den Rechenaufwand und erhalten gleichzeitig die Ausdrucksfähigkeit des Modells. Module wie C2f verwenden weniger Parameter als Standardfaltungen und bewahren dabei die Fähigkeit zum Lernen von Merkmalen.
Merkmale über mehrere Maßstäbe: Sie sind unverzichtbar, um Objekte unterschiedlicher Größe im selben Bild zu erkennen. Verwende Muster eines Feature Pyramid Network (FPN) mit mehreren Erkennungsköpfen auf unterschiedlichen Maßstäben.
Fehlerbehebung#
Häufige Probleme#
| Problem | Ursache | Lösung |
|---|---|---|
KeyError: 'ModuleName' | Modul nicht importiert | Füge es zu den Imports in tasks.py hinzu |
| Nicht übereinstimmende Kanalabmessungen | Falsche Spezifikation von args | Überprüfe die Kompatibilität der Eingangs- und Ausgangskanäle |
AttributeError: 'int' object has no attribute | Falscher Argumenttyp | Prüfe die Dokumentation des Moduls auf die korrekten Argumenttypen |
| Modell lässt sich nicht erstellen | Ungültige Referenz auf from | Stelle sicher, dass die referenzierten Schichten vorhanden sind |
Tipps zur Fehlersuche#
Bei der Entwicklung benutzerdefinierter Architekturen hilft eine systematische Fehlersuche, Probleme frühzeitig zu erkennen:
Identitätskopf zum Testen verwenden
Ersetze komplexe Köpfe durch nn.Identity, um Probleme im Backbone zu isolieren:
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debuggingSo kannst du die Ausgaben des Backbones direkt überprüfen:
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 dimensionsModellarchitektur überprüfen
Das Überprüfen der FLOPs-Anzahl und die Ausgabe jeder Schicht können ebenfalls dabei helfen, Probleme mit deiner benutzerdefinierten Modellkonfiguration zu finden. Die FLOPs-Anzahl sollte bei einem gültigen Modell ungleich null sein. Wenn sie null ist, liegt wahrscheinlich ein Problem beim Forward-Pass vor. Ein einfacher Forward-Pass sollte den genau auftretenden Fehler anzeigen.
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}")Schrittweise Validierung
- Minimal beginnen: Teste zuerst die einfachstmögliche Architektur
- Schrittweise erweitern: Baue die Komplexität Schicht für Schicht auf
- Abmessungen überprüfen: Überprüfe die Kompatibilität der Kanal- und räumlichen Abmessungen
- Skalierung validieren: Teste verschiedene Modellskalierungen (
n,s,m)
FAQ#
Setze den Parameter
ncam Anfang deiner YAML-Datei auf die Anzahl der Klassen in deinem Datensatz.nc: 5 # 5 classesJa. Du kannst jedes unterstützte Modul verwenden, einschließlich TorchVision-Backbones, oder dein eigenes benutzerdefiniertes Modul definieren und es wie unter Integration benutzerdefinierter Module beschrieben importieren.
Verwende den
scales-Abschnitt in deiner YAML-Datei, um Skalierungsfaktoren für Tiefe, Breite und maximale Kanalanzahl zu definieren. Das Modell wendet diese automatisch an, wenn du die Basis-YAML-Datei mit der an den Dateinamen angehängten Skalierung lädst (z. B.yolo26n.yaml).Dieses Format legt fest, wie jede Schicht erstellt wird:
from: Eingangsquelle(n)repeats: Anzahl der Wiederholungen des Modulsmodule: Schichttypargs: Argumente für das Modul
Überprüfe, ob die Ausgangskanäle einer Schicht mit den erwarteten Eingangskanälen der nächsten übereinstimmen. Verwende
print(model.model.model), um die Architektur deines Modells zu überprüfen.Prüfe den Quellcode im
ultralytics/nn/modules-Verzeichnis auf alle verfügbaren Module und ihre Argumente.Definiere dein Modul im Quellcode, importiere es wie unter Änderung des Quellcodes gezeigt und verweise in deiner YAML-Datei über seinen Namen darauf.
Ja, du kannst
model.load("path/to/weights")verwenden, um Gewichte aus einem vortrainierten Checkpoint zu laden. Allerdings werden nur die Gewichte von übereinstimmenden Schichten erfolgreich geladen.Verwende
model.info(), um zu überprüfen, ob die FLOPs-Anzahl ungleich null ist. Ein gültiges Modell sollte eine FLOPs-Anzahl ungleich null aufweisen. Wenn sie null ist, befolge die Vorschläge unter Tipps zur Fehlersuche, um das Problem zu finden.