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.