Skip to content

Commit b313df9

Browse files
committed
Add hydra_instantiate example
1 parent cbde197 commit b313df9

7 files changed

Lines changed: 97 additions & 0 deletions

File tree

docs/source/reproducible.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,40 @@ configuration file and use it the script like so:
104104
# Set the seed for numpy
105105
np.random.seed(config.seed)
106106
# application-specific seed setting
107+
108+
Instantiating objects
109+
---------------------
110+
111+
Another cool feature of Hydra is object instantiating. Imagine you want to try different
112+
Optimizers for your Deep Neural Network (DNN) or you want to try different DNNs in the same pipeline.
113+
Instead of doing ``if-else`` statements, you write one line of code and let Hydra choose the
114+
appropriate object class based on your configuration. See the script
115+
`examples/hydra_instantiate.py <https://github.com/ebezzam/python-dev-tips/blob/main/examples/hydra_instantiate.py>`_
116+
for the example.
117+
118+
.. code-block:: python
119+
@hydra.main(version_base=None, config_path="configs", config_name="instantiate")
120+
def run(config):
121+
# instantiate object from config
122+
example_array = instantiate(config.array)
123+
# application specific choice of object class
124+
125+
``instantiate`` function from ``hydra.utils`` allows you to define an object in a YAML file
126+
without being tied to a particular class. To do this, you need to define ``_target_`` in
127+
your config (see configs in ``configs/array``) and object initialization arguments. Object class
128+
can be either defined in your project (``configs/array/ExampleZeros``, ``configs/array/ExampleArange``)
129+
or taken from a package (``configs/array/ExampleNumpy``).
130+
131+
Note that here we use another Hydra feature: config grouping and splitting. Instead of writing
132+
configurations for all objects in the main config and copying configuration files, we create a sub-directory ``array``,
133+
where all ``array`` configs are defined. Now we can run the main config with the ``array`` of
134+
our choice simply by specifying it in the command line. For example, ``python3 hydra_instantiate.py array=ExampleNumpy``
135+
or ``python3 hydra_instantiate.py array=ExampleZeros``.
136+
137+
Object instantiating is recursive, i.e. some of the arguments of the class can also be
138+
defined using ``_target_`` and they will be created automatically. For example,
139+
``python3 hydra_instantiate.py array=ExampleArange +array/transform=power`` defines the ``transform`` argument of
140+
the ``ExampleArange`` class as the ``PowerTransform`` class. The ``+array/transform=power`` in the command line
141+
means adding the ``transform`` argument to the current ``array`` configuration from the ``power.yaml`` config defined
142+
in ``configs/array/transform``. That is, you can have sub-sub-directories. The default values from sub-sub-directories
143+
can also be changed in the command-line: ``python3 hydra_instantiate.py array=ExampleArange +array/transform=power array.transform.pow=3``
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_target_: hydra_instantiate.ExampleArange
2+
n: 4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_target_: numpy.ones
2+
shape: 4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_target_: hydra_instantiate.ExampleZeros
2+
n: 4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_target_: hydra_instantiate.PowerTransform
2+
pow: 2

examples/configs/instantiate.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# python examples/real_convolve.py -cn exp1
2+
defaults:
3+
- array: ExampleZeros
4+
- _self_
5+
6+
7+
hydra:
8+
job:
9+
chdir: True # change to output folder
10+
job_logging:
11+
formatters:
12+
simple:
13+
format: '[%(levelname)s] - %(message)s'

examples/hydra_instantiate.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import hydra
2+
from hydra.utils import instantiate
3+
import numpy as np
4+
5+
6+
class PowerTransform:
7+
def __init__(self, pow):
8+
self.pow = pow
9+
10+
def __call__(self, x):
11+
return np.power(x, self.pow)
12+
13+
14+
class ExampleZeros:
15+
def __init__(self, n) -> None:
16+
self.data = np.zeros(n)
17+
18+
def __str__(self):
19+
return str(self.data)
20+
21+
22+
class ExampleArange:
23+
def __init__(self, n, transform=None) -> None:
24+
self.data = np.arange(n)
25+
if transform is not None:
26+
self.data = transform(self.data)
27+
28+
def __str__(self):
29+
return str(self.data)
30+
31+
32+
@hydra.main(version_base=None, config_path="configs", config_name="instantiate")
33+
def run(config):
34+
example_array = instantiate(config.array)
35+
print(f"Class: {type(example_array)}, Data: {example_array}")
36+
37+
38+
if __name__ == "__main__":
39+
run()

0 commit comments

Comments
 (0)