mirror of
https://github.com/THU-MIG/yolov10.git
synced 2025-05-23 13:34:23 +08:00
ultralytics 8.0.141
create new SettingsManager (#3790)
This commit is contained in:
parent
42afe772d5
commit
20f5efd40a
@ -60,7 +60,7 @@ repos:
|
||||
hooks:
|
||||
- id: codespell
|
||||
args:
|
||||
- --ignore-words-list=crate,nd,strack,dota
|
||||
- --ignore-words-list=crate,nd,strack,dota,ane
|
||||
|
||||
# - repo: https://github.com/asottile/yesqa
|
||||
# rev: v1.4.0
|
||||
|
@ -234,14 +234,14 @@ We love your input! YOLOv5 and YOLOv8 would not be possible without help from ou
|
||||
|
||||
## <div align="center">License</div>
|
||||
|
||||
YOLOv8 is available under two different licenses:
|
||||
Ultralytics offers two licensing options to accommodate diverse use cases:
|
||||
|
||||
- **AGPL-3.0 License**: See [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for details.
|
||||
- **Enterprise License**: Provides greater flexibility for commercial product development without the open-source requirements of AGPL-3.0. Typical use cases are embedding Ultralytics software and AI models in commercial products and applications. Request an Enterprise License at [Ultralytics Licensing](https://ultralytics.com/license).
|
||||
- **AGPL-3.0 License**: This [OSI-approved](https://opensource.org/licenses/) open-source license is ideal for students and enthusiasts, promoting open collaboration and knowledge sharing. See the [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for more details.
|
||||
- **Enterprise License**: Designed for commercial use, this license permits seamless integration of Ultralytics software and AI models into commercial goods and services, bypassing the open-source requirements of AGPL-3.0. If your scenario involves embedding our solutions into a commercial offering, reach out through [Ultralytics Licensing](https://ultralytics.com/license).
|
||||
|
||||
## <div align="center">Contact</div>
|
||||
|
||||
For YOLOv8 bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
|
||||
For Ultralytics bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
|
||||
|
||||
<br>
|
||||
<div align="center">
|
||||
|
@ -233,14 +233,14 @@ success = model.export(format="onnx") # 将模型导出为 ONNX 格式
|
||||
|
||||
## <div align="center">许可证</div>
|
||||
|
||||
YOLOv8 提供两种不同的许可证:
|
||||
Ultralytics 提供两种许可证选项以适应各种使用场景:
|
||||
|
||||
- **AGPL-3.0 许可证**:详细信息请参阅 [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) 文件。
|
||||
- **企业许可证**:为商业产品开发提供更大的灵活性,无需遵循 AGPL-3.0 的开源要求。典型的用例是将 Ultralytics 软件和 AI 模型嵌入商业产品和应用中。在 [Ultralytics 授权](https://ultralytics.com/license) 处申请企业许可证。
|
||||
- **AGPL-3.0 许可证**:这个[OSI 批准](https://opensource.org/licenses/)的开源许可证非常适合学生和爱好者,可以推动开放的协作和知识分享。请查看[LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) 文件以了解更多细节。
|
||||
- **企业许可证**:专为商业用途设计,该许可证允许将 Ultralytics 的软件和 AI 模型无缝集成到商业产品和服务中,从而绕过 AGPL-3.0 的开源要求。如果您的场景涉及将我们的解决方案嵌入到商业产品中,请通过 [Ultralytics Licensing](https://ultralytics.com/license)与我们联系。
|
||||
|
||||
## <div align="center">联系方式</div>
|
||||
|
||||
对于 YOLOv8 的错误报告和功能请求,请访问 [GitHub Issues](https://github.com/ultralytics/ultralytics/issues),并加入我们的 [Discord](https://discord.gg/2wNGbc6g9X) 社区进行问题和讨论!
|
||||
对于 Ultralytics 的错误报告和功能请求,请访问 [GitHub Issues](https://github.com/ultralytics/ultralytics/issues),并加入我们的 [Discord](https://discord.gg/2wNGbc6g9X) 社区进行问题和讨论!
|
||||
|
||||
<br>
|
||||
<div align="center">
|
||||
|
@ -21,8 +21,8 @@ def extract_classes_and_functions(filepath):
|
||||
with open(filepath, 'r') as file:
|
||||
content = file.read()
|
||||
|
||||
class_pattern = r"(?:^|\n)class\s(\w+)(?:\(|:)"
|
||||
func_pattern = r"(?:^|\n)def\s(\w+)\("
|
||||
class_pattern = r'(?:^|\n)class\s(\w+)(?:\(|:)'
|
||||
func_pattern = r'(?:^|\n)def\s(\w+)\('
|
||||
|
||||
classes = re.findall(class_pattern, content)
|
||||
functions = re.findall(func_pattern, content)
|
||||
@ -34,18 +34,21 @@ def create_markdown(py_filepath, module_path, classes, functions):
|
||||
md_filepath = py_filepath.with_suffix('.md')
|
||||
|
||||
# Read existing content and keep header content between first two ---
|
||||
header_content = ""
|
||||
header_content = ''
|
||||
if md_filepath.exists():
|
||||
with open(md_filepath, 'r') as file:
|
||||
existing_content = file.read()
|
||||
header_parts = existing_content.split('---', 2)
|
||||
if 'description:' in header_parts or 'comments:' in header_parts and len(header_parts) >= 3:
|
||||
header_content = f"{header_parts[0]}---{header_parts[1]}---\n\n"
|
||||
header_parts = existing_content.split('---')
|
||||
for part in header_parts:
|
||||
if 'description:' in part or 'comments:' in part:
|
||||
header_content += f'---{part}---\n\n'
|
||||
|
||||
module_path = module_path.replace('.__init__', '')
|
||||
md_content = [f"## {class_name}\n---\n### ::: {module_path}.{class_name}\n<br><br>\n" for class_name in classes]
|
||||
md_content.extend(f"## {func_name}\n---\n### ::: {module_path}.{func_name}\n<br><br>\n" for func_name in functions)
|
||||
md_content = header_content + "\n".join(md_content)
|
||||
md_content = [f'## {class_name}\n---\n### ::: {module_path}.{class_name}\n<br><br>\n' for class_name in classes]
|
||||
md_content.extend(f'## {func_name}\n---\n### ::: {module_path}.{func_name}\n<br><br>\n' for func_name in functions)
|
||||
md_content = header_content + '\n'.join(md_content)
|
||||
if not md_content.endswith('\n'):
|
||||
md_content += '\n'
|
||||
|
||||
os.makedirs(os.path.dirname(md_filepath), exist_ok=True)
|
||||
with open(md_filepath, 'w') as file:
|
||||
@ -81,11 +84,11 @@ def create_nav_menu_yaml(nav_items):
|
||||
nav_tree_sorted = sort_nested_dict(nav_tree)
|
||||
|
||||
def _dict_to_yaml(d, level=0):
|
||||
yaml_str = ""
|
||||
indent = " " * level
|
||||
yaml_str = ''
|
||||
indent = ' ' * level
|
||||
for k, v in d.items():
|
||||
if isinstance(v, dict):
|
||||
yaml_str += f"{indent}- {k}:\n{_dict_to_yaml(v, level + 1)}"
|
||||
yaml_str += f'{indent}- {k}:\n{_dict_to_yaml(v, level + 1)}'
|
||||
else:
|
||||
yaml_str += f"{indent}- {k}: {str(v).replace('docs/', '')}\n"
|
||||
return yaml_str
|
||||
@ -99,7 +102,7 @@ def main():
|
||||
nav_items = []
|
||||
for root, _, files in os.walk(CODE_DIR):
|
||||
for file in files:
|
||||
if file.endswith(".py"):
|
||||
if file.endswith('.py'):
|
||||
py_filepath = Path(root) / file
|
||||
classes, functions = extract_classes_and_functions(py_filepath)
|
||||
|
||||
@ -113,5 +116,5 @@ def main():
|
||||
create_nav_menu_yaml(nav_items)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -181,3 +181,90 @@ For example, users can load a model, train it, evaluate its performance on a val
|
||||
```
|
||||
|
||||
[Python Guide](usage/python.md){.md-button .md-button--primary}
|
||||
|
||||
## Ultralytics Settings
|
||||
|
||||
The Ultralytics library provides a powerful settings management system to enable fine-grained control over your experiments. By making use of the `SettingsManager` housed within the `ultralytics.utils` module, users can readily access and alter their settings. These are stored in a YAML file and can be viewed or modified either directly within the Python environment or via the Command-Line Interface (CLI).
|
||||
|
||||
### Inspecting Settings
|
||||
|
||||
To gain insight into the current configuration of your settings, you can view them directly:
|
||||
|
||||
!!! example "View settings"
|
||||
|
||||
=== "Python"
|
||||
You can use Python to view your settings. Start by importing the `settings` object from the `ultralytics` module. Print and return settings using the following commands:
|
||||
```python
|
||||
from ultralytics import settings
|
||||
|
||||
# View all settings
|
||||
print(settings)
|
||||
|
||||
# Return a specific setting
|
||||
value = settings['runs_dir']
|
||||
```
|
||||
|
||||
=== "CLI"
|
||||
Alternatively, the command-line interface allows you to check your settings with a simple command:
|
||||
```bash
|
||||
yolo settings
|
||||
```
|
||||
|
||||
### Modifying Settings
|
||||
|
||||
Ultralytics allows users to easily modify their settings. Changes can be performed in the following ways:
|
||||
|
||||
!!! example "Update settings"
|
||||
|
||||
=== "Python"
|
||||
Within the Python environment, call the `update` method on the `settings` object to change your settings:
|
||||
```python
|
||||
from ultralytics import settings
|
||||
|
||||
# Update a setting
|
||||
settings.update({'runs_dir': '/path/to/runs'})
|
||||
|
||||
# Update multiple settings
|
||||
settings.update({'runs_dir': '/path/to/runs', 'tensorboard': False})
|
||||
|
||||
# Reset settings to default values
|
||||
settings.reset()
|
||||
```
|
||||
|
||||
=== "CLI"
|
||||
If you prefer using the command-line interface, the following command will allow you to modify your settings:
|
||||
```bash
|
||||
# Update a setting
|
||||
yolo settings runs_dir='/path/to/runs'
|
||||
|
||||
# Update multiple settings
|
||||
yolo settings runs_dir='/path/to/runs' tensorboard=False
|
||||
|
||||
# Reset settings to default values
|
||||
yolo settings reset
|
||||
```
|
||||
|
||||
### Understanding Settings
|
||||
|
||||
The table below provides an overview of the settings available for adjustment within Ultralytics. Each setting is outlined along with an example value, the data type, and a brief description.
|
||||
|
||||
| Name | Example Value | Data Type | Description |
|
||||
|--------------------|-----------------------|-----------|------------------------------------------------------------------------------------------------------------------|
|
||||
| `settings_version` | `'0.0.4'` | `str` | Ultralytics _settings_ version (different from Ultralytics [pip](https://pypi.org/project/ultralytics/) version) |
|
||||
| `datasets_dir` | `'/path/to/datasets'` | `str` | The directory where the datasets are stored |
|
||||
| `weights_dir` | `'/path/to/weights'` | `str` | The directory where the model weights are stored |
|
||||
| `runs_dir` | `'/path/to/runs'` | `str` | The directory where the experiment runs are stored |
|
||||
| `uuid` | `'a1b2c3d4'` | `str` | The unique identifier for the current settings |
|
||||
| `sync` | `True` | `bool` | Whether to sync analytics and crashes to HUB |
|
||||
| `api_key` | `''` | `str` | Ultralytics HUB [API Key](https://hub.ultralytics.com/settings?tab=api+keys) |
|
||||
| `clearml` | `True` | `bool` | Whether to use ClearML logging |
|
||||
| `comet` | `True` | `bool` | Whether to use [Comet ML](https://bit.ly/yolov8-readme-comet) for experiment tracking and visualization |
|
||||
| `dvc` | `True` | `bool` | Whether to use DVC for version control |
|
||||
| `hub` | `True` | `bool` | Whether to use [Ultralytics HUB](https://hub.ultralytics.com) integration |
|
||||
| `mlflow` | `True` | `bool` | Whether to use MLFlow for experiment tracking |
|
||||
| `neptune` | `True` | `bool` | Whether to use Neptune for experiment tracking |
|
||||
| `raytune` | `True` | `bool` | Whether to use Ray Tune for hyperparameter tuning |
|
||||
| `tensorboard` | `True` | `bool` | Whether to use TensorBoard for visualization |
|
||||
| `wandb` | `True` | `bool` | Whether to use Weights & Biases logging |
|
||||
|
||||
As you navigate through your projects or experiments, be sure to revisit these settings to ensure that they are optimally configured for your needs.
|
||||
|
@ -18,9 +18,9 @@ keywords: Ultralytics, YOLO, Configuration, cfg2dict, handle_deprecation, merge_
|
||||
### ::: ultralytics.cfg._handle_deprecation
|
||||
<br><br>
|
||||
|
||||
## check_cfg_mismatch
|
||||
## check_dict_alignment
|
||||
---
|
||||
### ::: ultralytics.cfg.check_cfg_mismatch
|
||||
### ::: ultralytics.cfg.check_dict_alignment
|
||||
<br><br>
|
||||
|
||||
## merge_equals_args
|
||||
@ -38,6 +38,16 @@ keywords: Ultralytics, YOLO, Configuration, cfg2dict, handle_deprecation, merge_
|
||||
### ::: ultralytics.cfg.handle_yolo_settings
|
||||
<br><br>
|
||||
|
||||
## parse_key_value_pair
|
||||
---
|
||||
### ::: ultralytics.cfg.parse_key_value_pair
|
||||
<br><br>
|
||||
|
||||
## smart_value
|
||||
---
|
||||
### ::: ultralytics.cfg.smart_value
|
||||
<br><br>
|
||||
|
||||
## entrypoint
|
||||
---
|
||||
### ::: ultralytics.cfg.entrypoint
|
||||
|
@ -1,8 +1,3 @@
|
||||
---
|
||||
description: Explore Ultralytics YOLO docs to understand task-specific models like DetectionModel, PoseModel, RTDETRDetectionModel and more. Plus, learn about ensemble, model loading.
|
||||
keywords: Ultralytics, YOLO docs, DetectionModel, SegmentationModel, ClassificationModel, Ensemble, torch_safe_load, yaml_model_load, guess_model_task
|
||||
---
|
||||
|
||||
## BaseModel
|
||||
---
|
||||
### ::: ultralytics.nn.tasks.BaseModel
|
||||
|
@ -28,6 +28,11 @@ keywords: Ultralytics, Utils, utilitarian functions, colorstr, yaml_save, set_lo
|
||||
### ::: ultralytics.utils.TryExcept
|
||||
<br><br>
|
||||
|
||||
## SettingsManager
|
||||
---
|
||||
### ::: ultralytics.utils.SettingsManager
|
||||
<br><br>
|
||||
|
||||
## plt_settings
|
||||
---
|
||||
### ::: ultralytics.utils.plt_settings
|
||||
@ -148,14 +153,9 @@ keywords: Ultralytics, Utils, utilitarian functions, colorstr, yaml_save, set_lo
|
||||
### ::: ultralytics.utils.set_sentry
|
||||
<br><br>
|
||||
|
||||
## get_settings
|
||||
## update_dict_recursive
|
||||
---
|
||||
### ::: ultralytics.utils.get_settings
|
||||
<br><br>
|
||||
|
||||
## set_settings
|
||||
---
|
||||
### ::: ultralytics.utils.set_settings
|
||||
### ::: ultralytics.utils.update_dict_recursive
|
||||
<br><br>
|
||||
|
||||
## deprecation_warn
|
||||
|
@ -8,6 +8,11 @@ keywords: Ultralytics, utility functions, file operations, working directory, fi
|
||||
### ::: ultralytics.utils.files.WorkingDirectory
|
||||
<br><br>
|
||||
|
||||
## spaces_in_path
|
||||
---
|
||||
### ::: ultralytics.utils.files.spaces_in_path
|
||||
<br><br>
|
||||
|
||||
## increment_path
|
||||
---
|
||||
### ::: ultralytics.utils.files.increment_path
|
||||
|
@ -74,7 +74,7 @@ Where:
|
||||
|
||||
!!! warning "Warning"
|
||||
|
||||
Arguments must be passed as `arg=val` pairs, split by an equals `=` sign and delimited by spaces ` ` between pairs. Do not use `--` argument prefixes or commas `,` beteen arguments.
|
||||
Arguments must be passed as `arg=val` pairs, split by an equals `=` sign and delimited by spaces ` ` between pairs. Do not use `--` argument prefixes or commas `,` between arguments.
|
||||
|
||||
- `yolo predict model=yolov8n.pt imgsz=640 conf=0.25` ✅
|
||||
- `yolo predict model yolov8n.pt imgsz 640 conf 0.25` ❌
|
||||
|
@ -29,7 +29,7 @@ To install the required packages, run:
|
||||
!!! tip "Installation"
|
||||
|
||||
```bash
|
||||
# Install and update Ultralytics and Ray Tune pacakges
|
||||
# Install and update Ultralytics and Ray Tune packages
|
||||
pip install -U ultralytics 'ray[tune]'
|
||||
|
||||
# Optionally install W&B for logging
|
||||
|
@ -1,13 +1,14 @@
|
||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
|
||||
__version__ = '8.0.140'
|
||||
__version__ = '8.0.141'
|
||||
|
||||
from ultralytics.engine.model import YOLO
|
||||
from ultralytics.hub import start
|
||||
from ultralytics.models import RTDETR, SAM
|
||||
from ultralytics.models.fastsam import FastSAM
|
||||
from ultralytics.models.nas import NAS
|
||||
from ultralytics.utils import SETTINGS as settings
|
||||
from ultralytics.utils.checks import check_yolo as checks
|
||||
from ultralytics.utils.downloads import download
|
||||
|
||||
__all__ = '__version__', 'YOLO', 'NAS', 'SAM', 'FastSAM', 'RTDETR', 'checks', 'download', 'start' # allow simpler import
|
||||
__all__ = '__version__', 'YOLO', 'NAS', 'SAM', 'FastSAM', 'RTDETR', 'checks', 'download', 'start', 'settings' # allow simpler import
|
||||
|
@ -9,9 +9,9 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from ultralytics.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, ROOT, USER_CONFIG_DIR,
|
||||
IterableSimpleNamespace, __version__, checks, colorstr, deprecation_warn, get_settings,
|
||||
yaml_load, yaml_print)
|
||||
from ultralytics.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, ROOT, SETTINGS, SETTINGS_YAML,
|
||||
IterableSimpleNamespace, __version__, checks, colorstr, deprecation_warn, yaml_load,
|
||||
yaml_print)
|
||||
|
||||
# Define valid tasks and modes
|
||||
MODES = 'train', 'val', 'predict', 'export', 'track', 'benchmark'
|
||||
@ -28,7 +28,6 @@ TASK2METRIC = {
|
||||
'classify': 'metrics/accuracy_top1',
|
||||
'pose': 'metrics/mAP50-95(P)'}
|
||||
|
||||
|
||||
CLI_HELP_MSG = \
|
||||
f"""
|
||||
Arguments received: {str(['yolo'] + sys.argv[1:])}. Ultralytics 'yolo' commands use the following syntax:
|
||||
@ -111,7 +110,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
|
||||
# Merge overrides
|
||||
if overrides:
|
||||
overrides = cfg2dict(overrides)
|
||||
check_cfg_mismatch(cfg, overrides)
|
||||
check_dict_alignment(cfg, overrides)
|
||||
cfg = {**cfg, **overrides} # merge cfg and overrides dicts (prefer overrides)
|
||||
|
||||
# Special handling for numeric project/name
|
||||
@ -147,9 +146,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
|
||||
|
||||
|
||||
def _handle_deprecation(custom):
|
||||
"""
|
||||
Hardcoded function to handle deprecated config keys
|
||||
"""
|
||||
"""Hardcoded function to handle deprecated config keys"""
|
||||
|
||||
for key in custom.copy().keys():
|
||||
if key == 'hide_labels':
|
||||
@ -165,7 +162,7 @@ def _handle_deprecation(custom):
|
||||
return custom
|
||||
|
||||
|
||||
def check_cfg_mismatch(base: Dict, custom: Dict, e=None):
|
||||
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.
|
||||
@ -175,13 +172,13 @@ def check_cfg_mismatch(base: Dict, custom: Dict, e=None):
|
||||
base (dict): a dictionary of base configuration options
|
||||
"""
|
||||
custom = _handle_deprecation(custom)
|
||||
base, custom = (set(x.keys()) for x in (base, custom))
|
||||
mismatched = [x for x in custom if x not in base]
|
||||
base_keys, custom_keys = (set(x.keys()) for x in (base, custom))
|
||||
mismatched = [k for k in custom_keys if k not in base_keys]
|
||||
if mismatched:
|
||||
string = ''
|
||||
for x in mismatched:
|
||||
matches = get_close_matches(x, base) # key list
|
||||
matches = [f'{k}={DEFAULT_CFG_DICT[k]}' if DEFAULT_CFG_DICT.get(k) is not None else k for k in matches]
|
||||
matches = get_close_matches(x, base_keys) # key list
|
||||
matches = [f'{k}={base[k]}' if base.get(k) is not None else k for k in matches]
|
||||
match_str = f'Similar arguments are i.e. {matches}.' if matches else ''
|
||||
string += f"'{colorstr('red', 'bold', x)}' is not a valid YOLO argument. {match_str}\n"
|
||||
raise SyntaxError(string + CLI_HELP_MSG) from e
|
||||
@ -251,12 +248,39 @@ def handle_yolo_settings(args: List[str]) -> None:
|
||||
Example:
|
||||
python my_script.py yolo settings reset
|
||||
"""
|
||||
path = USER_CONFIG_DIR / 'settings.yaml' # get SETTINGS YAML file path
|
||||
if any(args) and args[0] == 'reset':
|
||||
path.unlink() # delete the settings file
|
||||
get_settings() # create new settings
|
||||
LOGGER.info('Settings reset successfully') # inform the user that settings have been reset
|
||||
yaml_print(path) # print the current settings
|
||||
if any(args):
|
||||
if args[0] == 'reset':
|
||||
SETTINGS_YAML.unlink() # delete the settings file
|
||||
SETTINGS.reset() # create new settings
|
||||
LOGGER.info('Settings reset successfully') # inform the user that settings have been reset
|
||||
else:
|
||||
new = dict(parse_key_value_pair(a) for a in args)
|
||||
check_dict_alignment(SETTINGS, new)
|
||||
SETTINGS.update(new)
|
||||
|
||||
yaml_print(SETTINGS_YAML) # print the current settings
|
||||
|
||||
|
||||
def parse_key_value_pair(pair):
|
||||
"""Parse one 'key=value' pair and return key and value."""
|
||||
re.sub(r' *= *', '=', pair) # remove spaces around equals sign
|
||||
k, v = pair.split('=', 1) # split on first '=' sign
|
||||
assert v, f"missing '{k}' value"
|
||||
return k, smart_value(v)
|
||||
|
||||
|
||||
def smart_value(v):
|
||||
"""Convert a string to an underlying type such as int, float, bool, etc."""
|
||||
if v.lower() == 'none':
|
||||
return None
|
||||
elif v.lower() == 'true':
|
||||
return True
|
||||
elif v.lower() == 'false':
|
||||
return False
|
||||
else:
|
||||
with contextlib.suppress(Exception):
|
||||
return eval(v)
|
||||
return v
|
||||
|
||||
|
||||
def entrypoint(debug=''):
|
||||
@ -305,25 +329,14 @@ def entrypoint(debug=''):
|
||||
a = a[:-1]
|
||||
if '=' in a:
|
||||
try:
|
||||
re.sub(r' *= *', '=', a) # remove spaces around equals sign
|
||||
k, v = a.split('=', 1) # split on first '=' sign
|
||||
assert v, f"missing '{k}' value"
|
||||
k, v = parse_key_value_pair(a)
|
||||
if k == 'cfg': # custom.yaml passed
|
||||
LOGGER.info(f'Overriding {DEFAULT_CFG_PATH} with {v}')
|
||||
overrides = {k: val for k, val in yaml_load(checks.check_yaml(v)).items() if k != 'cfg'}
|
||||
else:
|
||||
if v.lower() == 'none':
|
||||
v = None
|
||||
elif v.lower() == 'true':
|
||||
v = True
|
||||
elif v.lower() == 'false':
|
||||
v = False
|
||||
else:
|
||||
with contextlib.suppress(Exception):
|
||||
v = eval(v)
|
||||
overrides[k] = v
|
||||
except (NameError, SyntaxError, ValueError, AssertionError) as e:
|
||||
check_cfg_mismatch(full_args_dict, {a: ''}, e)
|
||||
check_dict_alignment(full_args_dict, {a: ''}, e)
|
||||
|
||||
elif a in TASKS:
|
||||
overrides['task'] = a
|
||||
@ -338,13 +351,13 @@ def entrypoint(debug=''):
|
||||
raise SyntaxError(f"'{colorstr('red', 'bold', a)}' is a valid YOLO argument but is missing an '=' sign "
|
||||
f"to set its value, i.e. try '{a}={DEFAULT_CFG_DICT[a]}'\n{CLI_HELP_MSG}")
|
||||
else:
|
||||
check_cfg_mismatch(full_args_dict, {a: ''})
|
||||
check_dict_alignment(full_args_dict, {a: ''})
|
||||
|
||||
# Check keys
|
||||
check_cfg_mismatch(full_args_dict, overrides)
|
||||
check_dict_alignment(full_args_dict, overrides)
|
||||
|
||||
# Mode
|
||||
mode = overrides.get('mode', None)
|
||||
mode = overrides.get('mode')
|
||||
if mode is None:
|
||||
mode = DEFAULT_CFG.mode or 'predict'
|
||||
LOGGER.warning(f"WARNING ⚠️ 'mode' is missing. Valid modes are {MODES}. Using default 'mode={mode}'.")
|
||||
|
@ -3,7 +3,7 @@
|
||||
import requests
|
||||
|
||||
from ultralytics.hub.utils import HUB_API_ROOT, PREFIX, request_with_credentials
|
||||
from ultralytics.utils import LOGGER, SETTINGS, emojis, is_colab, set_settings
|
||||
from ultralytics.utils import LOGGER, SETTINGS, emojis, is_colab
|
||||
|
||||
API_KEY_URL = 'https://hub.ultralytics.com/settings?tab=api+keys'
|
||||
|
||||
@ -45,7 +45,7 @@ class Auth:
|
||||
|
||||
# Update SETTINGS with the new API key after successful authentication
|
||||
if success:
|
||||
set_settings({'api_key': self.api_key})
|
||||
SETTINGS.update({'api_key': self.api_key})
|
||||
# Log that the new login was successful
|
||||
if verbose:
|
||||
LOGGER.info(f'{PREFIX}New authentication successful ✅')
|
||||
|
@ -713,62 +713,105 @@ def set_sentry():
|
||||
logging.getLogger(logger).setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
def get_settings(file=SETTINGS_YAML, version='0.0.3'):
|
||||
def update_dict_recursive(d, u):
|
||||
"""
|
||||
Loads a global Ultralytics settings YAML file or creates one with default values if it does not exist.
|
||||
Recursively updates the dictionary `d` with the key-value pairs from the dictionary `u` without overwriting
|
||||
entire sub-dictionaries. Note that function recursion is intended and not a problem, as this allows for updating
|
||||
nested dictionaries at any arbitrary depth.
|
||||
|
||||
Args:
|
||||
file (Path): Path to the Ultralytics settings YAML file. Defaults to 'settings.yaml' in the USER_CONFIG_DIR.
|
||||
version (str): Settings version. If min settings version not met, new default settings will be saved.
|
||||
d (dict): The dictionary to be updated.
|
||||
u (dict): The dictionary to update `d` with.
|
||||
|
||||
Returns:
|
||||
(dict): Dictionary of settings key-value pairs.
|
||||
(dict): The recursively updated dictionary.
|
||||
"""
|
||||
import hashlib
|
||||
|
||||
from ultralytics.utils.checks import check_version
|
||||
from ultralytics.utils.torch_utils import torch_distributed_zero_first
|
||||
|
||||
git_dir = get_git_dir()
|
||||
root = git_dir or Path()
|
||||
datasets_root = (root.parent if git_dir and is_dir_writeable(root.parent) else root).resolve()
|
||||
defaults = {
|
||||
'datasets_dir': str(datasets_root / 'datasets'), # default datasets directory.
|
||||
'weights_dir': str(root / 'weights'), # default weights directory.
|
||||
'runs_dir': str(root / 'runs'), # default runs directory.
|
||||
'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), # SHA-256 anonymized UUID hash
|
||||
'sync': True, # sync analytics to help with YOLO development
|
||||
'api_key': '', # Ultralytics HUB API key (https://hub.ultralytics.com/)
|
||||
'settings_version': version} # Ultralytics settings version
|
||||
|
||||
with torch_distributed_zero_first(RANK):
|
||||
if not file.exists():
|
||||
yaml_save(file, defaults)
|
||||
settings = yaml_load(file)
|
||||
|
||||
# Check that settings keys and types match defaults
|
||||
correct = \
|
||||
settings \
|
||||
and settings.keys() == defaults.keys() \
|
||||
and all(type(a) == type(b) for a, b in zip(settings.values(), defaults.values())) \
|
||||
and check_version(settings['settings_version'], version)
|
||||
if not correct:
|
||||
LOGGER.warning('WARNING ⚠️ Ultralytics settings reset to defaults. This is normal and may be due to a '
|
||||
'recent ultralytics package update, but may have overwritten previous settings. '
|
||||
f"\nView and update settings with 'yolo settings' or at '{file}'")
|
||||
settings = defaults # merge **defaults with **settings (prefer **settings)
|
||||
yaml_save(file, settings) # save updated defaults
|
||||
|
||||
return settings
|
||||
for k, v in u.items():
|
||||
d[k] = update_dict_recursive(d.get(k, {}), v) if isinstance(v, dict) else v
|
||||
return d
|
||||
|
||||
|
||||
def set_settings(kwargs, file=SETTINGS_YAML):
|
||||
class SettingsManager(dict):
|
||||
"""
|
||||
Function that runs on a first-time ultralytics package installation to set up global settings and create necessary
|
||||
directories.
|
||||
Manages Ultralytics settings stored in a YAML file.
|
||||
|
||||
Args:
|
||||
file (str | Path): Path to the Ultralytics settings YAML file. Default is USER_CONFIG_DIR / 'settings.yaml'.
|
||||
version (str): Settings version. In case of local version mismatch, new default settings will be saved.
|
||||
"""
|
||||
SETTINGS.update(kwargs)
|
||||
yaml_save(file, SETTINGS)
|
||||
|
||||
def __init__(self, file=SETTINGS_YAML, version='0.0.4'):
|
||||
import copy
|
||||
import hashlib
|
||||
|
||||
from ultralytics.utils.checks import check_version
|
||||
from ultralytics.utils.torch_utils import torch_distributed_zero_first
|
||||
|
||||
git_dir = get_git_dir()
|
||||
root = git_dir or Path()
|
||||
datasets_root = (root.parent if git_dir and is_dir_writeable(root.parent) else root).resolve()
|
||||
|
||||
self.file = Path(file)
|
||||
self.version = version
|
||||
self.defaults = {
|
||||
'settings_version': version,
|
||||
'datasets_dir': str(datasets_root / 'datasets'),
|
||||
'weights_dir': str(root / 'weights'),
|
||||
'runs_dir': str(root / 'runs'),
|
||||
'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(),
|
||||
'sync': True,
|
||||
'api_key': '',
|
||||
'clearml': True, # integrations
|
||||
'comet': True,
|
||||
'dvc': True,
|
||||
'hub': True,
|
||||
'mlflow': True,
|
||||
'neptune': True,
|
||||
'raytune': True,
|
||||
'tensorboard': True,
|
||||
'wandb': True}
|
||||
|
||||
super().__init__(copy.deepcopy(self.defaults))
|
||||
|
||||
with torch_distributed_zero_first(RANK):
|
||||
if not self.file.exists():
|
||||
self.save()
|
||||
|
||||
self.load()
|
||||
correct_keys = self.keys() == self.defaults.keys()
|
||||
correct_types = all(type(a) == type(b) for a, b in zip(self.values(), self.defaults.values()))
|
||||
correct_version = check_version(self['settings_version'], self.version)
|
||||
if not (correct_keys and correct_types and correct_version):
|
||||
LOGGER.warning(
|
||||
'WARNING ⚠️ Ultralytics settings reset to default values. This may be due to a possible problem '
|
||||
'with your settings or a recent ultralytics package update. '
|
||||
f"\nView settings with 'yolo settings' or at '{self.file}'"
|
||||
"\nUpdate settings with 'yolo settings key=value', i.e. 'yolo settings runs_dir=path/to/dir'.")
|
||||
self.reset()
|
||||
|
||||
def load(self):
|
||||
"""Loads settings from the YAML file."""
|
||||
self.update(yaml_load(self.file))
|
||||
|
||||
def save(self):
|
||||
"""Saves the current settings to the YAML file."""
|
||||
yaml_save(self.file, dict(self))
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
"""Updates a setting value in the current settings and saves the settings."""
|
||||
new = dict(*args, **kwargs)
|
||||
if any(isinstance(v, dict) for v in new.values()):
|
||||
update_dict_recursive(self, new)
|
||||
else:
|
||||
# super().update(*args, **kwargs)
|
||||
super().update(new)
|
||||
self.save()
|
||||
|
||||
def reset(self):
|
||||
"""Resets the settings to default and saves them."""
|
||||
self.clear()
|
||||
self.update(self.defaults)
|
||||
self.save()
|
||||
|
||||
|
||||
def deprecation_warn(arg, new_arg, version=None):
|
||||
@ -794,7 +837,7 @@ def url2file(url):
|
||||
|
||||
# Check first-install steps
|
||||
PREFIX = colorstr('Ultralytics: ')
|
||||
SETTINGS = get_settings()
|
||||
SETTINGS = SettingsManager() # initialize settings
|
||||
DATASETS_DIR = Path(SETTINGS['datasets_dir']) # global datasets directory
|
||||
ENVIRONMENT = 'Colab' if is_colab() else 'Kaggle' if is_kaggle() else 'Jupyter' if is_jupyter() else \
|
||||
'Docker' if is_docker() else platform.system()
|
||||
|
@ -5,7 +5,7 @@ import re
|
||||
import matplotlib.image as mpimg
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from ultralytics.utils import LOGGER, TESTS_RUNNING
|
||||
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
try:
|
||||
@ -16,6 +16,7 @@ try:
|
||||
|
||||
assert hasattr(clearml, '__version__') # verify package is not directory
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert SETTINGS['clearml'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
clearml = None
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from ultralytics.utils import LOGGER, RANK, TESTS_RUNNING, ops
|
||||
from ultralytics.utils import LOGGER, RANK, SETTINGS, TESTS_RUNNING, ops
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
try:
|
||||
@ -11,6 +11,7 @@ try:
|
||||
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert hasattr(comet_ml, '__version__') # verify package is not directory
|
||||
assert SETTINGS['comet'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
comet_ml = None
|
||||
|
||||
|
@ -3,7 +3,7 @@ import os
|
||||
|
||||
import pkg_resources as pkg
|
||||
|
||||
from ultralytics.utils import LOGGER, TESTS_RUNNING
|
||||
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
try:
|
||||
@ -12,6 +12,7 @@ try:
|
||||
import dvclive
|
||||
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert SETTINGS['dvc'] is True # verify integration is enabled
|
||||
|
||||
ver = version('dvclive')
|
||||
if pkg.parse_version(ver) < pkg.parse_version('2.11.0'):
|
||||
|
@ -4,7 +4,7 @@ import json
|
||||
from time import time
|
||||
|
||||
from ultralytics.hub.utils import PREFIX, events
|
||||
from ultralytics.utils import LOGGER
|
||||
from ultralytics.utils import LOGGER, SETTINGS
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
|
||||
@ -84,4 +84,4 @@ callbacks = {
|
||||
'on_train_start': on_train_start,
|
||||
'on_val_start': on_val_start,
|
||||
'on_predict_start': on_predict_start,
|
||||
'on_export_start': on_export_start}
|
||||
'on_export_start': on_export_start} if SETTINGS['hub'] is True else {} # verify enabled
|
||||
|
@ -4,13 +4,14 @@ import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from ultralytics.utils import LOGGER, TESTS_RUNNING, colorstr
|
||||
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
|
||||
|
||||
try:
|
||||
import mlflow
|
||||
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert hasattr(mlflow, '__version__') # verify package is not directory
|
||||
assert SETTINGS['mlflow'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
mlflow = None
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import matplotlib.image as mpimg
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from ultralytics.utils import LOGGER, TESTS_RUNNING
|
||||
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
try:
|
||||
@ -12,6 +12,7 @@ try:
|
||||
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert hasattr(neptune, '__version__')
|
||||
assert SETTINGS['neptune'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
neptune = None
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
|
||||
from ultralytics.utils import SETTINGS
|
||||
|
||||
try:
|
||||
import ray
|
||||
from ray import tune
|
||||
from ray.air import session
|
||||
|
||||
assert SETTINGS['raytune'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
tune = None
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
|
||||
from ultralytics.utils import LOGGER, TESTS_RUNNING, colorstr
|
||||
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
|
||||
|
||||
try:
|
||||
from torch.utils.tensorboard import SummaryWriter
|
||||
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert SETTINGS['tensorboard'] is True # verify integration is enabled
|
||||
|
||||
# TypeError for handling 'Descriptors cannot not be created directly.' protobuf errors in Windows
|
||||
except (ImportError, AssertionError, TypeError):
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
from ultralytics.utils import TESTS_RUNNING
|
||||
from ultralytics.utils import SETTINGS, TESTS_RUNNING
|
||||
from ultralytics.utils.torch_utils import model_info_for_loggers
|
||||
|
||||
try:
|
||||
@ -7,6 +7,7 @@ try:
|
||||
|
||||
assert hasattr(wb, '__version__')
|
||||
assert not TESTS_RUNNING # do not log pytest
|
||||
assert SETTINGS['wandb'] is True # verify integration is enabled
|
||||
except (ImportError, AssertionError):
|
||||
wb = None
|
||||
|
||||
@ -16,7 +17,7 @@ _processed_plots = {}
|
||||
def _log_plots(plots, step):
|
||||
for name, params in plots.items():
|
||||
timestamp = params['timestamp']
|
||||
if _processed_plots.get(name, None) != timestamp:
|
||||
if _processed_plots.get(name) != timestamp:
|
||||
wb.run.log({name.stem: wb.Image(str(name))}, step=step)
|
||||
_processed_plots[name] = timestamp
|
||||
|
||||
|
@ -38,7 +38,7 @@ def spaces_in_path(path):
|
||||
path (str | Path): The original path.
|
||||
|
||||
Yields:
|
||||
Path: Temporary path with spaces replaced by underscores if spaces were present, otherwise the original path.
|
||||
(Path): Temporary path with spaces replaced by underscores if spaces were present, otherwise the original path.
|
||||
|
||||
Examples:
|
||||
with spaces_in_path('/path/with spaces') as new_path:
|
||||
|
Loading…
x
Reference in New Issue
Block a user