Supposons que nous ayons les fichiers suivants :
my_app.py
outer/conf1.yaml
outer/middle/conf2.yaml
outer/middle/inner/conf3.yaml
Pour concrétiser les choses, voici le contenu de l'application my_app.py
:
import hydra, omegaconf
@hydra.main(config_path="outer", config_name="conf1")
def my_app(cfg) -> None:
print(omegaconf.OmegaConf.to_yaml(cfg))
my_app()
TLDR
Si votre yaml
ne contiennent que des données simples (c'est-à-dire pas de liste de valeurs par défaut ou de directives de paquetage), l'approche la plus flexible pour composer dynamiquement votre configuration à la ligne de commande ressemble à ceci :
$ python my_app.py +middle@_global_=conf2 +middle/inner@_global_=conf3
Cela permettra de fusionner outer/middle/conf2.yaml
sur le dessus de outer/conf1.yaml
puis fusionner outer/middle/inner/conf3.yaml
en plus de cela. Le site @_global_
Le mot-clé signifie que les configurations d'entrée doivent être fusionnées au niveau supérieur au lieu d'être imbriquées selon les noms des répertoires qui les contiennent.
Maintenant, les détails...
Pour répondre à cette question, je pourrais utiliser certaines fonctionnalités de la récente version candidate de Hydra 1.1 :
>>> import hydra
>>> hydra.__version__
'1.1.0.rc1'
Nous pouvons adopter plusieurs approches pour remplacer notre configuration externe par une configuration interne ou intermédiaire :
- Utilisez la liste des valeurs par défaut pour spécifier un paquet.
- Utilisez un en-tête de paquet pour spécifier un paquet.
- Utiliser un package override en ligne de commande pour spécifier un package (c'est la méthode utilisée dans la section TLDR ci-dessus)
Voici les détails de chaque approche :
Utilisez la liste des valeurs par défaut pour spécifier un paquet.
Supposons que nous ayons ce qui suit : Dans outer/conf1.yaml
:
defaults:
- _self_
- middle@_here_: conf2
a: 1
b: 2
Sur outer/middle/conf1.yaml
:
defaults:
- _self_
- inner@_here_: conf3
b: 3
c: 4
Sur outer/middle/inner/conf3.yaml
:
c: 5
d: 6
Avec ces fichiers yaml, en exécutant my_app.py
donne le résultat suivant :
$ python my_app.py
a: 1
b: 3
c: 5
d: 6
Comme vous pouvez le voir, conf1
est remplacée par conf2
qui est à son tour remplacée par conf3
. Alors, comment cela fonctionne-t-il ? Le site liste des valeurs par défaut est utilisé pour spécifier l'ordre dans lequel chaque objet de configuration est composé. Dans conf1
le @_here_
Le mot clé "package" est utilisé pour spécifier que le site conf2
devrait être fusionné avec le groupe de configuration actuel au lieu d'être inclus dans le groupe middle
paquet. Ceci est documenté dans Paquet de liste par défaut mots-clés . Il est également intéressant de noter que @_global_
mot-clé. Notez que l'on pourrait tout aussi bien écrire - middle@foo: conf2
au lieu de - middle@_here_: conf2
dans la liste des valeurs par défaut, auquel cas a "foo"
apparaîtrait dans la configuration de sortie avec le contenu de la clé conf2
emboîtée sous elle.
Tout comme dans conf1.yaml
, conf2.yaml
utilise la liste des valeurs par défaut pour spécifier que conf3
devrait être fusionné avec conf2
au lieu d'être fusionné dans un paquet nommé "inner"
(ce qui aurait été le comportement par défaut, comme c'est le cas pour l'option documenté aquí ).
Quel est le - _self_
mot-clé fait ? Dans une liste de valeurs par défaut, ce mot-clé permet de contrôler l'ordre dans lequel les valeurs la configuration actuelle est fusionnée avec d'autres configurations d'entrée spécifiées dans la liste des dans la liste defaults. Par exemple, dans la liste conf2.yaml
liste des défauts, écriture - _self_
avant - inner@_here_: conf3
assure que conf3
seront fusionnés dans conf2
et non l'inverse. Ce site _self_
Le mot-clé est documenté aquí . Si - _self_
n'est pas spécifié dans le par défaut, alors l'ordre dans lequel les valeurs par défaut sont fusionnées avec la actuelle est le suivant :
- en utilisant Hydra 1.0 : les configurations d'entrée de la liste defaults list sont fusionnées dans la configuration courante.
- avec Hydra 1.1 : la configuration courante est fusionnée en dernier, écrasant les autres configurations spécifiées dans la liste des valeurs par défaut
Pour référence, voir ces migrations instructions pour passer de la version 1.0 à la version 1.1.
Utilisez un en-tête de paquet pour spécifier un paquet.
Utilisation d'un paquet directive en haut d'un fichier yaml peut permettre d'obtenir un résultat similaire :
Sur outer/conf1.yaml
:
defaults:
- _self_
- middle: conf2
a: 1
b: 2
Sur outer/middle/conf2.yaml
:
# @package _global_
defaults:
- _self_
- inner: conf3
b: 3
c: 4
Sur outer/middle/inner/conf3.yaml
# @package _global_
c: 5
d: 6
Le site # @package <PACKAGE>
spécifie l'endroit où le contenu du fichier configuration d'entrée actuelle doit être placé.
$ python my_app.py
a: 1
b: 3
c: 5
d: 6
Cela fonctionne de la même manière que l'utilisation d'un @<PACKAGE>
dans les valeurs par défaut (comme détaillé dans la section précédente), et le résultat sur la ligne de commande est identique. Une différence entre ces deux approches est qu'un en-tête de paquetage s'applique à tout le contenu de la configuration d'entrée donnée, alors que l'utilisation d'un en-tête de paquetage @<PACKAGE>
dans la liste des valeurs par défaut permet d'obtenir des valeurs plus granulaires. contrôle plus granulaire sur les configurations d'entrée qui doivent être placées dans les différents paquets.
Utilisation de la - _self_
dans la liste des valeurs par défaut est toujours nécessaire pour assurer que la fusion s'effectue dans l'ordre correct (voir la section précédente pour des notes sur _self_
).
Le traitement des en-têtes de paquets par Hydra est le suivant différent dans Hydra 1.0 par rapport à 1.1 .
Utilisez un paquetage prioritaire en ligne de commande pour spécifier un paquetage
La manière la plus élégante et la plus souple d'obtenir le résultat souhaité est d'utiliser une commande de remplacement de paquetage : Étant donné que outer/conf1.yaml
comme suit :
a: 1
b: 2
Et outer/middle/conf2.yaml
ainsi :
b: 3
c: 4
y outer/middle/inner/conf3.yaml
:
c: 5
d: 6
Nous pouvons utiliser la puissante ligne de commande de Hydra syntaxe de contournement pour composer la configuration de sortie :
$ python my_app.py +middle@_global_=conf2 +middle/inner@_global_=conf3
a: 1
b: 3
c: 5
d: 6
Utilisation de la _self_
n'est pas nécessaire dans le cadre de cette approche car l'option +<group>@<package>=<option>
a pour effet de ajout de aux valeurs par défaut liste ( aquí est une référence) par opposition à la préposition.