Update Results and CFG docstrings (#14139)

Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com>
Co-authored-by: UltralyticsAssistant <web@ultralytics.com>
This commit is contained in:
Glenn Jocher 2024-07-01 21:18:55 +02:00 committed by GitHub
parent 08bc98812c
commit 0f2bee4cc6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 299 additions and 103 deletions

View file

@ -187,10 +187,31 @@ def cfg2dict(cfg):
Convert a configuration object to a dictionary, whether it is a file path, a string, or a SimpleNamespace object.
Args:
cfg (str | Path | dict | SimpleNamespace): Configuration object to be converted to a dictionary.
cfg (str | Path | dict | SimpleNamespace): Configuration object to be converted to a dictionary. This may be a
path to a configuration file, a dictionary, or a SimpleNamespace object.
Returns:
cfg (dict): Configuration object in dictionary format.
(dict): Configuration object in dictionary format.
Example:
```python
from ultralytics.cfg import cfg2dict
from types import SimpleNamespace
# Example usage with a file path
config_dict = cfg2dict('config.yaml')
# Example usage with a SimpleNamespace
config_sn = SimpleNamespace(param1='value1', param2='value2')
config_dict = cfg2dict(config_sn)
# Example usage with a dictionary (returns the same dictionary)
config_dict = cfg2dict({'param1': 'value1', 'param2': 'value2'})
```
Notes:
- If `cfg` is a path or a string, it will be loaded as YAML and converted to a dictionary.
- If `cfg` is a SimpleNamespace object, it will be converted to a dictionary using `vars()`.
"""
if isinstance(cfg, (str, Path)):
cfg = yaml_load(cfg) # load dict
@ -201,14 +222,36 @@ def cfg2dict(cfg):
def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):
"""
Load and merge configuration data from a file or dictionary.
Load and merge configuration data from a file or dictionary, with optional overrides.
Args:
cfg (str | Path | Dict | SimpleNamespace): Configuration data.
overrides (str | Dict | optional): Overrides in the form of a file name or a dictionary. Default is None.
cfg (str | Path | dict | SimpleNamespace, optional): Configuration data source. Defaults to `DEFAULT_CFG_DICT`.
overrides (dict | None, optional): Dictionary containing key-value pairs to override the base configuration.
Defaults to None.
Returns:
(SimpleNamespace): Training arguments namespace.
(SimpleNamespace): Namespace containing the merged training arguments.
Notes:
- If both `cfg` and `overrides` are provided, the values in `overrides` will take precedence.
- Special handling ensures alignment and correctness of the configuration, such as converting numeric `project`
and `name` to strings and validating the configuration keys and values.
Example:
```python
from ultralytics.cfg import get_cfg
# Load default configuration
config = get_cfg()
# Load from a custom file with overrides
config = get_cfg('path/to/config.yaml', overrides={'epochs': 50, 'batch_size': 16})
```
Configuration dictionary merged with overrides:
```python
{'epochs': 50, 'batch_size': 16, ...}
```
"""
cfg = cfg2dict(cfg)
@ -236,7 +279,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
def check_cfg(cfg, hard=True):
"""Check Ultralytics configuration argument types and values."""
"""Validate Ultralytics configuration argument types and values, converting them if necessary."""
for k, v in cfg.items():
if v is not None: # None values may be from optional args
if k in CFG_FLOAT_KEYS and not isinstance(v, (int, float)):
@ -272,7 +315,7 @@ def check_cfg(cfg, hard=True):
def get_save_dir(args, name=None):
"""Return save_dir as created from train/val/predict arguments."""
"""Returns the directory path for saving outputs, derived from arguments or default settings."""
if getattr(args, "save_dir", None):
save_dir = args.save_dir
@ -287,7 +330,7 @@ def get_save_dir(args, name=None):
def _handle_deprecation(custom):
"""Hardcoded function to handle deprecated config keys."""
"""Handles deprecated configuration keys by mapping them to current equivalents with deprecation warnings."""
for key in custom.copy().keys():
if key == "boxes":
@ -308,13 +351,35 @@ def _handle_deprecation(custom):
def check_dict_alignment(base: Dict, custom: Dict, e=None):
"""
This function checks for any mismatched keys between a custom configuration list and a base configuration list. If
any mismatched keys are found, the function prints out similar keys from the base list and exits the program.
Check for key alignment between custom and base configuration dictionaries, catering for deprecated keys and
providing informative error messages for mismatched keys.
Args:
custom (dict): a dictionary of custom configuration options
base (dict): a dictionary of base configuration options
e (Error, optional): An optional error that is passed by the calling function.
base (dict): The base configuration dictionary containing valid keys.
custom (dict): The custom configuration dictionary to be checked for alignment.
e (Exception, optional): An optional error instance passed by the calling function. Default is None.
Raises:
SystemExit: Terminates the program execution if mismatched keys are found.
Notes:
- The function provides suggestions for mismatched keys based on their similarity to valid keys in the
base configuration.
- Deprecated keys in the custom configuration are automatically handled and replaced with their updated
equivalents.
- A detailed error message is printed for each mismatched key, helping users to quickly identify and correct
their custom configurations.
Example:
```python
base_cfg = {'epochs': 50, 'lr0': 0.01, 'batch_size': 16}
custom_cfg = {'epoch': 100, 'lr': 0.02, 'batch_size': 32}
try:
check_dict_alignment(base_cfg, custom_cfg)
except SystemExit:
# Handle the error or correct the configuration
```
"""
custom = _handle_deprecation(custom)
base_keys, custom_keys = (set(x.keys()) for x in (base, custom))
@ -341,6 +406,22 @@ def merge_equals_args(args: List[str]) -> List[str]:
Returns:
(List[str]): A list of strings where the arguments around isolated '=' are merged.
Example:
The function modifies the argument list as follows:
```python
args = ["arg1", "=", "value"]
new_args = merge_equals_args(args)
print(new_args) # Output: ["arg1=value"]
args = ["arg1=", "value"]
new_args = merge_equals_args(args)
print(new_args) # Output: ["arg1=value"]
args = ["arg1", "=value"]
new_args = merge_equals_args(args)
print(new_args) # Output: ["arg1=value"]
```
"""
new_args = []
for i, arg in enumerate(args):
@ -361,15 +442,18 @@ def handle_yolo_hub(args: List[str]) -> None:
"""
Handle Ultralytics HUB command-line interface (CLI) commands.
This function processes Ultralytics HUB CLI commands such as login and logout.
It should be called when executing a script with arguments related to HUB authentication.
This function processes Ultralytics HUB CLI commands such as login and logout. It should be called when executing
a script with arguments related to HUB authentication.
Args:
args (List[str]): A list of command line arguments
args (List[str]): A list of command line arguments.
Returns:
None
Example:
```bash
python my_script.py hub login your_api_key
yolo hub login YOUR_API_KEY
```
"""
from ultralytics import hub
@ -387,16 +471,23 @@ def handle_yolo_settings(args: List[str]) -> None:
"""
Handle YOLO settings command-line interface (CLI) commands.
This function processes YOLO settings CLI commands such as reset.
It should be called when executing a script with arguments related to YOLO settings management.
This function processes YOLO settings CLI commands such as reset. It should be called when executing a script with
arguments related to YOLO settings management.
Args:
args (List[str]): A list of command line arguments for YOLO settings management.
Returns:
None
Example:
```bash
python my_script.py yolo settings reset
yolo settings reset
```
Notes:
For more information on handling YOLO settings, visit:
https://docs.ultralytics.com/quickstart/#ultralytics-settings
"""
url = "https://docs.ultralytics.com/quickstart/#ultralytics-settings" # help URL
try:
@ -417,7 +508,7 @@ def handle_yolo_settings(args: List[str]) -> None:
def handle_explorer():
"""Open the Ultralytics Explorer GUI."""
"""Open the Ultralytics Explorer GUI for dataset exploration and analysis."""
checks.check_requirements("streamlit")
LOGGER.info("💡 Loading Explorer dashboard...")
subprocess.run(["streamlit", "run", ROOT / "data/explorer/gui/dash.py", "--server.maxMessageSize", "2048"])
@ -432,7 +523,7 @@ def parse_key_value_pair(pair):
def smart_value(v):
"""Convert a string to an underlying type such as int, float, bool, etc."""
"""Convert a string to its appropriate type (int, float, bool, None, etc.)."""
v_lower = v.lower()
if v_lower == "none":
return None
@ -448,18 +539,33 @@ def smart_value(v):
def entrypoint(debug=""):
"""
This function is the ultralytics package entrypoint, it's responsible for parsing the command line arguments passed
to the package.
Ultralytics entrypoint function for parsing and executing command-line arguments.
This function allows for:
- passing mandatory YOLO args as a list of strings
- specifying the task to be performed, either 'detect', 'segment' or 'classify'
- specifying the mode, either 'train', 'val', 'test', or 'predict'
- running special modes like 'checks'
- passing overrides to the package's configuration
This function serves as the main entry point for the Ultralytics CLI, parsing command-line arguments and
executing the corresponding tasks such as training, validation, prediction, exporting models, and more.
It uses the package's default cfg and initializes it using the passed overrides.
Then it calls the CLI function with the composed cfg
Args:
debug (str, optional): Space-separated string of command-line arguments for debugging purposes. Default is "".
Returns:
(None): This function does not return any value.
Notes:
- For a list of all available commands and their arguments, see the provided help messages and the Ultralytics
documentation at https://docs.ultralytics.com.
- If no arguments are passed, the function will display the usage help message.
Example:
```python
# Train a detection model for 10 epochs with an initial learning_rate of 0.01
entrypoint("train data=coco8.yaml model=yolov8n.pt epochs=10 lr0=0.01")
# Predict a YouTube video using a pretrained segmentation model at image size 320
entrypoint("predict model=yolov8n-seg.pt source='https://youtu.be/LNwODJXcvt4' imgsz=320")
# Validate a pretrained detection model at batch-size 1 and image size 640
entrypoint("val model=yolov8n.pt data=coco8.yaml batch=1 imgsz=640")
```
"""
args = (debug.split(" ") if debug else ARGV)[1:]
if not args: # no arguments passed
@ -596,7 +702,7 @@ def entrypoint(debug=""):
# Special modes --------------------------------------------------------------------------------------------------------
def copy_default_cfg():
"""Copy and create a new default configuration file with '_copy' appended to its name."""
"""Copy and create a new default configuration file with '_copy' appended to its name, providing usage example."""
new_file = Path.cwd() / DEFAULT_CFG_PATH.name.replace(".yaml", "_copy.yaml")
shutil.copy2(DEFAULT_CFG_PATH, new_file)
LOGGER.info(