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.
Files changed (247) hide show
  1. tests/__init__.py +22 -0
  2. tests/conftest.py +83 -0
  3. tests/test_cli.py +122 -0
  4. tests/test_cuda.py +155 -0
  5. tests/test_engine.py +131 -0
  6. tests/test_exports.py +216 -0
  7. tests/test_integrations.py +150 -0
  8. tests/test_python.py +615 -0
  9. tests/test_solutions.py +94 -0
  10. ultralytics/__init__.py +11 -8
  11. ultralytics/cfg/__init__.py +569 -131
  12. ultralytics/cfg/datasets/Argoverse.yaml +2 -1
  13. ultralytics/cfg/datasets/DOTAv1.5.yaml +3 -2
  14. ultralytics/cfg/datasets/DOTAv1.yaml +3 -2
  15. ultralytics/cfg/datasets/GlobalWheat2020.yaml +3 -2
  16. ultralytics/cfg/datasets/ImageNet.yaml +2 -1
  17. ultralytics/cfg/datasets/Objects365.yaml +5 -4
  18. ultralytics/cfg/datasets/SKU-110K.yaml +2 -1
  19. ultralytics/cfg/datasets/VOC.yaml +3 -2
  20. ultralytics/cfg/datasets/VisDrone.yaml +6 -5
  21. ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
  22. ultralytics/cfg/datasets/brain-tumor.yaml +23 -0
  23. ultralytics/cfg/datasets/carparts-seg.yaml +3 -2
  24. ultralytics/cfg/datasets/coco-pose.yaml +7 -6
  25. ultralytics/cfg/datasets/coco.yaml +3 -2
  26. ultralytics/cfg/datasets/coco128-seg.yaml +4 -3
  27. ultralytics/cfg/datasets/coco128.yaml +4 -3
  28. ultralytics/cfg/datasets/coco8-pose.yaml +3 -2
  29. ultralytics/cfg/datasets/coco8-seg.yaml +3 -2
  30. ultralytics/cfg/datasets/coco8.yaml +3 -2
  31. ultralytics/cfg/datasets/crack-seg.yaml +3 -2
  32. ultralytics/cfg/datasets/dog-pose.yaml +24 -0
  33. ultralytics/cfg/datasets/dota8.yaml +3 -2
  34. ultralytics/cfg/datasets/hand-keypoints.yaml +26 -0
  35. ultralytics/cfg/datasets/lvis.yaml +1236 -0
  36. ultralytics/cfg/datasets/medical-pills.yaml +22 -0
  37. ultralytics/cfg/datasets/open-images-v7.yaml +2 -1
  38. ultralytics/cfg/datasets/package-seg.yaml +5 -4
  39. ultralytics/cfg/datasets/signature.yaml +21 -0
  40. ultralytics/cfg/datasets/tiger-pose.yaml +3 -2
  41. ultralytics/cfg/datasets/xView.yaml +2 -1
  42. ultralytics/cfg/default.yaml +14 -11
  43. ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +24 -0
  44. ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
  45. ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
  46. ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
  47. ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
  48. ultralytics/cfg/models/11/yolo11.yaml +50 -0
  49. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +5 -2
  50. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +5 -2
  51. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +5 -2
  52. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +5 -2
  53. ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
  54. ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
  55. ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
  56. ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
  57. ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
  58. ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
  59. ultralytics/cfg/models/v3/yolov3-spp.yaml +5 -2
  60. ultralytics/cfg/models/v3/yolov3-tiny.yaml +5 -2
  61. ultralytics/cfg/models/v3/yolov3.yaml +5 -2
  62. ultralytics/cfg/models/v5/yolov5-p6.yaml +5 -2
  63. ultralytics/cfg/models/v5/yolov5.yaml +5 -2
  64. ultralytics/cfg/models/v6/yolov6.yaml +5 -2
  65. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +5 -2
  66. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +5 -2
  67. ultralytics/cfg/models/v8/yolov8-cls.yaml +5 -2
  68. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +6 -2
  69. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +6 -2
  70. ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -2
  71. ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -2
  72. ultralytics/cfg/models/v8/yolov8-p2.yaml +5 -2
  73. ultralytics/cfg/models/v8/yolov8-p6.yaml +10 -7
  74. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +5 -2
  75. ultralytics/cfg/models/v8/yolov8-pose.yaml +5 -2
  76. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -2
  77. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +5 -2
  78. ultralytics/cfg/models/v8/yolov8-seg.yaml +5 -2
  79. ultralytics/cfg/models/v8/yolov8-world.yaml +5 -2
  80. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -2
  81. ultralytics/cfg/models/v8/yolov8.yaml +5 -2
  82. ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
  83. ultralytics/cfg/models/v9/yolov9c.yaml +30 -25
  84. ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
  85. ultralytics/cfg/models/v9/yolov9e.yaml +46 -42
  86. ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
  87. ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
  88. ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
  89. ultralytics/cfg/solutions/default.yaml +24 -0
  90. ultralytics/cfg/trackers/botsort.yaml +8 -5
  91. ultralytics/cfg/trackers/bytetrack.yaml +8 -5
  92. ultralytics/data/__init__.py +14 -3
  93. ultralytics/data/annotator.py +37 -15
  94. ultralytics/data/augment.py +1783 -289
  95. ultralytics/data/base.py +62 -27
  96. ultralytics/data/build.py +36 -8
  97. ultralytics/data/converter.py +196 -36
  98. ultralytics/data/dataset.py +233 -94
  99. ultralytics/data/loaders.py +199 -96
  100. ultralytics/data/split_dota.py +39 -29
  101. ultralytics/data/utils.py +110 -40
  102. ultralytics/engine/__init__.py +1 -1
  103. ultralytics/engine/exporter.py +569 -242
  104. ultralytics/engine/model.py +604 -252
  105. ultralytics/engine/predictor.py +22 -11
  106. ultralytics/engine/results.py +1228 -218
  107. ultralytics/engine/trainer.py +190 -129
  108. ultralytics/engine/tuner.py +18 -18
  109. ultralytics/engine/validator.py +18 -15
  110. ultralytics/hub/__init__.py +31 -13
  111. ultralytics/hub/auth.py +11 -7
  112. ultralytics/hub/google/__init__.py +159 -0
  113. ultralytics/hub/session.py +128 -94
  114. ultralytics/hub/utils.py +20 -21
  115. ultralytics/models/__init__.py +4 -2
  116. ultralytics/models/fastsam/__init__.py +2 -3
  117. ultralytics/models/fastsam/model.py +26 -4
  118. ultralytics/models/fastsam/predict.py +127 -63
  119. ultralytics/models/fastsam/utils.py +1 -44
  120. ultralytics/models/fastsam/val.py +1 -1
  121. ultralytics/models/nas/__init__.py +1 -1
  122. ultralytics/models/nas/model.py +21 -10
  123. ultralytics/models/nas/predict.py +3 -6
  124. ultralytics/models/nas/val.py +4 -4
  125. ultralytics/models/rtdetr/__init__.py +1 -1
  126. ultralytics/models/rtdetr/model.py +1 -1
  127. ultralytics/models/rtdetr/predict.py +6 -8
  128. ultralytics/models/rtdetr/train.py +6 -2
  129. ultralytics/models/rtdetr/val.py +3 -3
  130. ultralytics/models/sam/__init__.py +3 -3
  131. ultralytics/models/sam/amg.py +29 -23
  132. ultralytics/models/sam/build.py +211 -13
  133. ultralytics/models/sam/model.py +91 -30
  134. ultralytics/models/sam/modules/__init__.py +1 -1
  135. ultralytics/models/sam/modules/blocks.py +1129 -0
  136. ultralytics/models/sam/modules/decoders.py +381 -53
  137. ultralytics/models/sam/modules/encoders.py +515 -324
  138. ultralytics/models/sam/modules/memory_attention.py +237 -0
  139. ultralytics/models/sam/modules/sam.py +969 -21
  140. ultralytics/models/sam/modules/tiny_encoder.py +425 -154
  141. ultralytics/models/sam/modules/transformer.py +159 -60
  142. ultralytics/models/sam/modules/utils.py +293 -0
  143. ultralytics/models/sam/predict.py +1263 -132
  144. ultralytics/models/utils/__init__.py +1 -1
  145. ultralytics/models/utils/loss.py +36 -24
  146. ultralytics/models/utils/ops.py +3 -7
  147. ultralytics/models/yolo/__init__.py +3 -3
  148. ultralytics/models/yolo/classify/__init__.py +1 -1
  149. ultralytics/models/yolo/classify/predict.py +7 -8
  150. ultralytics/models/yolo/classify/train.py +17 -22
  151. ultralytics/models/yolo/classify/val.py +8 -4
  152. ultralytics/models/yolo/detect/__init__.py +1 -1
  153. ultralytics/models/yolo/detect/predict.py +3 -5
  154. ultralytics/models/yolo/detect/train.py +11 -4
  155. ultralytics/models/yolo/detect/val.py +90 -52
  156. ultralytics/models/yolo/model.py +14 -9
  157. ultralytics/models/yolo/obb/__init__.py +1 -1
  158. ultralytics/models/yolo/obb/predict.py +2 -2
  159. ultralytics/models/yolo/obb/train.py +5 -3
  160. ultralytics/models/yolo/obb/val.py +41 -23
  161. ultralytics/models/yolo/pose/__init__.py +1 -1
  162. ultralytics/models/yolo/pose/predict.py +3 -5
  163. ultralytics/models/yolo/pose/train.py +2 -2
  164. ultralytics/models/yolo/pose/val.py +51 -17
  165. ultralytics/models/yolo/segment/__init__.py +1 -1
  166. ultralytics/models/yolo/segment/predict.py +3 -5
  167. ultralytics/models/yolo/segment/train.py +2 -2
  168. ultralytics/models/yolo/segment/val.py +60 -19
  169. ultralytics/models/yolo/world/__init__.py +5 -0
  170. ultralytics/models/yolo/world/train.py +92 -0
  171. ultralytics/models/yolo/world/train_world.py +109 -0
  172. ultralytics/nn/__init__.py +1 -1
  173. ultralytics/nn/autobackend.py +228 -93
  174. ultralytics/nn/modules/__init__.py +39 -14
  175. ultralytics/nn/modules/activation.py +21 -0
  176. ultralytics/nn/modules/block.py +527 -67
  177. ultralytics/nn/modules/conv.py +24 -7
  178. ultralytics/nn/modules/head.py +177 -34
  179. ultralytics/nn/modules/transformer.py +6 -5
  180. ultralytics/nn/modules/utils.py +1 -2
  181. ultralytics/nn/tasks.py +225 -77
  182. ultralytics/solutions/__init__.py +30 -1
  183. ultralytics/solutions/ai_gym.py +96 -143
  184. ultralytics/solutions/analytics.py +247 -0
  185. ultralytics/solutions/distance_calculation.py +78 -135
  186. ultralytics/solutions/heatmap.py +93 -247
  187. ultralytics/solutions/object_counter.py +184 -259
  188. ultralytics/solutions/parking_management.py +246 -0
  189. ultralytics/solutions/queue_management.py +112 -0
  190. ultralytics/solutions/region_counter.py +116 -0
  191. ultralytics/solutions/security_alarm.py +144 -0
  192. ultralytics/solutions/solutions.py +178 -0
  193. ultralytics/solutions/speed_estimation.py +86 -174
  194. ultralytics/solutions/streamlit_inference.py +190 -0
  195. ultralytics/solutions/trackzone.py +68 -0
  196. ultralytics/trackers/__init__.py +1 -1
  197. ultralytics/trackers/basetrack.py +32 -13
  198. ultralytics/trackers/bot_sort.py +61 -28
  199. ultralytics/trackers/byte_tracker.py +83 -51
  200. ultralytics/trackers/track.py +21 -6
  201. ultralytics/trackers/utils/__init__.py +1 -1
  202. ultralytics/trackers/utils/gmc.py +62 -48
  203. ultralytics/trackers/utils/kalman_filter.py +166 -35
  204. ultralytics/trackers/utils/matching.py +40 -21
  205. ultralytics/utils/__init__.py +511 -239
  206. ultralytics/utils/autobatch.py +40 -22
  207. ultralytics/utils/benchmarks.py +266 -85
  208. ultralytics/utils/callbacks/__init__.py +1 -1
  209. ultralytics/utils/callbacks/base.py +1 -3
  210. ultralytics/utils/callbacks/clearml.py +7 -6
  211. ultralytics/utils/callbacks/comet.py +39 -17
  212. ultralytics/utils/callbacks/dvc.py +1 -1
  213. ultralytics/utils/callbacks/hub.py +16 -16
  214. ultralytics/utils/callbacks/mlflow.py +28 -24
  215. ultralytics/utils/callbacks/neptune.py +6 -2
  216. ultralytics/utils/callbacks/raytune.py +3 -4
  217. ultralytics/utils/callbacks/tensorboard.py +18 -18
  218. ultralytics/utils/callbacks/wb.py +27 -20
  219. ultralytics/utils/checks.py +160 -100
  220. ultralytics/utils/dist.py +2 -1
  221. ultralytics/utils/downloads.py +44 -37
  222. ultralytics/utils/errors.py +1 -1
  223. ultralytics/utils/files.py +72 -38
  224. ultralytics/utils/instance.py +41 -19
  225. ultralytics/utils/loss.py +84 -56
  226. ultralytics/utils/metrics.py +61 -56
  227. ultralytics/utils/ops.py +94 -89
  228. ultralytics/utils/patches.py +30 -14
  229. ultralytics/utils/plotting.py +600 -269
  230. ultralytics/utils/tal.py +67 -26
  231. ultralytics/utils/torch_utils.py +302 -102
  232. ultralytics/utils/triton.py +2 -1
  233. ultralytics/utils/tuner.py +21 -12
  234. ultralytics-8.3.62.dist-info/METADATA +370 -0
  235. ultralytics-8.3.62.dist-info/RECORD +241 -0
  236. {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/WHEEL +1 -1
  237. ultralytics/data/explorer/__init__.py +0 -5
  238. ultralytics/data/explorer/explorer.py +0 -472
  239. ultralytics/data/explorer/gui/__init__.py +0 -1
  240. ultralytics/data/explorer/gui/dash.py +0 -268
  241. ultralytics/data/explorer/utils.py +0 -166
  242. ultralytics/models/fastsam/prompt.py +0 -357
  243. ultralytics-8.1.28.dist-info/METADATA +0 -373
  244. ultralytics-8.1.28.dist-info/RECORD +0 -197
  245. {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/LICENSE +0 -0
  246. {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/entry_points.txt +0 -0
  247. {ultralytics-8.1.28.dist-info → ultralytics-8.3.62.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
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 YOLOv8 that are logged to Comet
19
- EVALUATION_PLOT_NAMES = "F1_curve", "P_curve", "R_curve", "PR_curve", "confusion_matrix"
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 'COMET_MODEL_NAME' or defaults to 'YOLOv8'."""
35
- return os.getenv("COMET_MODEL_NAME", "YOLOv8")
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 (-1, 0):
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", "yolov8")
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
- YOLOv8 resizes images during training and the label values are normalized based on this resized shape.
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 = [trainer.save_dir / f"{plots}.png" for plots in EVALUATION_PLOT_NAMES]
279
- _log_images(experiment, plot_filenames, None)
280
-
281
- label_plot_filenames = [trainer.save_dir / f"{labels}.jpg" for labels in LABEL_PLOT_NAMES]
282
- _log_images(experiment, label_plot_filenames, None)
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,4 +1,4 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
3
  from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, checks
4
4
 
@@ -1,27 +1,28 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
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.utils import HUB_WEB_ROOT, PREFIX, events
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 = getattr(trainer, "hub_session", None)
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 = getattr(trainer, "hub_session", None)
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 = getattr(trainer, "hub_session", None)
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 = getattr(trainer, "hub_session", None)
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" f"{PREFIX}View model at {session.model_url} 🚀")
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 YOLO 🚀, AGPL-3.0 license
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 the training phase.
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/YOLOv8"
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" f"{PREFIX}WARNING ⚠️ Not tracking this run")
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
- **SANITIZE(trainer.lr),
92
- **SANITIZE(trainer.label_loss_items(trainer.tloss, prefix="train")),
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=SANITIZE(trainer.metrics), step=trainer.epoch)
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
- mlflow.log_artifact(str(trainer.best.parent)) # log save_dir/weights directory with best.pt and last.pt
108
- for f in trainer.save_dir.glob("*"): # log all other files in save_dir
109
- if f.suffix in {".png", ".jpg", ".csv", ".pt", ".yaml"}:
110
- mlflow.log_artifact(str(f))
111
- keep_run_active = os.environ.get("MLFLOW_KEEP_RUN_ACTIVE", "False").lower() in ("true")
112
- if keep_run_active:
113
- LOGGER.info(f"{PREFIX}mlflow run still alive, remember to close it using mlflow.end_run()")
114
- else:
115
- mlflow.end_run()
116
- LOGGER.debug(f"{PREFIX}mlflow run ended")
117
-
118
- LOGGER.info(
119
- f"{PREFIX}results logged to {mlflow.get_tracking_uri()}\n"
120
- f"{PREFIX}disable with 'yolo settings mlflow=False'"
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 YOLO 🚀, AGPL-3.0 license
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(project=trainer.args.project or "YOLOv8", name=trainer.args.name, tags=["YOLOv8"])
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 YOLO 🚀, AGPL-3.0 license
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["epoch"] = trainer.epoch
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 YOLO 🚀, AGPL-3.0 license
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
- with contextlib.suppress(Exception):
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
- # 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}")
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 YOLO 🚀, AGPL-3.0 license
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 wandb's default precision-recall
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
- df = pd.DataFrame({"class": classes, "y": y, "x": x}).round(3)
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
- wb.run or wb.init(project=trainer.args.project or "YOLOv8", name=trainer.args.name, config=vars(trainer.args))
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
- for curve_name, curve_values in zip(trainer.validator.metrics.curves, trainer.validator.metrics.curves_results):
141
- x, y, x_title, y_title = curve_values
142
- _plot_curve(
143
- x,
144
- y,
145
- names=list(trainer.validator.metrics.names.values()),
146
- id=f"curves/{curve_name}",
147
- title=curve_name,
148
- x_title=x_title,
149
- y_title=y_title,
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