Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
3f6a8274
Unverified
Commit
3f6a8274
authored
Jan 05, 2022
by
liuzhe-lz
Committed by
GitHub
Jan 05, 2022
Browse files
Some string changes around experiment module (#4442)
parent
d5ed88e4
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
38 additions
and
17 deletions
+38
-17
nni/experiment/config/__init__.py
nni/experiment/config/__init__.py
+1
-1
nni/experiment/config/base.py
nni/experiment/config/base.py
+21
-11
nni/experiment/config/experiment_config.py
nni/experiment/config/experiment_config.py
+8
-4
nni/experiment/experiment.py
nni/experiment/experiment.py
+4
-0
nni/tools/nnictl/launcher.py
nni/tools/nnictl/launcher.py
+3
-0
test/ut/experiment/test_config_base.py
test/ut/experiment/test_config_base.py
+1
-1
No files found.
nni/experiment/config/__init__.py
View file @
3f6a8274
# Copyright (c) Microsoft Corporation.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# Licensed under the MIT license.
from
.exp_config
import
ExperimentConfig
from
.exp
eriment
_config
import
ExperimentConfig
from
.algorithm
import
AlgorithmConfig
,
CustomAlgorithmConfig
from
.algorithm
import
AlgorithmConfig
,
CustomAlgorithmConfig
from
.training_services
import
*
from
.training_services
import
*
from
.shared_storage
import
*
from
.shared_storage
import
*
nni/experiment/config/base.py
View file @
3f6a8274
...
@@ -59,7 +59,7 @@ class ConfigBase:
...
@@ -59,7 +59,7 @@ class ConfigBase:
def
__init__
(
self
,
**
kwargs
):
def
__init__
(
self
,
**
kwargs
):
"""
"""
There are two common ways to use the constructor,
There are two common ways to use the constructor,
directly writing
Python code
and unpacking from JSON(YAML) object:
directly writing
kwargs
and unpacking from JSON
(YAML) object:
.. code-block:: python
.. code-block:: python
...
@@ -77,7 +77,7 @@ class ConfigBase:
...
@@ -77,7 +77,7 @@ class ConfigBase:
then using ``hello_world=1``, ``helloWorld=1``, and ``_HELLOWORLD_=1`` in constructor
then using ``hello_world=1``, ``helloWorld=1``, and ``_HELLOWORLD_=1`` in constructor
will all assign to the same field.
will all assign to the same field.
If ``kwargs`` contain extra keys,
a `Valu
eError` will be raised.
If ``kwargs`` contain extra keys,
`Attribut
eError` will be raised.
If ``kwargs`` do not have enough key, missing fields are silently set to `MISSING()`.
If ``kwargs`` do not have enough key, missing fields are silently set to `MISSING()`.
You can use ``utils.is_missing()`` to check them.
You can use ``utils.is_missing()`` to check them.
...
@@ -90,7 +90,7 @@ class ConfigBase:
...
@@ -90,7 +90,7 @@ class ConfigBase:
if
args
:
# maybe a key is misspelled
if
args
:
# maybe a key is misspelled
class_name
=
type
(
self
).
__name__
class_name
=
type
(
self
).
__name__
fields
=
', '
.
join
(
args
.
keys
())
fields
=
', '
.
join
(
args
.
keys
())
raise
Valu
eError
(
f
'
{
class_name
}
does not have field(s)
{
fields
}
'
)
raise
Attribut
eError
(
f
'
{
class_name
}
does not have field(s)
{
fields
}
'
)
# try to unpack nested config
# try to unpack nested config
for
field
in
dataclasses
.
fields
(
self
):
for
field
in
dataclasses
.
fields
(
self
):
...
@@ -135,7 +135,7 @@ class ConfigBase:
...
@@ -135,7 +135,7 @@ class ConfigBase:
with
open
(
path
)
as
yaml_file
:
with
open
(
path
)
as
yaml_file
:
data
=
yaml
.
safe_load
(
yaml_file
)
data
=
yaml
.
safe_load
(
yaml_file
)
if
not
isinstance
(
data
,
dict
):
if
not
isinstance
(
data
,
dict
):
raise
Valu
eError
(
f
'Conent of config file
{
path
}
is not a dict/object'
)
raise
Typ
eError
(
f
'Conent of config file
{
path
}
is not a dict/object'
)
utils
.
set_base_path
(
Path
(
path
).
parent
)
utils
.
set_base_path
(
Path
(
path
).
parent
)
config
=
cls
(
**
data
)
config
=
cls
(
**
data
)
utils
.
unset_base_path
()
utils
.
unset_base_path
()
...
@@ -143,10 +143,15 @@ class ConfigBase:
...
@@ -143,10 +143,15 @@ class ConfigBase:
def
canonical_copy
(
self
):
def
canonical_copy
(
self
):
"""
"""
Create a canonical
ized
copy of the config, and validate it.
Create a
"
canonical
"
copy of the config, and validate it.
This function is mainly used internally by NNI.
This function is mainly used internally by NNI.
Term explanation:
The config schema for end users is more flexible than the format NNI manager accepts,
so config classes have to deal with the conversion.
Here we call the converted format "canonical".
Returns
Returns
-------
-------
type(self)
type(self)
...
@@ -186,15 +191,16 @@ class ConfigBase:
...
@@ -186,15 +191,16 @@ class ConfigBase:
def
_canonicalize
(
self
,
parents
):
def
_canonicalize
(
self
,
parents
):
"""
"""
The config schema for end users is more flexible than the format NNI manager accepts.
To be overrided by subclass.
This method convert a config object to the constrained format accepted by NNI manager.
Convert the config object to canonical format.
The default implementation will:
The default implementation will:
1. Resolve all ``PathLike`` fields to absolute path
1. Resolve all ``PathLike`` fields to absolute path
2. Call ``_canonicalize()`` on all children config objects, including those inside list and dict
2. Call ``_canonicalize(
[self] + parents
)`` on all children config objects, including those inside list and dict
Subclasses are recommended to call ``super()._canonicalize(parents)`` at the end of their overrided version
.
If the subclass has nested config fields, be careful about where to call ``super()._canonicalize()``
.
Parameters
Parameters
----------
----------
...
@@ -212,6 +218,8 @@ class ConfigBase:
...
@@ -212,6 +218,8 @@ class ConfigBase:
def
_validate_canonical
(
self
):
def
_validate_canonical
(
self
):
"""
"""
To be overrided by subclass.
Validate legality of a canonical config object. It's caller's responsibility to ensure the config is canonical.
Validate legality of a canonical config object. It's caller's responsibility to ensure the config is canonical.
Raise exception if any problem found. This function does **not** return truth value.
Raise exception if any problem found. This function does **not** return truth value.
...
@@ -220,8 +228,6 @@ class ConfigBase:
...
@@ -220,8 +228,6 @@ class ConfigBase:
1. Validate that all fields match their type hint
1. Validate that all fields match their type hint
2. Call ``_validate_canonical()`` on children config objects, including those inside list and dict
2. Call ``_validate_canonical()`` on children config objects, including those inside list and dict
Subclasses are recommended to to call ``super()._validate_canonical()``.
"""
"""
utils
.
validate_type
(
self
)
utils
.
validate_type
(
self
)
for
field
in
dataclasses
.
fields
(
self
):
for
field
in
dataclasses
.
fields
(
self
):
...
@@ -229,6 +235,10 @@ class ConfigBase:
...
@@ -229,6 +235,10 @@ class ConfigBase:
_recursive_validate_child
(
value
)
_recursive_validate_child
(
value
)
def
__setattr__
(
self
,
name
,
value
):
def
__setattr__
(
self
,
name
,
value
):
"""
To prevent typo, config classes forbid assigning to attribute that is not a config field,
unless it starts with underscore.
"""
if
hasattr
(
self
,
name
)
or
name
.
startswith
(
'_'
):
if
hasattr
(
self
,
name
)
or
name
.
startswith
(
'_'
):
super
().
__setattr__
(
name
,
value
)
super
().
__setattr__
(
name
,
value
)
return
return
...
...
nni/experiment/config/exp_config.py
→
nni/experiment/config/exp
eriment
_config.py
View file @
3f6a8274
...
@@ -47,12 +47,16 @@ class ExperimentConfig(ConfigBase):
...
@@ -47,12 +47,16 @@ class ExperimentConfig(ConfigBase):
)
)
)
)
Fields commented as "training service field" acts like shortcut for all training services.
Users can either specify them here or inside training service config.
In latter case hybrid training services can have different settings.
.. _reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html
.. _reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html
"""
"""
# TODO:
# The behavior described below is expected but does not work,
# because some fields are consumed by TrialDispatcher outside environment service.
# Add the lines to docstr when we fix this issue.
# Fields commented as "training service field" acts like shortcut for all training services.
# Users can either specify them here or inside training service config.
# In latter case hybrid training services can have different settings.
experiment_name
:
Optional
[
str
]
=
None
experiment_name
:
Optional
[
str
]
=
None
search_space_file
:
Optional
[
utils
.
PathLike
]
=
None
search_space_file
:
Optional
[
utils
.
PathLike
]
=
None
...
...
nni/experiment/experiment.py
View file @
3f6a8274
...
@@ -29,6 +29,10 @@ class RunMode(Enum):
...
@@ -29,6 +29,10 @@ class RunMode(Enum):
- Background: stop NNI manager when Python script exits; do not print NNI manager log. (default)
- Background: stop NNI manager when Python script exits; do not print NNI manager log. (default)
- Foreground: stop NNI manager when Python script exits; print NNI manager log to stdout.
- Foreground: stop NNI manager when Python script exits; print NNI manager log to stdout.
- Detach: do not stop NNI manager when Python script exits.
- Detach: do not stop NNI manager when Python script exits.
NOTE:
This API is non-stable and is likely to get refactored in next release.
NNI manager should treat log level more seriously so we can default to "foreground" without being too verbose.
"""
"""
Background
=
'background'
Background
=
'background'
Foreground
=
'foreground'
Foreground
=
'foreground'
...
...
nni/tools/nnictl/launcher.py
View file @
3f6a8274
...
@@ -91,6 +91,9 @@ def create_experiment(args):
...
@@ -91,6 +91,9 @@ def create_experiment(args):
run_mode
=
RunMode
.
Foreground
if
foreground
else
RunMode
.
Detach
run_mode
=
RunMode
.
Foreground
if
foreground
else
RunMode
.
Detach
exp
.
start
(
port
,
debug
,
run_mode
)
exp
.
start
(
port
,
debug
,
run_mode
)
_logger
.
info
(
f
'To stop experiment run "nnictl stop
{
exp
.
id
}
" or "nnictl stop --all"'
)
_logger
.
info
(
'Reference: https://nni.readthedocs.io/en/stable/Tutorial/Nnictl.html'
)
def
resume_experiment
(
args
):
def
resume_experiment
(
args
):
exp_id
=
args
.
id
exp_id
=
args
.
id
port
=
args
.
port
port
=
args
.
port
...
...
test/ut/experiment/test_config_base.py
View file @
3f6a8274
...
@@ -145,7 +145,7 @@ def test_bad():
...
@@ -145,7 +145,7 @@ def test_bad():
config
.
validate
()
config
.
validate
()
except
Exception
as
e
:
except
Exception
as
e
:
exc
=
e
exc
=
e
assert
isinstance
(
exc
,
ValueError
),
tag
assert
exc
is
not
None
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
test_good
()
test_good
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment