Leitfaden zur YAML-Modellkonfiguration#
Die YAML-Konfigurationsdatei des Modells dient als Bauplan für neuronale Netze von Ultralytics. Sie legt fest, wie die Schichten miteinander verbunden sind, welche Parameter die einzelnen Module verwenden und wie das gesamte Netzwerk für verschiedene Modellgrößen skaliert wird.
Aufbau der Konfiguration#
Modelle in YAML-Dateien sind in drei Hauptabschnitte gegliedert, die gemeinsam die Architektur definieren.
Abschnitt „Parameters“#
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 zusammengesetzte Skalierungsfaktoren, mit denen Tiefe, Breite und maximale Kanalanzahl des Modells angepasst werden, um verschiedene Modellgrößen zu erzeugen (von Nano bis Extra Large).kpt_shapegilt für Pose-Modelle. Der Wert kann[N, 2]für(x, y)Keypoints oder[N, 3]für(x, y, visibility)sein.
Mit dem Parameter scales kannst du aus einer einzelnen Basis-YAML mehrere Modellgrößen erzeugen. Wenn du zum Beispiel yolo26n.yaml lädst, liest Ultralytics die Basisdatei yolo26.yaml und wendet die Skalierungsfaktoren n (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 festlegt, überschreibt Ultralytics die Modellkonfiguration zur Laufzeit automatisch, damit sie mit der YAML-Datei des Datensatzes übereinstimmt.
Architektur von Backbone und Head#
Die Modellarchitektur besteht aus den Abschnitten Backbone (Merkmalsextraktion) und Head (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 Indizierung der Schichten läuft über Backbone und Head hinweg fort. Zusammengeführte Feature-Maps müssen dieselben räumlichen Dimensionen haben.
Format der Schichtdefinition#
Für jede Schicht gilt dasselbe Muster: [from, repeats, module, args]
| Komponente | Zweck | Beispiele |
|---|---|---|
| from | Eingangsverbindungen | -1 (vorherige Schicht), 6 (Schicht 6), [4, 6, 8] (mehrere Eingänge) |
| repeats | Anzahl der Wiederholungen | 1 (einmal), 3 (dreimal 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 Netzwerk:
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layerDie Schichten werden ab 0 indiziert. Negative Indizes verweisen auf vorherige Schichten (-1 = vorherige Schicht), positive Indizes auf bestimmte Schichten anhand ihrer Position.
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 Skalierungsfaktor für die Tiefe multipliziert, der in der Konfiguration der Modellgröße festgelegt ist.
Verfügbare Module#
Die Module sind nach Funktion geordnet und im Modulverzeichnis von Ultralytics definiert. Die folgenden Tabellen zeigen häufig verwendete Module nach Kategorie. Im Quellcode stehen viele weitere zur Verfügung:
Grundlegende Operationen#
| Modul | Zweck | Quelle | Argumente |
|---|---|---|---|
Conv | Faltung + 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-Engpass mit 2 Faltungen | block.py | [out_ch, shortcut, groups, expansion] |
SPPF | Räumliches Pyramiden-Pooling (schnell) | block.py | [out_ch, kernel_size] |
Concat | Zusammenführung 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-Erkennungs-Head | head.py | [nc] |
Hier ist eine Auswahl der verfügbaren Module zu sehen. Die 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
# Modell mit 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 Erkennung auf mehreren Skalen zu erhalten.
Das Index-Modul zur Merkmalsauswahl#
Wenn du Modelle verwendest, die mehrere Feature-Maps 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 detectionModulauflösungssystem#
Für Anpassungen ist es wichtig zu verstehen, wie Ultralytics Module findet und importiert:
Ablauf der Modulsuche#
Ultralytics verwendet ein dreistufiges System in parse_model:
# Kernlogik zur Auflösung
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]
) # Modul abrufen- 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 Namensraum über Importe
Modul-Importkette#
Standardmodule werden über Importe in tasks.py verfügbar:
from ultralytics.nn.modules import ( # noqa: F401
SPPF,
C2f,
Conv,
Detect,
# ... viele weitere Module
Index,
TorchVision,
)Integration benutzerdefinierter Module#
Änderungen am Quellcode#
Änderungen am Quellcode bieten die flexibelste Möglichkeit, benutzerdefinierte Module zu integrieren, können aber knifflig sein. Gehe wie folgt vor, um ein benutzerdefiniertes Modul zu definieren und zu verwenden:
-
Installiere Ultralytics im Entwicklungsmodus mithilfe der Git-Klonmethode aus der Schnellstartanleitung.
-
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 Paketebene verfügbar in
ultralytics/nn/modules/__init__.py:from .block import CustomBlock # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock -
Füge es zu den Importen hinzu in
ultralytics/nn/tasks.py:from ultralytics.nn.modules import CustomBlock # noqa -
Füge das Modul zu
base_moduleshinzu inparse_model(). Module in dieser Menge erhalten automatisch Eingangs- und Ausgangskanäle:base_modules = frozenset( { # Vorhandene Module... CustomBlock, } ) -
Verwende das Modul in deiner Modell-YAML:
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]] -
Prüfe die FLOPs, um sicherzustellen, dass der Forward-Pass funktioniert:
from ultralytics import YOLO model = YOLO("custom_model.yaml", task="classify") model.info() # sollte bei erfolgreicher Ausführung ungleich null FLOPs ausgeben
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 durch.
Bewährte Vorgehensweisen#
Tipps zum Architekturdesign#
Einfach anfangen: Beginne mit bewährten Architekturen, bevor du Anpassungen vornimmst. Verwende vorhandene YOLO-Konfigurationen als Vorlagen und ändere sie schrittweise, statt alles von Grund auf neu zu erstellen.
Schrittweise testen: Überprüfe jede Änderung Schritt für Schritt. Füge jeweils ein eigenes Modul hinzu und stelle sicher, dass es funktioniert, bevor du mit der nächsten Änderung fortfährst.
Kanäle überwachen: Achte darauf, dass die Kanalabmessungen zwischen verbundenen Schichten übereinstimmen. Die Ausgabekanäle (c2) einer Schicht müssen mit den Eingabekanälen (c1) der nächsten Schicht in der Sequenz übereinstimmen.
Skip Connections verwenden: Nutze die Wiederverwendung von Merkmalen mit [[-1, N], 1, Concat, [1]]-Mustern. Diese Verbindungen verbessern den Gradientenfluss und ermöglichen es dem Modell, Merkmale aus verschiedenen Maßstäben zu kombinieren.
Passend skalieren: Wähle die Modellgrößen entsprechend deinen Rechenkapazitäten. Verwende nano (n) für Edge-Geräte, small (s) für eine ausgewogene Leistung und größere Größen (m, l, x) für maximale Genauigkeit.
Überlegungen zur Leistung#
Tiefe im Vergleich zur Breite: Tiefe Netzwerke erfassen komplexe hierarchische Merkmale durch mehrere Transformationsschichten, während breite Netzwerke auf jeder Schicht mehr Informationen parallel verarbeiten. Stimme beides auf die Komplexität deiner Aufgabe ab.
Skip Connections: 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: Senken die Rechenkosten und bewahren dabei die Ausdrucksfähigkeit des Modells. Module wie C2f verwenden weniger Parameter als Standardfaltungen und erhalten gleichzeitig die Fähigkeit, Merkmale zu lernen.
Merkmale verschiedener Maßstäbe: Sie sind unverzichtbar, wenn Objekte unterschiedlicher Größe im selben Bild erkannt werden sollen. Verwende Muster eines Feature Pyramid Network (FPN) mit mehreren Erkennungsköpfen auf verschiedenen Maßstäben.
Fehlerbehebung#
Häufige Probleme#
| Problem | Ursache | Lösung |
|---|---|---|
KeyError: 'ModuleName' | Modul nicht importiert | Zu den Imports in tasks.py hinzufügen |
| Abweichende Kanalabmessungen | Falsche Spezifikation von args | Kompatibilität der Ein- und Ausgabekanäle überprüfen |
AttributeError: 'int' object has no attribute | Falscher Argumenttyp | In der Moduldokumentation nach den korrekten Argumenttypen suchen |
| Modell lässt sich nicht erstellen | Ungültiger Verweis auf from | Sicherstellen, dass die referenzierten Schichten vorhanden sind |
Tipps zur Fehlersuche#
Bei der Entwicklung eigener Architekturen hilft eine systematische Fehlersuche dabei, Probleme frühzeitig zu erkennen:
Identity-Kopf zum Testen verwenden
Ersetze komplexe Köpfe durch nn.Identity, um Probleme im Backbone einzugrenzen:
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debuggingSo lassen sich die Backbone-Ausgaben direkt untersuchen:
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 untersuchen
Die FLOPs zu prüfen und jede Schicht auszugeben, kann ebenfalls helfen, Probleme mit deiner eigenen Modellkonfiguration zu beheben. Bei einem gültigen Modell sollte der FLOPs-Wert größer als null sein. Ist er null, liegt wahrscheinlich ein Problem beim Forward-Pass vor. Ein einfacher Forward-Pass sollte den genauen 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 überprüfen
- Mit dem Minimum beginnen: Zuerst mit der einfachstmöglichen Architektur testen
- Schrittweise erweitern: Die Komplexität Schicht für Schicht erhöhen
- Abmessungen prüfen: Kompatibilität der Kanalanzahl und der räumlichen Größe überprüfen
- Skalierung überprüfen: Mit verschiedenen Modellgrößen testen (
n,s,m)
Häufig gestellte Fragen#
Lege den Parameter
ncam Anfang deiner YAML-Datei so fest, dass er der Anzahl der Klassen in deinem Datensatz entspricht.nc: 5 # 5 classesJa. Du kannst jedes unterstützte Modul verwenden, darunter TorchVision-Backbones, oder ein eigenes Modul definieren und es wie unter Integration eigener Module beschrieben importieren.
Verwende den Abschnitt
scalesin deiner YAML-Datei, um Skalierungsfaktoren für Tiefe, Breite und maximale Kanalanzahl festzulegen. Das Modell wendet diese Faktoren automatisch an, wenn du die Basis-YAML-Datei mit der an den Dateinamen angehängten Skalierungsangabe lädst (z. B.yolo26n.yaml).Dieses Format legt fest, wie jede Schicht aufgebaut wird:
from: Eingabequelle(n)repeats: Anzahl der Wiederholungen des Modulsmodule: Typ der Schichtargs: Argumente für das Modul
Prüfe, ob die Ausgabekanäle einer Schicht mit den erwarteten Eingabekanälen der nächsten übereinstimmen. Verwende
print(model.model.model), um die Architektur deines Modells zu untersuchen.Im Quellcodeverzeichnis
ultralytics/nn/modulesfindest du alle verfügbaren Module und ihre Argumente.Definiere dein Modul im Quellcode, importiere es wie unter Quellcode ändern beschrieben und verweise in deiner YAML-Datei mit seinem Namen darauf.
Ja, du kannst
model.load("path/to/weights")verwenden, um Gewichte aus einem vortrainierten Checkpoint zu laden. Es werden jedoch nur die Gewichte von Schichten geladen, die übereinstimmen.Verwende
model.info(), um zu prüfen, ob der FLOPs-Wert größer als null ist. Bei einem gültigen Modell sollte der FLOPs-Wert größer als null sein. Ist er null, befolge die Vorschläge unter Tipps zur Fehlersuche, um das Problem zu finden.