5 votes

fb-hydra : Comment faire en sorte que les configurations internes héritent des champs de la configuration externe ?

J'essaie d'écrire une structure de configuration hiérarchique telle que les fichiers de configuration des répertoires internes héritent des fichiers de configuration des répertoires externes. Par exemple, dans le scénario suivant

upper_config
|
|-middle_config
|   |
|   |-lower_config

Je voudrais middle_config pour être en mesure d'hériter et de remplacer les paramètres des upper_config et lower_config pour être en mesure d'hériter et de remplacer les paramètres de l'un et de l'autre middle_config y upper_config .

Une solution serait d'écrire un analyseur de configuration de telle sorte que les modules externes soient lus en premier, et qu'au fur et à mesure que les modules internes sont lus, ils écrasent les champs des modules externes.

Cependant, j'aimerais utiliser Hydra (ou un autre outil, ouvert aux suggestions) pour toutes les commodités supplémentaires. J'ai lu la documentation d'un bout à l'autre plusieurs fois, et bien que j'aie l'impression que les groupes de configuration ou les directives de paquets devraient pouvoir gérer cela, je n'arrive pas à m'y retrouver.

Je crois ce post pose une question très similaire, mais la réponse ne m'a pas éclairé, et il semble que la personne qui a posé la question a décidé d'implémenter une version du config parser que j'ai décrit ci-dessus.

J'espère qu'il existe un moyen pour qu'un fichier de configuration interne puisse être utilisé. package doit être modifiée pour pointer vers une configuration parente et hériter ainsi de sa liste par défaut.

7voto

Jasha Points 176

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X