From 3d60347755db969277628570745ffbbdd43289b6 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sun, 23 Apr 2023 15:28:22 +0200 Subject: [PATCH] `ultralytics 8.0.86` HUB resume, Classify train and RayTune fixes (#2200) Co-authored-by: Ayush Chaurasia --- docs/build_reference.py | 19 +++++++------- docs/reference/hub/utils.md | 4 +-- docs/usage/hyperparameter_tuning.md | 1 - mkdocs.yml | 1 + ultralytics/__init__.py | 2 +- ultralytics/hub/utils.py | 11 +++++--- ultralytics/yolo/engine/trainer.py | 1 + ultralytics/yolo/utils/__init__.py | 36 ++++++++++++++++++++++----- ultralytics/yolo/utils/tuner.py | 1 - ultralytics/yolo/v8/classify/train.py | 2 +- 10 files changed, 52 insertions(+), 26 deletions(-) diff --git a/docs/build_reference.py b/docs/build_reference.py index b8f6d88a..84e11f9a 100644 --- a/docs/build_reference.py +++ b/docs/build_reference.py @@ -10,8 +10,11 @@ import os import re from collections import defaultdict from pathlib import Path +from ultralytics.yolo.utils import ROOT -TARGET_DIR = Path('..') +NEW_YAML_DIR = ROOT.parent +CODE_DIR = ROOT +REFERENCE_DIR = ROOT.parent / 'docs/reference' def extract_classes_and_functions(filepath): @@ -38,7 +41,7 @@ def create_markdown(py_filepath, module_path, classes, functions): with open(md_filepath, 'w') as file: file.write(md_content) - return md_filepath.relative_to(TARGET_DIR) + return md_filepath.relative_to(NEW_YAML_DIR) def nested_dict(): @@ -77,26 +80,22 @@ def create_nav_menu_yaml(nav_items): yaml_str += f"{indent}- {k}: {str(v).replace('docs/', '')}\n" return yaml_str - with open(TARGET_DIR / 'nav_menu_updated.yml', 'w') as file: + with open(NEW_YAML_DIR / 'nav_menu_updated.yml', 'w') as file: yaml_str = _dict_to_yaml(nav_tree_sorted) file.write(yaml_str) def main(): - source_dir = Path("../ultralytics") - target_dir = Path("reference") - nav_items = [] - - for root, _, files in os.walk(source_dir): + for root, _, files in os.walk(CODE_DIR): for file in files: if file.endswith(".py") and file != "__init__.py": py_filepath = Path(root) / file classes, functions = extract_classes_and_functions(py_filepath) if classes or functions: - py_filepath_rel = py_filepath.relative_to(source_dir) - md_filepath = target_dir / py_filepath_rel + py_filepath_rel = py_filepath.relative_to(CODE_DIR) + md_filepath = REFERENCE_DIR / py_filepath_rel module_path = f"ultralytics.{py_filepath_rel.with_suffix('').as_posix().replace('/', '.')}" md_rel_filepath = create_markdown(md_filepath, module_path, classes, functions) nav_items.append(str(md_rel_filepath)) diff --git a/docs/reference/hub/utils.md b/docs/reference/hub/utils.md index 2931d9ca..82dba746 100644 --- a/docs/reference/hub/utils.md +++ b/docs/reference/hub/utils.md @@ -1,6 +1,6 @@ -# Traces +# Events --- -:::ultralytics.hub.utils.Traces +:::ultralytics.hub.utils.Events

# request_with_credentials diff --git a/docs/usage/hyperparameter_tuning.md b/docs/usage/hyperparameter_tuning.md index d9957eff..e261785e 100644 --- a/docs/usage/hyperparameter_tuning.md +++ b/docs/usage/hyperparameter_tuning.md @@ -70,7 +70,6 @@ The following table lists the default search space parameters for hyperparameter | warmup_momentum | `tune.uniform(0.0, 0.95)` | Warmup momentum | | box | `tune.uniform(0.02, 0.2)` | Box loss weight | | cls | `tune.uniform(0.2, 4.0)` | Class loss weight | -| fl_gamma | `tune.uniform(0.0, 2.0)` | Focal loss gamma | | hsv_h | `tune.uniform(0.0, 0.1)` | Hue augmentation range | | hsv_s | `tune.uniform(0.0, 0.9)` | Saturation augmentation range | | hsv_v | `tune.uniform(0.0, 0.9)` | Value (brightness) augmentation range | diff --git a/mkdocs.yml b/mkdocs.yml index a524c85b..bf9e7570 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -200,6 +200,7 @@ nav: - comet: reference/yolo/utils/callbacks/comet.md - hub: reference/yolo/utils/callbacks/hub.md - mlflow: reference/yolo/utils/callbacks/mlflow.md + - neptune: reference/yolo/utils/callbacks/neptune.md - raytune: reference/yolo/utils/callbacks/raytune.md - tensorboard: reference/yolo/utils/callbacks/tensorboard.md - wb: reference/yolo/utils/callbacks/wb.md diff --git a/ultralytics/__init__.py b/ultralytics/__init__.py index 2278f09f..82163660 100644 --- a/ultralytics/__init__.py +++ b/ultralytics/__init__.py @@ -1,6 +1,6 @@ # Ultralytics YOLO 🚀, AGPL-3.0 license -__version__ = '8.0.85' +__version__ = '8.0.86' from ultralytics.hub import start from ultralytics.yolo.engine.model import YOLO diff --git a/ultralytics/hub/utils.py b/ultralytics/hub/utils.py index c86060a0..e2492ee8 100644 --- a/ultralytics/hub/utils.py +++ b/ultralytics/hub/utils.py @@ -2,6 +2,7 @@ import os import platform +import random import sys import threading import time @@ -147,7 +148,7 @@ class Events: disabled when sync=False. Run 'yolo settings' to see and update settings YAML file. Attributes: - url (str): The GA4 Measurement Protocol URL. + url (str): The URL to send anonymous events. rate_limit (float): The rate limit in seconds for sending events. metadata (dict): A dictionary containing metadata about the environment. enabled (bool): A flag to enable or disable Events based on certain conditions. @@ -165,9 +166,11 @@ class Events: self.metadata = { 'cli': Path(sys.argv[0]).name == 'yolo', 'install': 'git' if is_git_dir() else 'pip' if is_pip_package() else 'other', - 'python': platform.python_version(), + 'python': '.'.join(platform.python_version_tuple()[:2]), # i.e. 3.10 'version': __version__, - 'env': ENVIRONMENT} + 'env': ENVIRONMENT, + 'session_id': round(random.random() * 1E15), + 'engagement_time_msec': 1000} self.enabled = \ SETTINGS['sync'] and \ RANK in (-1, 0) and \ @@ -180,7 +183,7 @@ class Events: Attempts to add a new event to the events list and send events if the rate limit is reached. Args: - cfg: The configuration object containing mode and task information. + cfg (IterableSimpleNamespace): The configuration object containing mode and task information. """ if not self.enabled: # Events disabled, do nothing diff --git a/ultralytics/yolo/engine/trainer.py b/ultralytics/yolo/engine/trainer.py index eb7e26ba..4d6bbd66 100644 --- a/ultralytics/yolo/engine/trainer.py +++ b/ultralytics/yolo/engine/trainer.py @@ -281,6 +281,7 @@ class BaseTrainer: if self.args.close_mosaic: base_idx = (self.epochs - self.args.close_mosaic) * nb self.plot_idx.extend([base_idx, base_idx + 1, base_idx + 2]) + epoch = self.epochs # predefine for resume fully trained model edge cases for epoch in range(self.start_epoch, self.epochs): self.epoch = epoch self.run_callbacks('on_train_epoch_start') diff --git a/ultralytics/yolo/utils/__init__.py b/ultralytics/yolo/utils/__init__.py index 620ddb9e..90ebe63a 100644 --- a/ultralytics/yolo/utils/__init__.py +++ b/ultralytics/yolo/utils/__init__.py @@ -605,11 +605,35 @@ def threaded(func): def set_sentry(): """ - Initialize the Sentry SDK for error tracking and reporting if pytest is not currently running. + Initialize the Sentry SDK for error tracking and reporting. Enabled when sync=True in settings and + disabled when sync=False. Run 'yolo settings' to see and update settings YAML file. + + Conditions required to send errors: + - sync=True in YOLO settings + - pytest is not running + - running in a pip package installation + - running in a non-git directory + - running with rank -1 or 0 + - online environment + - CLI used to run package (checked with 'yolo' as the name of the main CLI command) + + The function also configures Sentry SDK to ignore KeyboardInterrupt and FileNotFoundError + exceptions and to exclude events with 'out of memory' in their exception message. + + Additionally, the function sets custom tags and user information for Sentry events. """ def before_send(event, hint): - """A function executed before sending the event to Sentry.""" + """ + Modify the event before sending it to Sentry based on specific exception types and messages. + + Args: + event (dict): The event dictionary containing information about the error. + hint (dict): A dictionary containing additional information about the error. + + Returns: + dict: The modified event or None if the event should not be sent to Sentry. + """ if 'exc_info' in hint: exc_type, exc_value, tb = hint['exc_info'] if exc_type in (KeyboardInterrupt, FileNotFoundError) \ @@ -628,19 +652,19 @@ def set_sentry(): Path(sys.argv[0]).name == 'yolo' and \ not TESTS_RUNNING and \ ONLINE and \ - ((is_pip_package() and not is_git_dir()) or - (get_git_origin_url() == 'https://github.com/ultralytics/ultralytics.git' and get_git_branch() == 'main')): + is_pip_package() and \ + not is_git_dir(): import sentry_sdk # noqa sentry_sdk.init( - dsn='https://f805855f03bb4363bc1e16cb7d87b654@o4504521589325824.ingest.sentry.io/4504521592406016', + dsn='https://5ff1556b71594bfea135ff0203a0d290@o4504521589325824.ingest.sentry.io/4504521592406016', debug=False, traces_sample_rate=1.0, release=__version__, environment='production', # 'dev' or 'production' before_send=before_send, ignore_errors=[KeyboardInterrupt, FileNotFoundError]) - sentry_sdk.set_user({'id': SETTINGS['uuid']}) + sentry_sdk.set_user({'id': SETTINGS['uuid']}) # SHA-256 anonymized UUID hash # Disable all sentry logging for logger in 'sentry_sdk', 'sentry_sdk.errors': diff --git a/ultralytics/yolo/utils/tuner.py b/ultralytics/yolo/utils/tuner.py index 3c69d1d2..53d6e89b 100644 --- a/ultralytics/yolo/utils/tuner.py +++ b/ultralytics/yolo/utils/tuner.py @@ -21,7 +21,6 @@ default_space = { 'warmup_momentum': tune.uniform(0.0, 0.95), # warmup initial momentum 'box': tune.uniform(0.02, 0.2), # box loss gain 'cls': tune.uniform(0.2, 4.0), # cls loss gain (scale with pixels) - 'fl_gamma': tune.uniform(0.0, 2.0), # focal loss gamma (efficientDet default gamma=1.5) 'hsv_h': tune.uniform(0.0, 0.1), # image HSV-Hue augmentation (fraction) 'hsv_s': tune.uniform(0.0, 0.9), # image HSV-Saturation augmentation (fraction) 'hsv_v': tune.uniform(0.0, 0.9), # image HSV-Value augmentation (fraction) diff --git a/ultralytics/yolo/v8/classify/train.py b/ultralytics/yolo/v8/classify/train.py index 5c50b4fd..3a3f284c 100644 --- a/ultralytics/yolo/v8/classify/train.py +++ b/ultralytics/yolo/v8/classify/train.py @@ -30,7 +30,7 @@ class ClassificationTrainer(BaseTrainer): if weights: model.load(weights) - pretrained = False + pretrained = self.args.pretrained for m in model.modules(): if not pretrained and hasattr(m, 'reset_parameters'): m.reset_parameters()