Sie können einige Einstellungen in eine YAML-Datei schreiben und als Referenz aus Python laden. Besonders im Bereich des maschinellen Lernens habe ich viele Eindrücke.
Das Ergebnis des Ladens ist jedoch ein Wörterbuchobjekt, dessen Schlüsselname und hierarchische Struktur in der YAML-Datei visuell bestätigt werden müssen. Ich konnte die YAML-Überprüfungsarbeit während des Codierens nicht ertragen.
Dieser Artikel ist eine der Möglichkeiten, dies für Personen zu tun, die ** config in einer YAML-Datei definieren möchten und dieses Element während der Python-Implementierung automatisch vervollständigt wird ** </ font> Ist vorgestellt.
Den Code finden Sie hier [https://github.com/Nkriskeeic/configer]. Dieser Code ist modular aufgebaut und kann mit pip installiert werden.
Schauen wir uns zunächst ein Beispiel für das Schreiben von Einstellungswerten in eine YAML-Datei an.
config.yml
model:
in_channels: 3
n_blocks: 10
block:
channels: 64
activation: relu
out_channels: 1
Ich denke, dass die Einstellungswerte in der YAML-Datei oft hierarchisch beschrieben werden, wie oben gezeigt. Wenn Sie dies aus einem Python-Skript lesen, wird es möglicherweise etwas anders geschrieben, aber ich denke, es wird ungefähr so aussehen.
main.py
config = yaml.safe_load('./config.yml')
model = Model(
in_channels = config['model']['in_channels'],
out_channels = config['model']['out_channels'],
n_blocks = config['model']['n_blobks'],
block_channels = config['model']['block']['channels'],
...
)
Erstens konnte ich es nicht ertragen, diesen ** Wörterbuchschlüsselnamen ** hart zu codieren. Zweitens konnte ich es für die in YAML definierte hierarchische Struktur nicht ertragen, in die YAML-Datei zu gehen, um mich daran zu erinnern, welche Werte in welcher Hierarchie definiert wurden.
Im Idealfall ** Wenn Sie die Konfiguration in der YAML-Datei definieren, werden die in YAML festgelegten Elemente auch während der Implementierung im Python-Skript automatisch vervollständigt **.
main.py[Ideal]
config = get_config('./config.yml')
model = Model(
in_channels = config.model.in_channels,
out_channels = config.model.out_channels, # <-Der Punktzugriff wird automatisch abgeschlossen. Ich möchte, dass Sie den Typ überprüfen
In YACS wird die Vorlage der YAML-Datei vom Python-Skript definiert, sodass ich denke, dass es möglich ist, den Inhalt von YAML durch automatische Vervollständigung im Python-Skript auszugeben. Es wurde jedoch nicht durch mein PyCharm ergänzt.
yacs
from yacs.config import CfgNode as CN
_C = CN()
_C.MODEL = CN()
_C.MODEL.IN_CHANNELS = 3
def get_cfg_defaults():
return _C.clone()
config = get_cfg_defaults()
config.MODEL.IN_CHANNELS # <--Nicht automatisch ergänzt
Daher habe ich beschlossen, ein eigenes Framework zu erstellen. ** Wenn Sie config in der YAML-Datei definieren, werden die in YAML festgelegten Elemente auch während der Implementierung im Python-Skript automatisch vervollständigt.
Erstens: ** Wenn eine Python-Datei mit demselben Inhalt automatisch aus der YAML-Datei generiert werden kann, kann sie bei der Implementierung von ** </ font> automatisch unter Bezugnahme auf die Python-Datei abgeschlossen werden. Ich tat. Das ist das Bild.
config.yml
hoge: piyo
YAML-> Python-Konvertierung
config.py
hoge: str = 'piyo'
Bei der obigen einfachen Konvertierung fiel es mir jedoch schwer, die hierarchische Struktur in YAML unter Python auszudrücken.
Aus diesem Grund habe ich beschlossen, es etwas komplizierter zu gestalten und damit umzugehen, indem ** alle hierarchischen Strukturen in Datenklassen umgewandelt werden **.
config.yml
model:
in_channels: 3
n_blocks: 10
block:
channels: 64
activation: relu
out_channels: 1
YAML-> Python-Konvertierung
config.py
@dataclass
class ModelBlock:
channels: int = 64
activation: str = 'relu'
@dataclass
class Model:
in_channels: int = 3
n_blocks: int = 10
block: ModelBlock = ModelBlock()
out_channels: int = 1
@dataclass
class Config:
model: Model = Model()
Config().model.block.channels # <-Alles kann ergänzt werden
Der Grund für die Verwendung der Datenklasse besteht darin, die Anzahl der Beschreibungen aufgrund der automatischen Generierung magischer Methoden zu verringern und versehentliche Änderungen an Elementvariablen durch Setzen von "eingefroren = Wahr" zu verhindern. Ich versuche auch, Typanmerkungen zu generieren. Dies wird rekursiv implementiert. Gefällt mir.
Allein damit konvertiere ich nur die YAML-Datei in ein Python-Skript, aber da ich die Konfiguration klassifizieren konnte, möchte ich sie generieren, nachdem ich einige praktische Methoden hinzugefügt habe, die sich auf die Einstellung beziehen.
Es schien schmerzhaft zu sein, die Generierung nur mit String-Verkettung zu schreiben, daher entschied ich mich für die Verwendung eines Python-Skriptgenerierungsmoduls von Drittanbietern, prestring. tat.
Ich habe es mit [Like this] implementiert (https://github.com/Nkriskeeic/configer/blob/master/configer/template/template.py).
Generieren Sie eine config.py
, während Sie mehrere Dateien kombinieren
Es ist ein Bild zu tun.
config.yml
model:
in_channels: 3
n_blocks: 10
block:
channels: 64
activation: relu
out_channels: 1
YAML-> Python-Konvertierung
config.py
@dataclass
class ModelBlock:
channels: int = 64
activation: str = 'relu'
@dataclass
class Model:
in_channels: int = 3
n_blocks: int = 10
block: ModelBlock = ModelBlock()
out_channels: int = 1
@dataclass
class Config:
model: Model = Model()
def some_cool_method():
...
class ConfigGenerator:
def generate():
...
return Config()
Die Klasse "Config" ist für die Pflege des Inhalts von YAML verantwortlich. Der Grund für das Erstellen der "ConfigGenerator" -Klasse besteht darin, dass beim tatsächlichen Lesen des Einstellungswerts aus der YAML-Datei überprüft werden musste, ob er mit der aktuellen "Config" -Klasse inkonsistent war und ob der Typ unterschiedlich war.
Wenn Sie config in der Zieldatei ** YAML definieren, werden die in YAML festgelegten Elemente auch während der Implementierung im Python-Skript automatisch vervollständigt (indem der Inhalt der YAML-Datei in die Python-Klasse konvertiert wird) ** Dinge sind jetzt möglich.
main.py
config = ConfigGenerator().generate()
model = Model(
in_channels = config.model.in_channels,
out_channels = config.model.out_channels, # <-Der Punktzugriff wird automatisch abgeschlossen und es werden auch Typanmerkungen angezeigt
Es gibt jedoch eine Einschränkung, dass ** wenn Sie eine YAML-Datei schreiben, Sie den Befehl drücken müssen, um sie vom Terminal aus in ein Python-Skript zu konvertieren **.
Wenn Sie nicht in 1 Sekunde zur Tippfehler- oder YAML-Datei wechseln müssen, befinden Sie sich im akzeptablen Bereich und es ist in Ordnung.
Da config zu einer Datenklasse gemacht wurde, hielt ich es für zweckmäßig, verschiedene Klassenmethoden durch automatische Generierung hinzuzufügen.
Wenn der Einstellungswert im Experiment häufig geändert wird, gibt es eine Szene wie "Die Standardeinstellung wird in" default.yml "beschrieben, und einige Werte werden in" exp1.yml "aktualisiert". herauskommen. Um die Sichtbarkeit zu verbessern, "Schreiben Sie die Standardeinstellung in" default.yml ", überschreiben Sie die Modelleinstellung mit" model.yml "und überschreiben Sie die Datensatzeinstellung mit" dataset.yml ". Es gibt auch Szenen.
Zu jener Zeit
main.py
config = ConfigGenerator() \
.update_by(['exp1.yml']) \
.generate()
config = ConfigGenerator() \
.update_by(['model.yml', 'dataset.yml']) \
.generate()
Ich habe beschlossen, eine solche Funktion zu "Config Generator" hinzuzufügen, da dies nach Möglichkeit praktisch wäre.
Für die von update_by
übergebene YAML müssen Sie sie jedoch nur als Wörterbuch laden, den Typ und den Variablennamen überprüfen und den entsprechenden Wert überschreiben.
Vorerst habe ich es möglich gemacht, mehrere YAML-Dateien gleichzeitig zu empfangen. Wenn ich jedoch versuche, denselben Einstellungswert mit einem anderen Wert in der jeweils anderen Datei zu überschreiben, wird ein Fehler ausgegeben.
Indem Sie die eingestellten Werte bei der Ausführung des Skripts leicht lesbar anzeigen, können Sie unerwartete Unfälle vermeiden.
Ich habe es so angezeigt.
python
config = ConfigGenerator() \
.update_by(['model.yml']) \
.update_by(['exp01.yml']) \
.generate()
config.pprint(wait_yes=True) # <-Verhindern Sie die Ausführung von Code, es sei denn, Sie überprüfen die Anzeige und drücken JA
Ausgabeergebnis
default from /config/default.yml model: in_channels: 3 n_blocks: 20 (default 10, changed by /config/model.yml) block: channels: 32 (default 64, changed by /config/exp01.yml) activation: relu out_channels: 1
Ich habe versucht, beim Aktualisieren vom Standardwert mit einer Datei eine Warnmeldung auszugeben. Auf diese Weise können Sie sofort feststellen, wenn Sie den Code mit einer Einstellung ausführen, die sich von der geplanten Einstellung unterscheidet.
Recommended Posts