Als Markdown anzeigen

Einfrieren von Schichten

Beim Einfrieren bleiben ausgewählte Gewichte konstant, während der Rest des Modells trainiert wird. Selektoren beziehen sich auf die geordneten Freeze-Gruppen oder Modulnamen einer Familie und nicht auf rohe Schichtnummern eines YAML-Graphen.

Einfrieren von Komponenten

freeze ist optional. Standardmäßig wird nichts eingefroren.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Die ersten 10 Gruppen bilden das gesamte YOLOv9-Backbone.model.train(data="my-dataset.yaml", epochs=50, freeze=10)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=50 freeze=10
Nach Namen
from libreyolo import LibreYOLO model = LibreYOLO("LibreRFDETRs.pt")model.train(data="my-dataset.yaml", epochs=50, freeze="backbone")
Mehrere Selektoren
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", freeze=["backbone", "neck"])

Das Einfrieren erfolgt nach dem Erstellen des Modells und nach einem möglichen Neuaufbau des Heads für eine neue Klassenzahl, aber vor dem Erstellen des Optimizers. Der Optimizer erhält daher ausschließlich trainierbare Parameter.

Mögliche Selektoren

WertBedeutung
None, False, "", "none"Alle Parameter trainieren
10 oder "10"Die ersten zehn Freeze-Gruppen der Familie einfrieren
[0, 3, 7]Diese nullbasierten Gruppen einfrieren
"backbone"Die passende Gruppe, das passende Modul oder das passende Parameterpräfix einfrieren
["backbone", "neck"]Jeden aufgeführten Selektor einfrieren
["backbone", 3]Gemischte Listen funktionieren ebenfalls

Ein String wird vor seiner Interpretation geparst. Daher akzeptieren die CLI und eine YAML-Konfiguration dieselben Formen wie Python. freeze="[0, 3, 'head']" wird als literale Liste geparst, freeze="backbone,neck" am Komma geteilt und ein einfacher Dezimalstring in eine Anzahl umgewandelt.

freeze=True wird abgelehnt, weil die Angabe mehrdeutig ist.

Namensselektoren können mit dem Namen einer Freeze-Gruppe, einem Modulnamen oder einem Parameternamen-Präfix übereinstimmen. Die Glob-Zeichen *, ? und [ werden unterstützt. Ein vorangestelltes model. wird flexibel behandelt. Dadurch treffen backbone und model.backbone jeweils die intern von der Familie verwendete Schreibweise.

Familienspezifische Gruppen

Eine Ganzzahl bezeichnet die familieneigene geordnete Liste von Freeze-Gruppen und keine Position in einem gemeinsamen Graphen. Die Familien von LibreYOLO bestehen nicht alle aus demselben sequenziellen, per YAML indizierten Modell. Eine rohe Schichtnummer hätte deshalb bei jeder Familie eine andere Bedeutung.

YOLOv9 ordnet seine Gruppen von der Eingabeseite aus: zehn Backbone-Stufen, anschließend sechs Neck-Stufen und zuletzt den Head. Deshalb entspricht freeze=10 genau dem Backbone. Darüber bilden backbone, neck und head stabile Namensselektoren.

Die Gruppen von RF-DETR heißen backbone.encoder, backbone.projector, decoder, queries, transformer.encoder_output und head. Namen sind hier die bessere Wahl, weil Transformer-Komponenten keiner Schichtanzahl zugeordnet werden können. backbone trifft per Präfix beide Backbone-Gruppen.

Familien ohne semantisch definierte Gruppen greifen auf einen konservativen Standard zurück: Jedes direkte Kind des Modells, das mindestens einen Parameter besitzt, bildet in Deklarationsreihenfolge eine Gruppe. Dies ist normalerweise eine kurze Liste. Eine große Ganzzahl findet daher nicht genügend Gruppen:

freeze index 10 is out of range for 3 available freeze groups.

Zeige die tatsächliche Liste an, anstatt zu raten:

Freeze-Gruppen einer Familie der Reihe nach auflisten
from libreyolo import LibreYOLO9from libreyolo.models.yolo9.trainer import YOLO9Trainer model = LibreYOLO9("LibreYOLO9s.pt", size="s")trainer = YOLO9Trainer(model=model.model, wrapper_model=model, size="s") for index, (name, _module) in enumerate(trainer.get_freeze_groups()):    print(index, name)

Deutliche Fehlermeldungen

Jede falsche Angabe löst einen Fehler aus, damit nicht unbemerkt etwas anderes trainiert wird als angefordert.

Ein Selektor ohne Treffer löst einen Fehler aus, der die erfolglosen Selektoren nennt:

freeze selector(s) matched no parameters: 'backbon'

Wenn nach dem Einfrieren keine trainierbaren Parameter mehr übrig wären, wird sowohl beim Einfrieren als auch erneut beim Aufbau des Optimizers ein Fehler ausgelöst:

freeze would leave no trainable parameters. Use a smaller freeze value or
target a narrower module.

Dies geschieht bei freeze="all", da all mit jedem Parameter übereinstimmt.

Bei erfolgreichem Einfrieren hält eine Zeile den Vorgang fest:

Layer freezing: selectors=[10], tensors=124, params=2103776, trainable=1863456/3967232

Keine Aktualisierung eingefrorener BatchNorm-Statistiken

Ein eingefrorener Parameter befindet sich weiterhin in einem Modul, dessen laufende Statistiken sich sonst weiter ändern würden. Jedes BatchNorm-artige Modul, dessen Parameter zur eingefrorenen Menge gehören, wird in den Evaluierungsmodus versetzt. Der Trainer wendet dies nach jedem Aufruf von model.train() zu Beginn einer Epoche erneut an, damit die Statistiken über den gesamten Lauf konstant bleiben.

Dieses Verhalten ist standardmäßig aktiviert und sorgt dafür, dass beim Einfrieren eines Backbones tatsächlich alle seine Zustände unverändert bleiben.

Kombination mit LoRA

freeze und lora=True können gemeinsam verwendet werden. Bei RF-DETR, DEIM und ConvNeXt bleiben die Adapterparameter auch dann trainierbar, wenn ihre übergeordnete Gruppe eingefroren ist. Diese Kombination ist erwünscht: ein eingefrorenes Backbone, auf dem Adapter lernen. Siehe LoRA-Fine-Tuning.

Umfang

Hierbei handelt es sich um statisches Einfrieren, das beim Start festgelegt wird. Zeitgesteuertes Auftauen und progressives Einfrieren gehören nicht zur Schnittstelle.

Verwandte Themen

  • Unter Hyperparameter findest du die übrigen Optionen von train().
  • Distillation beschreibt eine weitere Möglichkeit, Wissen eines großen Modells in einen Trainingslauf zu übertragen.

Mit LibreYOLO v1.5.0 verifiziert.