-
Notifications
You must be signed in to change notification settings - Fork 362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Support Pure Python style Configuration File #1071
Merged
Conversation
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
HAOCHENYE
force-pushed
the
new_config_type
branch
from
April 20, 2023 02:46
16ac0f7
to
ea5a049
Compare
HAOCHENYE
force-pushed
the
new_config_type
branch
from
April 25, 2023 10:00
cb40f97
to
8d19fa5
Compare
ly015
reviewed
Jun 14, 2023
LGTM |
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 14, 2023
zhouzaida
reviewed
Jun 15, 2023
zhouzaida
changed the title
New config type
[Feature] Support Pure Python style Configuration File
Jun 15, 2023
zhouzaida
approved these changes
Jun 16, 2023
15 tasks
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1071 +/- ##
=======================================
Coverage ? 77.90%
=======================================
Files ? 140
Lines ? 11974
Branches ? 2464
=======================================
Hits ? 9328
Misses ? 2205
Partials ? 441
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Thanks for your contribution and we appreciate it a lot. The following instructions would make your pull request more healthy and more easily get feedback. If you do not understand some items, don't worry, just make the pull request and seek help from maintainers.
Motivation
Add Pure Python style Configuration File
Current pure text style configuration files can satisfy most of our development needs and some module aliases can greatly simplify the configuration files (e.g.
ResNet
can refer tommcls.models.ResNet
). However, there are also some disadvantages:type
field is specified by a string, and IDE cannot directly jump to the corresponding class definition, which is not conducive to code reading and jumping._delete_
, resulting in a higher learning cost.module not found
errors.In summary, although pure text style configuration files can provide the same syntax rules for
python
,json
, andyaml
format configurations, when the configuration files become complex, pure text style configuration files will appear inadequate. Therefore, we provide a pure Python style configuration file, i.e., thelazy import
mode, which can fully utilize Python's syntax rules to solve the above problems. At the same time, the pure Python style configuration file also supports exporting tojson
andyaml
formats.Basic Syntax
Simply describe the syntax difference between python style config and pure text style config
Module Construction
We use a simple example to compare pure Python style and pure text style configuration files:
Pure Python style
# No need for registration
Pure text style
Pure Python style
Pure text style
The same for pure Python style and pure text style
From the above example, we can see that the difference between pure Python style and pure text style configuration files is:
type
field is no longer a string but directly refers to the module. Correspondingly, import syntax needs to be added in the configuration file.It should be noted that the OpenMMLab series algorithm library still retains the registration process when adding modules. When users build their own projects based on MMEngine, if they use pure Python style configuration files, registration is not required. You may wonder that if you are not in an environment with torch installed, you cannot parse the sample configuration file. Can this configuration file still be called a configuration file? Don't worry, we will explain this part later.
Inheritance
The inheritance syntax of pure Python style configuration files is slightly different:
Pure Python Style:
Pure Python style configuration files use import syntax to achieve inheritance. The advantage of doing this is that we can directly jump to the inherited configuration file for easy reading and jumping. The variable inheritance rule (add, delete, change, and search) is completely aligned with Python syntax. For example, if I want to modify the learning rate of the optimizer in the base configuration file:
Of course, if you are already accustomed to the inheritance rules of pure text style configuration files and the variable is of the
dict
type in the_base_
configuration file, you can also use merge syntax to achieve the same inheritance rule as pure text style configuration files:Compared with pure text style configuration files, the inheritance rule of pure Python style configuration files is completely aligned with the import syntax of Python, which is easier to understand and supports jumping between configuration files. You may wonder since both inheritance and module imports use import syntax, why do we need an
if '_base_'
statement for inheriting configuration files? On the one hand, this can improve the readability of configuration files, making inherited configuration files more prominent. On the other hand, it is also restricted by the rules of lazy_import, which will be explained later.What is Lazy Import
You may find that pure Python style configuration files seem to organize configuration files using pure Python syntax. Then, I do not need configuration classes, and I could just import configuration files using Python syntax. If you have such a feeling, then it is worth celebrating because this is exactly the effect we want.
As mentioned earlier, parsing configuration files requires dependencies on third-party libraries referenced in the configuration files. This is actually a very unreasonable thing. For example, if I trained a model based on MMagic and wanted to deploy it with the onnxruntime backend of MMDeploy. Due to the lack of torch in the deployment environment, and torch is needed in the configuration file parsing process, this makes it inconvenient for me to directly use the configuration file of MMagic as the deployment configuration. To solve this problem, we introduced the concept of lazy_import.
It is a complex task to discuss the specific implementation of lazy_import, so here we only briefly introduce its function. The core idea of lazy_import is to delay the execution of the import statement in the configuration file until the configuration file is parsed, so that the dependency problem caused by the import statement in the configuration file can be avoided. During the configuration file parsing process, the equivalent code executed by the Python interpreter is as follows:
Original configuration file:
Code actually executed by the python interpreter through the configuration class:
As an internal type of the
Config
module, theLazyObject
cannot be accessed directly by users. When accessing the type field, it will undergo a series of conversions to convertLazyObject
into the actualtorch.optim.SGD
type. In this way, parsing the configuration file will not trigger the import of third-party libraries, while users can still access the types of third-party libraries normally when using the configuration file.To access the internal type of
LazyObject
, you can use theConfig.to_dict
interface:At this point, the type accessed is the
LazyObject
type.However, we cannot adopt the lazy import strategy for the inheritance (import) of base files since we need the configuration file parsed to include the fields defined in the base configuration file, and we need to trigger the import really. Therefore, we have added a restriction on importing base files, which must be imported in the
if '_base_'
code block.Limitations
from ._base_.alpha import beta
, thealpha
here must be the module (module) name, i.e., a Python file, rather than the package (package) name containing__init__.py
.import torch, numpy, os
, is not supported. Multiple import statements need to be used instead, such asimport torch; import numpy; import os
.Modification
Please briefly describe what modification is made in this PR.
BC-breaking (Optional)
Does the modification introduce changes that break the backward-compatibility of the downstream repos?
If so, please describe how it breaks the compatibility and how the downstream projects should modify their code to keep compatibility with this PR.
Use cases (Optional)
open-mmlab/mmdetection#10366
open-mmlab/mmyolo#787
open-mmlab/mmrazor#539
open-mmlab/mmpose#2390
open-mmlab/mmpretrain#1567
Checklist