forked from facebookresearch/detectron2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: fix facebookresearch#3225 Pull Request resolved: fairinternal/detectron2#553 Reviewed By: wat3rBro Differential Revision: D29731838 Pulled By: ppwwyyxx fbshipit-source-id: 69ed27681747cf00a2fa682c245369c3d1ee8945
- Loading branch information
1 parent
729227f
commit 8b0953c
Showing
12 changed files
with
203 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,5 @@ Tutorials | |
training | ||
evaluation | ||
configs | ||
lazyconfigs | ||
deployment |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
# Lazy Configs | ||
|
||
The traditional yacs-based config system provides basic, standard functionalities. | ||
However, it does not offer enough flexibility for many new projects. | ||
We develop an alternative, non-intrusive config system that can be used with | ||
detectron2 or potentially any other complex projects. | ||
|
||
## Python Syntax | ||
|
||
Our config objects are still dictionaries. Instead of using Yaml to define dictionaries, | ||
we create dictionaries in Python directly. This gives users the following power that | ||
doesn't exist in Yaml: | ||
|
||
* Easily manipulate the dictionary (addition & deletion) using Python. | ||
* Write simple arithmetics or call simple functions. | ||
* Use more data types / objects. | ||
* Import / compose other config files, using the familiar Python import syntax. | ||
|
||
A Python config file can be loaded like this: | ||
```python | ||
# config.py: | ||
a = dict(x=1, y=2, z=dict(xx=1)) | ||
b = dict(x=3, y=4) | ||
|
||
# my_code.py: | ||
from detectron2.config import LazyConfig | ||
cfg = LazyConfig.load("path/to/config.py") # an omegaconf dictionary | ||
assert cfg.a.z.xx == 1 | ||
``` | ||
|
||
After `LazyConfig.load`, `cfg` will be a dictionary that contains all dictionaries | ||
defined in the global scope of the config file. Note that: | ||
* All dictionaries are turned to an [omegaconf](https://omegaconf.readthedocs.io/) | ||
config object during loading. This enables access to omegaconf features, | ||
such as its [access syntax](https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#access-and-manipulation) | ||
and [interoplation](https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#variable-interpolation). | ||
* Absolute imports in `config.py` works the same as in regular Python. | ||
* Relative imports can only import dictionaries from config files. | ||
They are simply a syntax sugar for [LazyConfig.load_rel](../modules/config.html#detectron2.config.LazyConfig.load_rel). | ||
They can load Python files at relative path without requiring `__init__.py`. | ||
|
||
## Recursive Instantiation | ||
|
||
The LazyConfig system heavily uses recursive instantiation, which is a pattern that | ||
uses a dictionary to describe a | ||
call to a function/class. The dictionary consists of: | ||
|
||
1. A "\_target\_" key which contains path to the callable, such as "module.submodule.class_name". | ||
2. Other keys that represent arguments to pass to the callable. Arguments themselves can be defined | ||
using recursive instantiation. | ||
|
||
We provide a helper function [LazyCall](../modules/config.html#detectron2.config.LazyCall) that helps create such dictionaries. | ||
The following code using `LazyCall` | ||
```python | ||
from detectron2.config import LazyCall as L | ||
from my_app import Trainer, Optimizer | ||
cfg = L(Trainer)( | ||
optimizer=L(Optimizer)( | ||
lr=0.01, | ||
algo="SGD" | ||
) | ||
) | ||
``` | ||
creates a dictionary like this: | ||
``` | ||
cfg = { | ||
"_target_": "my_app.Trainer", | ||
"optimizer": { | ||
"_target_": "my_app.Optimizer", | ||
"lr": 0.01, "algo": "SGD" | ||
} | ||
} | ||
``` | ||
|
||
By representing objects using such dictionaries, a general | ||
[instantiate](../modules/config.html#detectron2.config.instantiate) | ||
function can turn them into actual objects, i.e.: | ||
```python | ||
from detectron2.config import instantiate | ||
trainer = instantiate(cfg) | ||
# equivalent to: | ||
# from my_app import Trainer, Optimizer | ||
# trainer = Trainer(optimizer=Optimizer(lr=0.01, algo="SGD")) | ||
``` | ||
|
||
This pattern is powerful enough to describe very complex objects, e.g.: | ||
|
||
<details> | ||
<summary> | ||
A Full Mask R-CNN described in recursive instantiation (click to expand) | ||
</summary> | ||
|
||
```eval_rst | ||
.. literalinclude:: ../../configs/common/models/mask_rcnn_fpn.py | ||
:language: python | ||
:linenos: | ||
``` | ||
|
||
</details> | ||
|
||
There are also objects or logic that cannot be described simply by a dictionary, | ||
such as reused objects or method calls. They may require some refactoring | ||
to work with recursive instantiation. | ||
|
||
## Using Model Zoo LazyConfigs | ||
|
||
We provide some configs in the model zoo using the LazyConfig system, for example: | ||
|
||
* [common baselines](../../configs/common/). | ||
* [new Mask R-CNN baselines](../../configs/new_baselines/) | ||
|
||
After installing detectron2, they can be loaded by the model zoo API | ||
[model_zoo.get_config](../modules/model_zoo.html#detectron2.model_zoo.get_config). | ||
|
||
Our model zoo configs follow some simple conventions, e.g. | ||
`cfg.model` defines a model object, `cfg.dataloader.{train,test}` defines dataloader objects, | ||
and `cfg.train` contains training options in key-value form. | ||
We provide a reference training script | ||
[tools/lazyconfig_train_net.py](../../tools/lazyconfig_train_net.py), | ||
that can train/eval our model zoo configs. | ||
It also shows how to support command line value overrides. | ||
|
||
Nevertheless, you are free to define any custom structure for your project and use it | ||
with your own scripts. | ||
|
||
To demonstrate the power and flexibility of the new system, we show that | ||
[a simple config file](../../configs/Misc/torchvision_imagenet_R_50.py) | ||
can let detectron2 train an ImageNet classification model from torchvision, even though | ||
detectron2 contains no features about ImageNet classification. | ||
This can serve as a reference for using detectron2 in other deep learning tasks. | ||
|
||
## Summary | ||
|
||
By using recursive instantiation to create objects, | ||
we avoid passing a giant config to many places, because `cfg` is only passed to `instantiate`. | ||
This has the following benefits: | ||
|
||
* It's __non-intrusive__: objects to be constructed are config-agnostic, regular Python | ||
functions/classes. | ||
They can even live in other libraries. For example, | ||
`{"_target_": "torch.nn.Conv2d", "in_channels": 10, "out_channels": 10, "kernel_size": 1}` | ||
defines a conv layer. | ||
* __Clarity__ of what function/classes will be called, and what arguments they use. | ||
* `cfg` doesn't need pre-defined keys and structures. It's valid as long as it translates to valid | ||
code. This gives a lot more __flexibility__. | ||
* You can still pass huge dictionaries as arguments, just like the old way. | ||
|
||
Putting recursive instantiation together with the Python config file syntax, the config file | ||
looks a lot like the code that will be executed: | ||
|
||
 | ||
|
||
However, the config file just defines dictionaries, which can be easily manipulated further | ||
by composition or overrides. | ||
The corresponding code will only be executed | ||
later when `instantiate` is called. In some way, | ||
in config files we're writing "editable code" that will be "lazily executed" later when needed. | ||
That's why we call this system "LazyConfig". |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters