Composing Config Files¶
Perhaps the most important feature of the configuration system is that config files can easily be composed to encourage config files to be more modular. Specifically, when loading a config file, it will inherit all values of any config files listed under the key _base
. This inheritance behaves analogously to python’s class inheritance in that each config can have arbitrarily many parents and the full inheritance tree is linearized using the “C3” linearization algorithm (so no cycles are permitted). The configs are updated in reverse order of precedence (so that the higher precedence config file can override arguments in the lower precedence files).
For example, consider the following config directory structure:
config/
base.yaml
cluster.yaml
demo.yaml
model/
base.yaml
simple.yaml
large.yaml
data/
base.yaml
mnist.yaml
cifar.yaml
Where base.yaml
contains the following:
checkpoint-epochs: 5
gpu: no
cluster.yaml
contains the following:
_base: [base]
gpu: yes
num-workers: 8
model/base.yaml
contains the following:
_base: [base]
optim: sgd
lr: 0.001
act: relu
model/simple.yaml
contains the following:
_base: [model/base]
model-name: deep-nn
hidden: [40, 40]
model/large.yaml
contains the following:
_base: [model/base]
model-name: large-nn
hidden: [300, 300, 300]
batch-norm: yes
optim: adam
data/base.yaml
contains the following:
_base: [base]
batch-size: 128
data-dir: /path/to/all/data
data/mnist.yaml
contains the following:
_base: [data/base]
dataset: mnist
num-classes: 10
data/cifar.yaml
contains the following:
_base: [data/base]
dataset: cifar
num-classes: 100
demo.yaml
contains the following:
_base: [data/mnist, model/simple]
Then, the following configs would be the result of composing the above config files:
>>> import omnifig as fig
>>> print(fig.create_config('cluster', 'model/simple', 'data/mnist'))
gpu: yes
num-workers: 8
checkpoint-epochs: 5
optim: sgd
lr: 0.001
act: relu
model-name: some-model
hidden: [40, 40]
batch-size: 128
dataset: mnist
data-dir: /path/to/all/data
num-classes: 10
>>> print(fig.create_config('model/large', 'data/cifar'))
gpu: no
checkpoint-epochs: 5
optim: adam
lr: 0.001
act: relu
model-name: large-nn
hidden: [300, 300, 300]
batch-norm: yes
batch-size: 128
data-dir: /path/to/all/data
dataset: cifar
num-classes: 100
>>> print(fig.create_config('model/large', 'data/cifar', 'cluster'))
gpu: yes
num-workers: 8
checkpoint-epochs: 5
optim: adam
lr: 0.001
act: relu
model-name: large-nn
hidden: [300, 300, 300]
batch-norm: yes
batch-size: 128
data-dir: /path/to/all/data
dataset: cifar
num-classes: 100
>>> print(fig.create_config('demo'))
gpu: no
checkpoint-epochs: 5
optim: sgd
lr: 0.001
act: relu
model-name: some-model
hidden: [40, 40]
batch-size: 128
dataset: mnist
data-dir: /path/to/all/data
num-classes: 10
See the feature slide B4.