ultralytics 8.1.28__py3-none-any.whl → 8.3.62__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/__init__.py +22 -0
- tests/conftest.py +83 -0
- tests/test_cli.py +122 -0
- tests/test_cuda.py +155 -0
- tests/test_engine.py +131 -0
- tests/test_exports.py +216 -0
- tests/test_integrations.py +150 -0
- tests/test_python.py +615 -0
- tests/test_solutions.py +94 -0
- ultralytics/__init__.py +11 -8
- ultralytics/cfg/__init__.py +569 -131
- ultralytics/cfg/datasets/Argoverse.yaml +2 -1
- ultralytics/cfg/datasets/DOTAv1.5.yaml +3 -2
- ultralytics/cfg/datasets/DOTAv1.yaml +3 -2
- ultralytics/cfg/datasets/GlobalWheat2020.yaml +3 -2
- ultralytics/cfg/datasets/ImageNet.yaml +2 -1
- ultralytics/cfg/datasets/Objects365.yaml +5 -4
- ultralytics/cfg/datasets/SKU-110K.yaml +2 -1
- ultralytics/cfg/datasets/VOC.yaml +3 -2
- ultralytics/cfg/datasets/VisDrone.yaml +6 -5
- ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
- ultralytics/cfg/datasets/brain-tumor.yaml +23 -0
- ultralytics/cfg/datasets/carparts-seg.yaml +3 -2
- ultralytics/cfg/datasets/coco-pose.yaml +7 -6
- ultralytics/cfg/datasets/coco.yaml +3 -2
- ultralytics/cfg/datasets/coco128-seg.yaml +4 -3
- ultralytics/cfg/datasets/coco128.yaml +4 -3
- ultralytics/cfg/datasets/coco8-pose.yaml +3 -2
- ultralytics/cfg/datasets/coco8-seg.yaml +3 -2
- ultralytics/cfg/datasets/coco8.yaml +3 -2
- ultralytics/cfg/datasets/crack-seg.yaml +3 -2
- ultralytics/cfg/datasets/dog-pose.yaml +24 -0
- ultralytics/cfg/datasets/dota8.yaml +3 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +26 -0
- ultralytics/cfg/datasets/lvis.yaml +1236 -0
- ultralytics/cfg/datasets/medical-pills.yaml +22 -0
- ultralytics/cfg/datasets/open-images-v7.yaml +2 -1
- ultralytics/cfg/datasets/package-seg.yaml +5 -4
- ultralytics/cfg/datasets/signature.yaml +21 -0
- ultralytics/cfg/datasets/tiger-pose.yaml +3 -2
- ultralytics/cfg/datasets/xView.yaml +2 -1
- ultralytics/cfg/default.yaml +14 -11
- ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +24 -0
- ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
- ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
- ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
- ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
- ultralytics/cfg/models/11/yolo11.yaml +50 -0
- ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +5 -2
- ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
- ultralytics/cfg/models/v3/yolov3-spp.yaml +5 -2
- ultralytics/cfg/models/v3/yolov3-tiny.yaml +5 -2
- ultralytics/cfg/models/v3/yolov3.yaml +5 -2
- ultralytics/cfg/models/v5/yolov5-p6.yaml +5 -2
- ultralytics/cfg/models/v5/yolov5.yaml +5 -2
- ultralytics/cfg/models/v6/yolov6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +6 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +6 -2
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-p2.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-p6.yaml +10 -7
- ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-pose.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-seg.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-world.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8.yaml +5 -2
- ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9c.yaml +30 -25
- ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
- ultralytics/cfg/models/v9/yolov9e.yaml +46 -42
- ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
- ultralytics/cfg/solutions/default.yaml +24 -0
- ultralytics/cfg/trackers/botsort.yaml +8 -5
- ultralytics/cfg/trackers/bytetrack.yaml +8 -5
- ultralytics/data/__init__.py +14 -3
- ultralytics/data/annotator.py +37 -15
- ultralytics/data/augment.py +1783 -289
- ultralytics/data/base.py +62 -27
- ultralytics/data/build.py +36 -8
- ultralytics/data/converter.py +196 -36
- ultralytics/data/dataset.py +233 -94
- ultralytics/data/loaders.py +199 -96
- ultralytics/data/split_dota.py +39 -29
- ultralytics/data/utils.py +110 -40
- ultralytics/engine/__init__.py +1 -1
- ultralytics/engine/exporter.py +569 -242
- ultralytics/engine/model.py +604 -252
- ultralytics/engine/predictor.py +22 -11
- ultralytics/engine/results.py +1228 -218
- ultralytics/engine/trainer.py +190 -129
- ultralytics/engine/tuner.py +18 -18
- ultralytics/engine/validator.py +18 -15
- ultralytics/hub/__init__.py +31 -13
- ultralytics/hub/auth.py +11 -7
- ultralytics/hub/google/__init__.py +159 -0
- ultralytics/hub/session.py +128 -94
- ultralytics/hub/utils.py +20 -21
- ultralytics/models/__init__.py +4 -2
- ultralytics/models/fastsam/__init__.py +2 -3
- ultralytics/models/fastsam/model.py +26 -4
- ultralytics/models/fastsam/predict.py +127 -63
- ultralytics/models/fastsam/utils.py +1 -44
- ultralytics/models/fastsam/val.py +1 -1
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +21 -10
- ultralytics/models/nas/predict.py +3 -6
- ultralytics/models/nas/val.py +4 -4
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +1 -1
- ultralytics/models/rtdetr/predict.py +6 -8
- ultralytics/models/rtdetr/train.py +6 -2
- ultralytics/models/rtdetr/val.py +3 -3
- ultralytics/models/sam/__init__.py +3 -3
- ultralytics/models/sam/amg.py +29 -23
- ultralytics/models/sam/build.py +211 -13
- ultralytics/models/sam/model.py +91 -30
- ultralytics/models/sam/modules/__init__.py +1 -1
- ultralytics/models/sam/modules/blocks.py +1129 -0
- ultralytics/models/sam/modules/decoders.py +381 -53
- ultralytics/models/sam/modules/encoders.py +515 -324
- ultralytics/models/sam/modules/memory_attention.py +237 -0
- ultralytics/models/sam/modules/sam.py +969 -21
- ultralytics/models/sam/modules/tiny_encoder.py +425 -154
- ultralytics/models/sam/modules/transformer.py +159 -60
- ultralytics/models/sam/modules/utils.py +293 -0
- ultralytics/models/sam/predict.py +1263 -132
- ultralytics/models/utils/__init__.py +1 -1
- ultralytics/models/utils/loss.py +36 -24
- ultralytics/models/utils/ops.py +3 -7
- ultralytics/models/yolo/__init__.py +3 -3
- ultralytics/models/yolo/classify/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +7 -8
- ultralytics/models/yolo/classify/train.py +17 -22
- ultralytics/models/yolo/classify/val.py +8 -4
- ultralytics/models/yolo/detect/__init__.py +1 -1
- ultralytics/models/yolo/detect/predict.py +3 -5
- ultralytics/models/yolo/detect/train.py +11 -4
- ultralytics/models/yolo/detect/val.py +90 -52
- ultralytics/models/yolo/model.py +14 -9
- ultralytics/models/yolo/obb/__init__.py +1 -1
- ultralytics/models/yolo/obb/predict.py +2 -2
- ultralytics/models/yolo/obb/train.py +5 -3
- ultralytics/models/yolo/obb/val.py +41 -23
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +3 -5
- ultralytics/models/yolo/pose/train.py +2 -2
- ultralytics/models/yolo/pose/val.py +51 -17
- ultralytics/models/yolo/segment/__init__.py +1 -1
- ultralytics/models/yolo/segment/predict.py +3 -5
- ultralytics/models/yolo/segment/train.py +2 -2
- ultralytics/models/yolo/segment/val.py +60 -19
- ultralytics/models/yolo/world/__init__.py +5 -0
- ultralytics/models/yolo/world/train.py +92 -0
- ultralytics/models/yolo/world/train_world.py +109 -0
- ultralytics/nn/__init__.py +1 -1
- ultralytics/nn/autobackend.py +228 -93
- ultralytics/nn/modules/__init__.py +39 -14
- ultralytics/nn/modules/activation.py +21 -0
- ultralytics/nn/modules/block.py +527 -67
- ultralytics/nn/modules/conv.py +24 -7
- ultralytics/nn/modules/head.py +177 -34
- ultralytics/nn/modules/transformer.py +6 -5
- ultralytics/nn/modules/utils.py +1 -2
- ultralytics/nn/tasks.py +225 -77
- ultralytics/solutions/__init__.py +30 -1
- ultralytics/solutions/ai_gym.py +96 -143
- ultralytics/solutions/analytics.py +247 -0
- ultralytics/solutions/distance_calculation.py +78 -135
- ultralytics/solutions/heatmap.py +93 -247
- ultralytics/solutions/object_counter.py +184 -259
- ultralytics/solutions/parking_management.py +246 -0
- ultralytics/solutions/queue_management.py +112 -0
- ultralytics/solutions/region_counter.py +116 -0
- ultralytics/solutions/security_alarm.py +144 -0
- ultralytics/solutions/solutions.py +178 -0
- ultralytics/solutions/speed_estimation.py +86 -174
- ultralytics/solutions/streamlit_inference.py +190 -0
- ultralytics/solutions/trackzone.py +68 -0
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +32 -13
- ultralytics/trackers/bot_sort.py +61 -28
- ultralytics/trackers/byte_tracker.py +83 -51
- ultralytics/trackers/track.py +21 -6
- ultralytics/trackers/utils/__init__.py +1 -1
- ultralytics/trackers/utils/gmc.py +62 -48
- ultralytics/trackers/utils/kalman_filter.py +166 -35
- ultralytics/trackers/utils/matching.py +40 -21
- ultralytics/utils/__init__.py +511 -239
- ultralytics/utils/autobatch.py +40 -22
- ultralytics/utils/benchmarks.py +266 -85
- ultralytics/utils/callbacks/__init__.py +1 -1
- ultralytics/utils/callbacks/base.py +1 -3
- ultralytics/utils/callbacks/clearml.py +7 -6
- ultralytics/utils/callbacks/comet.py +39 -17
- ultralytics/utils/callbacks/dvc.py +1 -1
- ultralytics/utils/callbacks/hub.py +16 -16
- ultralytics/utils/callbacks/mlflow.py +28 -24
- ultralytics/utils/callbacks/neptune.py +6 -2
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +18 -18
- ultralytics/utils/callbacks/wb.py +27 -20
- ultralytics/utils/checks.py +160 -100
- ultralytics/utils/dist.py +2 -1
- ultralytics/utils/downloads.py +44 -37
- ultralytics/utils/errors.py +1 -1
- ultralytics/utils/files.py +72 -38
- ultralytics/utils/instance.py +41 -19
- ultralytics/utils/loss.py +84 -56
- ultralytics/utils/metrics.py +61 -56
- ultralytics/utils/ops.py +94 -89
- ultralytics/utils/patches.py +30 -14
- ultralytics/utils/plotting.py +600 -269
- ultralytics/utils/tal.py +67 -26
- ultralytics/utils/torch_utils.py +302 -102
- ultralytics/utils/triton.py +2 -1
- ultralytics/utils/tuner.py +21 -12
- ultralytics-8.3.62.dist-info/METADATA +370 -0
- ultralytics-8.3.62.dist-info/RECORD +241 -0
- {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/WHEEL +1 -1
- ultralytics/data/explorer/__init__.py +0 -5
- ultralytics/data/explorer/explorer.py +0 -472
- ultralytics/data/explorer/gui/__init__.py +0 -1
- ultralytics/data/explorer/gui/dash.py +0 -268
- ultralytics/data/explorer/utils.py +0 -166
- ultralytics/models/fastsam/prompt.py +0 -357
- ultralytics-8.1.28.dist-info/METADATA +0 -373
- ultralytics-8.1.28.dist-info/RECORD +0 -197
- {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/LICENSE +0 -0
- {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
from ultralytics.utils import LOGGER, RANK, SETTINGS, TESTS_RUNNING, ops
|
4
|
+
from ultralytics.utils.metrics import ClassifyMetrics, DetMetrics, OBBMetrics, PoseMetrics, SegmentMetrics
|
4
5
|
|
5
6
|
try:
|
6
7
|
assert not TESTS_RUNNING # do not log pytest
|
@@ -15,9 +16,12 @@ try:
|
|
15
16
|
# Ensures certain logging functions only run for supported tasks
|
16
17
|
COMET_SUPPORTED_TASKS = ["detect"]
|
17
18
|
|
18
|
-
# Names of plots created by
|
19
|
-
|
19
|
+
# Names of plots created by Ultralytics that are logged to Comet
|
20
|
+
CONFUSION_MATRIX_PLOT_NAMES = "confusion_matrix", "confusion_matrix_normalized"
|
21
|
+
EVALUATION_PLOT_NAMES = "F1_curve", "P_curve", "R_curve", "PR_curve"
|
20
22
|
LABEL_PLOT_NAMES = "labels", "labels_correlogram"
|
23
|
+
SEGMENT_METRICS_PLOT_PREFIX = "Box", "Mask"
|
24
|
+
POSE_METRICS_PLOT_PREFIX = "Box", "Pose"
|
21
25
|
|
22
26
|
_comet_image_prediction_count = 0
|
23
27
|
|
@@ -31,8 +35,8 @@ def _get_comet_mode():
|
|
31
35
|
|
32
36
|
|
33
37
|
def _get_comet_model_name():
|
34
|
-
"""Returns the model name for Comet from the environment variable
|
35
|
-
return os.getenv("COMET_MODEL_NAME", "
|
38
|
+
"""Returns the model name for Comet from the environment variable COMET_MODEL_NAME or defaults to 'Ultralytics'."""
|
39
|
+
return os.getenv("COMET_MODEL_NAME", "Ultralytics")
|
36
40
|
|
37
41
|
|
38
42
|
def _get_eval_batch_logging_interval():
|
@@ -71,7 +75,7 @@ def _get_experiment_type(mode, project_name):
|
|
71
75
|
|
72
76
|
def _create_experiment(args):
|
73
77
|
"""Ensures that the experiment object is only created in a single process during distributed training."""
|
74
|
-
if RANK not in
|
78
|
+
if RANK not in {-1, 0}:
|
75
79
|
return
|
76
80
|
try:
|
77
81
|
comet_mode = _get_comet_mode()
|
@@ -86,7 +90,7 @@ def _create_experiment(args):
|
|
86
90
|
"max_image_predictions": _get_max_image_predictions_to_log(),
|
87
91
|
}
|
88
92
|
)
|
89
|
-
experiment.log_other("Created from", "
|
93
|
+
experiment.log_other("Created from", "ultralytics")
|
90
94
|
|
91
95
|
except Exception as e:
|
92
96
|
LOGGER.warning(f"WARNING ⚠️ Comet installed but not initialized correctly, not logging this run. {e}")
|
@@ -110,11 +114,10 @@ def _fetch_trainer_metadata(trainer):
|
|
110
114
|
|
111
115
|
def _scale_bounding_box_to_original_image_shape(box, resized_image_shape, original_image_shape, ratio_pad):
|
112
116
|
"""
|
113
|
-
|
117
|
+
YOLO resizes images during training and the label values are normalized based on this resized shape.
|
114
118
|
|
115
119
|
This function rescales the bounding box labels to the original image shape.
|
116
120
|
"""
|
117
|
-
|
118
121
|
resized_image_height, resized_image_width = resized_image_shape
|
119
122
|
|
120
123
|
# Convert normalized xywh format predictions to xyxy in resized scale format
|
@@ -275,11 +278,31 @@ def _log_image_predictions(experiment, validator, curr_step):
|
|
275
278
|
|
276
279
|
def _log_plots(experiment, trainer):
|
277
280
|
"""Logs evaluation plots and label plots for the experiment."""
|
278
|
-
plot_filenames =
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
281
|
+
plot_filenames = None
|
282
|
+
if isinstance(trainer.validator.metrics, SegmentMetrics) and trainer.validator.metrics.task == "segment":
|
283
|
+
plot_filenames = [
|
284
|
+
trainer.save_dir / f"{prefix}{plots}.png"
|
285
|
+
for plots in EVALUATION_PLOT_NAMES
|
286
|
+
for prefix in SEGMENT_METRICS_PLOT_PREFIX
|
287
|
+
]
|
288
|
+
elif isinstance(trainer.validator.metrics, PoseMetrics):
|
289
|
+
plot_filenames = [
|
290
|
+
trainer.save_dir / f"{prefix}{plots}.png"
|
291
|
+
for plots in EVALUATION_PLOT_NAMES
|
292
|
+
for prefix in POSE_METRICS_PLOT_PREFIX
|
293
|
+
]
|
294
|
+
elif isinstance(trainer.validator.metrics, (DetMetrics, OBBMetrics)):
|
295
|
+
plot_filenames = [trainer.save_dir / f"{plots}.png" for plots in EVALUATION_PLOT_NAMES]
|
296
|
+
|
297
|
+
if plot_filenames is not None:
|
298
|
+
_log_images(experiment, plot_filenames, None)
|
299
|
+
|
300
|
+
confusion_matrix_filenames = [trainer.save_dir / f"{plots}.png" for plots in CONFUSION_MATRIX_PLOT_NAMES]
|
301
|
+
_log_images(experiment, confusion_matrix_filenames, None)
|
302
|
+
|
303
|
+
if not isinstance(trainer.validator.metrics, ClassifyMetrics):
|
304
|
+
label_plot_filenames = [trainer.save_dir / f"{labels}.jpg" for labels in LABEL_PLOT_NAMES]
|
305
|
+
_log_images(experiment, label_plot_filenames, None)
|
283
306
|
|
284
307
|
|
285
308
|
def _log_model(experiment, trainer):
|
@@ -308,9 +331,6 @@ def on_train_epoch_end(trainer):
|
|
308
331
|
|
309
332
|
experiment.log_metrics(trainer.label_loss_items(trainer.tloss, prefix="train"), step=curr_step, epoch=curr_epoch)
|
310
333
|
|
311
|
-
if curr_epoch == 1:
|
312
|
-
_log_images(experiment, trainer.save_dir.glob("train_batch*.jpg"), curr_step)
|
313
|
-
|
314
334
|
|
315
335
|
def on_fit_epoch_end(trainer):
|
316
336
|
"""Logs model assets at the end of each epoch."""
|
@@ -357,6 +377,8 @@ def on_train_end(trainer):
|
|
357
377
|
|
358
378
|
_log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
|
359
379
|
_log_image_predictions(experiment, trainer.validator, curr_step)
|
380
|
+
_log_images(experiment, trainer.save_dir.glob("train_batch*.jpg"), curr_step)
|
381
|
+
_log_images(experiment, trainer.save_dir.glob("val_batch*.jpg"), curr_step)
|
360
382
|
experiment.end()
|
361
383
|
|
362
384
|
global _comet_image_prediction_count
|
@@ -1,27 +1,28 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
import json
|
4
4
|
from time import time
|
5
5
|
|
6
|
-
from ultralytics.hub
|
7
|
-
from ultralytics.utils import LOGGER, SETTINGS
|
6
|
+
from ultralytics.hub import HUB_WEB_ROOT, PREFIX, HUBTrainingSession, events
|
7
|
+
from ultralytics.utils import LOGGER, RANK, SETTINGS
|
8
|
+
|
9
|
+
|
10
|
+
def on_pretrain_routine_start(trainer):
|
11
|
+
"""Create a remote Ultralytics HUB session to log local model training."""
|
12
|
+
if RANK in {-1, 0} and SETTINGS["hub"] is True and SETTINGS["api_key"] and trainer.hub_session is None:
|
13
|
+
trainer.hub_session = HUBTrainingSession.create_session(trainer.args.model, trainer.args)
|
8
14
|
|
9
15
|
|
10
16
|
def on_pretrain_routine_end(trainer):
|
11
17
|
"""Logs info before starting timer for upload rate limit."""
|
12
|
-
session
|
13
|
-
if session:
|
18
|
+
if session := getattr(trainer, "hub_session", None):
|
14
19
|
# Start timer for upload rate limit
|
15
|
-
session.timers = {
|
16
|
-
"metrics": time(),
|
17
|
-
"ckpt": time(),
|
18
|
-
} # start timer on session.rate_limit
|
20
|
+
session.timers = {"metrics": time(), "ckpt": time()} # start timer on session.rate_limit
|
19
21
|
|
20
22
|
|
21
23
|
def on_fit_epoch_end(trainer):
|
22
24
|
"""Uploads training progress metrics at the end of each epoch."""
|
23
|
-
session
|
24
|
-
if session:
|
25
|
+
if session := getattr(trainer, "hub_session", None):
|
25
26
|
# Upload metrics after val end
|
26
27
|
all_plots = {
|
27
28
|
**trainer.label_loss_items(trainer.tloss, prefix="train"),
|
@@ -46,8 +47,7 @@ def on_fit_epoch_end(trainer):
|
|
46
47
|
|
47
48
|
def on_model_save(trainer):
|
48
49
|
"""Saves checkpoints to Ultralytics HUB with rate limiting."""
|
49
|
-
session
|
50
|
-
if session:
|
50
|
+
if session := getattr(trainer, "hub_session", None):
|
51
51
|
# Upload checkpoints with rate limiting
|
52
52
|
is_best = trainer.best_fitness == trainer.fitness
|
53
53
|
if time() - session.timers["ckpt"] > session.rate_limits["ckpt"]:
|
@@ -58,8 +58,7 @@ def on_model_save(trainer):
|
|
58
58
|
|
59
59
|
def on_train_end(trainer):
|
60
60
|
"""Upload final model and metrics to Ultralytics HUB at the end of training."""
|
61
|
-
session
|
62
|
-
if session:
|
61
|
+
if session := getattr(trainer, "hub_session", None):
|
63
62
|
# Upload final model and metrics with exponential standoff
|
64
63
|
LOGGER.info(f"{PREFIX}Syncing final model...")
|
65
64
|
session.upload_model(
|
@@ -69,7 +68,7 @@ def on_train_end(trainer):
|
|
69
68
|
final=True,
|
70
69
|
)
|
71
70
|
session.alive = False # stop heartbeats
|
72
|
-
LOGGER.info(f"{PREFIX}Done ✅\n
|
71
|
+
LOGGER.info(f"{PREFIX}Done ✅\n{PREFIX}View model at {session.model_url} 🚀")
|
73
72
|
|
74
73
|
|
75
74
|
def on_train_start(trainer):
|
@@ -94,6 +93,7 @@ def on_export_start(exporter):
|
|
94
93
|
|
95
94
|
callbacks = (
|
96
95
|
{
|
96
|
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
97
97
|
"on_pretrain_routine_end": on_pretrain_routine_end,
|
98
98
|
"on_fit_epoch_end": on_fit_epoch_end,
|
99
99
|
"on_model_save": on_model_save,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
"""
|
3
3
|
MLflow Logging for Ultralytics YOLO.
|
4
4
|
|
@@ -34,12 +34,16 @@ try:
|
|
34
34
|
from pathlib import Path
|
35
35
|
|
36
36
|
PREFIX = colorstr("MLflow: ")
|
37
|
-
SANITIZE = lambda x: {k.replace("(", "").replace(")", ""): float(v) for k, v in x.items()}
|
38
37
|
|
39
38
|
except (ImportError, AssertionError):
|
40
39
|
mlflow = None
|
41
40
|
|
42
41
|
|
42
|
+
def sanitize_dict(x):
|
43
|
+
"""Sanitize dictionary keys by removing parentheses and converting values to floats."""
|
44
|
+
return {k.replace("(", "").replace(")", ""): float(v) for k, v in x.items()}
|
45
|
+
|
46
|
+
|
43
47
|
def on_pretrain_routine_end(trainer):
|
44
48
|
"""
|
45
49
|
Log training parameters to MLflow at the end of the pretraining routine.
|
@@ -58,7 +62,7 @@ def on_pretrain_routine_end(trainer):
|
|
58
62
|
MLFLOW_TRACKING_URI: The URI for MLflow tracking. If not set, defaults to 'runs/mlflow'.
|
59
63
|
MLFLOW_EXPERIMENT_NAME: The name of the MLflow experiment. If not set, defaults to trainer.args.project.
|
60
64
|
MLFLOW_RUN: The name of the MLflow run. If not set, defaults to trainer.args.name.
|
61
|
-
MLFLOW_KEEP_RUN_ACTIVE: Boolean indicating whether to keep the MLflow run active after the end of
|
65
|
+
MLFLOW_KEEP_RUN_ACTIVE: Boolean indicating whether to keep the MLflow run active after the end of training.
|
62
66
|
"""
|
63
67
|
global mlflow
|
64
68
|
|
@@ -67,7 +71,7 @@ def on_pretrain_routine_end(trainer):
|
|
67
71
|
mlflow.set_tracking_uri(uri)
|
68
72
|
|
69
73
|
# Set experiment and run names
|
70
|
-
experiment_name = os.environ.get("MLFLOW_EXPERIMENT_NAME") or trainer.args.project or "/Shared/
|
74
|
+
experiment_name = os.environ.get("MLFLOW_EXPERIMENT_NAME") or trainer.args.project or "/Shared/Ultralytics"
|
71
75
|
run_name = os.environ.get("MLFLOW_RUN") or trainer.args.name
|
72
76
|
mlflow.set_experiment(experiment_name)
|
73
77
|
|
@@ -80,7 +84,7 @@ def on_pretrain_routine_end(trainer):
|
|
80
84
|
LOGGER.info(f"{PREFIX}disable with 'yolo settings mlflow=False'")
|
81
85
|
mlflow.log_params(dict(trainer.args))
|
82
86
|
except Exception as e:
|
83
|
-
LOGGER.warning(f"{PREFIX}WARNING ⚠️ Failed to initialize: {e}\n
|
87
|
+
LOGGER.warning(f"{PREFIX}WARNING ⚠️ Failed to initialize: {e}\n{PREFIX}WARNING ⚠️ Not tracking this run")
|
84
88
|
|
85
89
|
|
86
90
|
def on_train_epoch_end(trainer):
|
@@ -88,8 +92,8 @@ def on_train_epoch_end(trainer):
|
|
88
92
|
if mlflow:
|
89
93
|
mlflow.log_metrics(
|
90
94
|
metrics={
|
91
|
-
**
|
92
|
-
**
|
95
|
+
**sanitize_dict(trainer.lr),
|
96
|
+
**sanitize_dict(trainer.label_loss_items(trainer.tloss, prefix="train")),
|
93
97
|
},
|
94
98
|
step=trainer.epoch,
|
95
99
|
)
|
@@ -98,27 +102,27 @@ def on_train_epoch_end(trainer):
|
|
98
102
|
def on_fit_epoch_end(trainer):
|
99
103
|
"""Log training metrics at the end of each fit epoch to MLflow."""
|
100
104
|
if mlflow:
|
101
|
-
mlflow.log_metrics(metrics=
|
105
|
+
mlflow.log_metrics(metrics=sanitize_dict(trainer.metrics), step=trainer.epoch)
|
102
106
|
|
103
107
|
|
104
108
|
def on_train_end(trainer):
|
105
109
|
"""Log model artifacts at the end of the training."""
|
106
|
-
if mlflow:
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
110
|
+
if not mlflow:
|
111
|
+
return
|
112
|
+
mlflow.log_artifact(str(trainer.best.parent)) # log save_dir/weights directory with best.pt and last.pt
|
113
|
+
for f in trainer.save_dir.glob("*"): # log all other files in save_dir
|
114
|
+
if f.suffix in {".png", ".jpg", ".csv", ".pt", ".yaml"}:
|
115
|
+
mlflow.log_artifact(str(f))
|
116
|
+
keep_run_active = os.environ.get("MLFLOW_KEEP_RUN_ACTIVE", "False").lower() == "true"
|
117
|
+
if keep_run_active:
|
118
|
+
LOGGER.info(f"{PREFIX}mlflow run still alive, remember to close it using mlflow.end_run()")
|
119
|
+
else:
|
120
|
+
mlflow.end_run()
|
121
|
+
LOGGER.debug(f"{PREFIX}mlflow run ended")
|
122
|
+
|
123
|
+
LOGGER.info(
|
124
|
+
f"{PREFIX}results logged to {mlflow.get_tracking_uri()}\n{PREFIX}disable with 'yolo settings mlflow=False'"
|
125
|
+
)
|
122
126
|
|
123
127
|
|
124
128
|
callbacks = (
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
4
4
|
|
@@ -52,7 +52,11 @@ def on_pretrain_routine_start(trainer):
|
|
52
52
|
"""Callback function called before the training routine starts."""
|
53
53
|
try:
|
54
54
|
global run
|
55
|
-
run = neptune.init_run(
|
55
|
+
run = neptune.init_run(
|
56
|
+
project=trainer.args.project or "Ultralytics",
|
57
|
+
name=trainer.args.name,
|
58
|
+
tags=["Ultralytics"],
|
59
|
+
)
|
56
60
|
run["Configuration/Hyperparameters"] = {k: "" if v is None else v for k, v in vars(trainer.args).items()}
|
57
61
|
except Exception as e:
|
58
62
|
LOGGER.warning(f"WARNING ⚠️ NeptuneAI installed but not initialized correctly, not logging this run. {e}")
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
from ultralytics.utils import SETTINGS
|
4
4
|
|
@@ -14,10 +14,9 @@ except (ImportError, AssertionError):
|
|
14
14
|
|
15
15
|
def on_fit_epoch_end(trainer):
|
16
16
|
"""Sends training metrics to Ray Tune at end of each epoch."""
|
17
|
-
if ray.tune.is_session_enabled()
|
17
|
+
if ray.train._internal.session._get_session(): # replacement for deprecated ray.tune.is_session_enabled()
|
18
18
|
metrics = trainer.metrics
|
19
|
-
metrics
|
20
|
-
session.report(metrics)
|
19
|
+
session.report({**metrics, **{"epoch": trainer.epoch + 1}})
|
21
20
|
|
22
21
|
|
23
22
|
callbacks = (
|
@@ -1,5 +1,4 @@
|
|
1
|
-
# Ultralytics
|
2
|
-
import contextlib
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
3
2
|
|
4
3
|
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
|
5
4
|
|
@@ -15,6 +14,7 @@ try:
|
|
15
14
|
# Imports below only required if TensorBoard enabled
|
16
15
|
import warnings
|
17
16
|
from copy import deepcopy
|
17
|
+
|
18
18
|
from ultralytics.utils.torch_utils import de_parallel, torch
|
19
19
|
|
20
20
|
except (ImportError, AssertionError, TypeError, AttributeError):
|
@@ -32,7 +32,6 @@ def _log_scalars(scalars, step=0):
|
|
32
32
|
|
33
33
|
def _log_tensorboard_graph(trainer):
|
34
34
|
"""Log model graph to TensorBoard."""
|
35
|
-
|
36
35
|
# Input image
|
37
36
|
imgsz = trainer.args.imgsz
|
38
37
|
imgsz = (imgsz, imgsz) if isinstance(imgsz, int) else imgsz
|
@@ -44,26 +43,27 @@ def _log_tensorboard_graph(trainer):
|
|
44
43
|
warnings.simplefilter("ignore", category=torch.jit.TracerWarning) # suppress jit trace warning
|
45
44
|
|
46
45
|
# Try simple method first (YOLO)
|
47
|
-
|
46
|
+
try:
|
48
47
|
trainer.model.eval() # place in .eval() mode to avoid BatchNorm statistics changes
|
49
48
|
WRITER.add_graph(torch.jit.trace(de_parallel(trainer.model), im, strict=False), [])
|
50
49
|
LOGGER.info(f"{PREFIX}model graph visualization added ✅")
|
51
50
|
return
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
m
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
52
|
+
except Exception:
|
53
|
+
# Fallback to TorchScript export steps (RTDETR)
|
54
|
+
try:
|
55
|
+
model = deepcopy(de_parallel(trainer.model))
|
56
|
+
model.eval()
|
57
|
+
model = model.fuse(verbose=False)
|
58
|
+
for m in model.modules():
|
59
|
+
if hasattr(m, "export"): # Detect, RTDETRDecoder (Segment and Pose use Detect base class)
|
60
|
+
m.export = True
|
61
|
+
m.format = "torchscript"
|
62
|
+
model(im) # dry run
|
63
|
+
WRITER.add_graph(torch.jit.trace(model, im, strict=False), [])
|
64
|
+
LOGGER.info(f"{PREFIX}model graph visualization added ✅")
|
65
|
+
except Exception as e:
|
66
|
+
LOGGER.warning(f"{PREFIX}WARNING ⚠️ TensorBoard graph visualization failure {e}")
|
67
67
|
|
68
68
|
|
69
69
|
def on_pretrain_routine_start(trainer):
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
from ultralytics.utils import SETTINGS, TESTS_RUNNING
|
4
4
|
from ultralytics.utils.torch_utils import model_info_for_loggers
|
@@ -9,10 +9,6 @@ try:
|
|
9
9
|
import wandb as wb
|
10
10
|
|
11
11
|
assert hasattr(wb, "__version__") # verify package is not directory
|
12
|
-
|
13
|
-
import numpy as np
|
14
|
-
import pandas as pd
|
15
|
-
|
16
12
|
_processed_plots = {}
|
17
13
|
|
18
14
|
except (ImportError, AssertionError):
|
@@ -23,7 +19,7 @@ def _custom_table(x, y, classes, title="Precision Recall Curve", x_title="Recall
|
|
23
19
|
"""
|
24
20
|
Create and log a custom metric visualization to wandb.plot.pr_curve.
|
25
21
|
|
26
|
-
This function crafts a custom metric visualization that mimics the behavior of
|
22
|
+
This function crafts a custom metric visualization that mimics the behavior of the default wandb precision-recall
|
27
23
|
curve while allowing for enhanced customization. The visual metric is useful for monitoring model performance across
|
28
24
|
different classes.
|
29
25
|
|
@@ -38,7 +34,9 @@ def _custom_table(x, y, classes, title="Precision Recall Curve", x_title="Recall
|
|
38
34
|
Returns:
|
39
35
|
(wandb.Object): A wandb object suitable for logging, showcasing the crafted metric visualization.
|
40
36
|
"""
|
41
|
-
|
37
|
+
import pandas # scope for faster 'import ultralytics'
|
38
|
+
|
39
|
+
df = pandas.DataFrame({"class": classes, "y": y, "x": x}).round(3)
|
42
40
|
fields = {"x": "x", "y": "y", "class": "class"}
|
43
41
|
string_fields = {"title": title, "x-axis-title": x_title, "y-axis-title": y_title}
|
44
42
|
return wb.plot_table(
|
@@ -77,6 +75,8 @@ def _plot_curve(
|
|
77
75
|
Note:
|
78
76
|
The function leverages the '_custom_table' function to generate the actual visualization.
|
79
77
|
"""
|
78
|
+
import numpy as np
|
79
|
+
|
80
80
|
# Create new x
|
81
81
|
if names is None:
|
82
82
|
names = []
|
@@ -100,7 +100,7 @@ def _plot_curve(
|
|
100
100
|
|
101
101
|
def _log_plots(plots, step):
|
102
102
|
"""Logs plots from the input dictionary if they haven't been logged already at the specified step."""
|
103
|
-
for name, params in plots.items():
|
103
|
+
for name, params in plots.copy().items(): # shallow copy to prevent plots dict changing during iteration
|
104
104
|
timestamp = params["timestamp"]
|
105
105
|
if _processed_plots.get(name) != timestamp:
|
106
106
|
wb.run.log({name.stem: wb.Image(str(name))}, step=step)
|
@@ -109,7 +109,12 @@ def _log_plots(plots, step):
|
|
109
109
|
|
110
110
|
def on_pretrain_routine_start(trainer):
|
111
111
|
"""Initiate and start project if module is present."""
|
112
|
-
|
112
|
+
if not wb.run:
|
113
|
+
wb.init(
|
114
|
+
project=str(trainer.args.project).replace("/", "-") if trainer.args.project else "Ultralytics",
|
115
|
+
name=str(trainer.args.name).replace("/", "-"),
|
116
|
+
config=vars(trainer.args),
|
117
|
+
)
|
113
118
|
|
114
119
|
|
115
120
|
def on_fit_epoch_end(trainer):
|
@@ -137,17 +142,19 @@ def on_train_end(trainer):
|
|
137
142
|
if trainer.best.exists():
|
138
143
|
art.add_file(trainer.best)
|
139
144
|
wb.run.log_artifact(art, aliases=["best"])
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
x,
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
145
|
+
# Check if we actually have plots to save
|
146
|
+
if trainer.args.plots and hasattr(trainer.validator.metrics, "curves_results"):
|
147
|
+
for curve_name, curve_values in zip(trainer.validator.metrics.curves, trainer.validator.metrics.curves_results):
|
148
|
+
x, y, x_title, y_title = curve_values
|
149
|
+
_plot_curve(
|
150
|
+
x,
|
151
|
+
y,
|
152
|
+
names=list(trainer.validator.metrics.names.values()),
|
153
|
+
id=f"curves/{curve_name}",
|
154
|
+
title=curve_name,
|
155
|
+
x_title=x_title,
|
156
|
+
y_title=y_title,
|
157
|
+
)
|
151
158
|
wb.run.finish() # required or run continues on dashboard
|
152
159
|
|
153
160
|
|