dgenerate-ultralytics-headless 8.3.214__py3-none-any.whl → 8.3.248__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 (236) hide show
  1. {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/METADATA +13 -14
  2. dgenerate_ultralytics_headless-8.3.248.dist-info/RECORD +298 -0
  3. tests/__init__.py +5 -7
  4. tests/conftest.py +8 -15
  5. tests/test_cli.py +1 -1
  6. tests/test_cuda.py +5 -8
  7. tests/test_engine.py +1 -1
  8. tests/test_exports.py +57 -12
  9. tests/test_integrations.py +4 -4
  10. tests/test_python.py +84 -53
  11. tests/test_solutions.py +160 -151
  12. ultralytics/__init__.py +1 -1
  13. ultralytics/cfg/__init__.py +56 -62
  14. ultralytics/cfg/datasets/Argoverse.yaml +7 -6
  15. ultralytics/cfg/datasets/DOTAv1.5.yaml +1 -1
  16. ultralytics/cfg/datasets/DOTAv1.yaml +1 -1
  17. ultralytics/cfg/datasets/ImageNet.yaml +1 -1
  18. ultralytics/cfg/datasets/VOC.yaml +15 -16
  19. ultralytics/cfg/datasets/african-wildlife.yaml +1 -1
  20. ultralytics/cfg/datasets/coco-pose.yaml +21 -0
  21. ultralytics/cfg/datasets/coco128-seg.yaml +1 -1
  22. ultralytics/cfg/datasets/coco8-pose.yaml +21 -0
  23. ultralytics/cfg/datasets/dog-pose.yaml +28 -0
  24. ultralytics/cfg/datasets/dota8-multispectral.yaml +1 -1
  25. ultralytics/cfg/datasets/dota8.yaml +2 -2
  26. ultralytics/cfg/datasets/hand-keypoints.yaml +26 -2
  27. ultralytics/cfg/datasets/kitti.yaml +27 -0
  28. ultralytics/cfg/datasets/lvis.yaml +5 -5
  29. ultralytics/cfg/datasets/open-images-v7.yaml +1 -1
  30. ultralytics/cfg/datasets/tiger-pose.yaml +16 -0
  31. ultralytics/cfg/datasets/xView.yaml +16 -16
  32. ultralytics/cfg/default.yaml +1 -1
  33. ultralytics/cfg/models/11/yolo11-pose.yaml +1 -1
  34. ultralytics/cfg/models/11/yoloe-11-seg.yaml +2 -2
  35. ultralytics/cfg/models/11/yoloe-11.yaml +2 -2
  36. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +1 -1
  37. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +1 -1
  38. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +1 -1
  39. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +1 -1
  40. ultralytics/cfg/models/v10/yolov10b.yaml +2 -2
  41. ultralytics/cfg/models/v10/yolov10l.yaml +2 -2
  42. ultralytics/cfg/models/v10/yolov10m.yaml +2 -2
  43. ultralytics/cfg/models/v10/yolov10n.yaml +2 -2
  44. ultralytics/cfg/models/v10/yolov10s.yaml +2 -2
  45. ultralytics/cfg/models/v10/yolov10x.yaml +2 -2
  46. ultralytics/cfg/models/v3/yolov3-tiny.yaml +1 -1
  47. ultralytics/cfg/models/v6/yolov6.yaml +1 -1
  48. ultralytics/cfg/models/v8/yoloe-v8-seg.yaml +9 -6
  49. ultralytics/cfg/models/v8/yoloe-v8.yaml +9 -6
  50. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +1 -1
  51. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +1 -1
  52. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +2 -2
  53. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +2 -2
  54. ultralytics/cfg/models/v8/yolov8-ghost.yaml +2 -2
  55. ultralytics/cfg/models/v8/yolov8-obb.yaml +1 -1
  56. ultralytics/cfg/models/v8/yolov8-p2.yaml +1 -1
  57. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +1 -1
  58. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +1 -1
  59. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +1 -1
  60. ultralytics/cfg/models/v8/yolov8-world.yaml +1 -1
  61. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +6 -6
  62. ultralytics/cfg/models/v9/yolov9s.yaml +1 -1
  63. ultralytics/data/__init__.py +4 -4
  64. ultralytics/data/annotator.py +3 -4
  65. ultralytics/data/augment.py +285 -475
  66. ultralytics/data/base.py +18 -26
  67. ultralytics/data/build.py +147 -25
  68. ultralytics/data/converter.py +36 -46
  69. ultralytics/data/dataset.py +46 -74
  70. ultralytics/data/loaders.py +42 -49
  71. ultralytics/data/split.py +5 -6
  72. ultralytics/data/split_dota.py +8 -15
  73. ultralytics/data/utils.py +34 -43
  74. ultralytics/engine/exporter.py +319 -237
  75. ultralytics/engine/model.py +148 -188
  76. ultralytics/engine/predictor.py +29 -38
  77. ultralytics/engine/results.py +177 -311
  78. ultralytics/engine/trainer.py +83 -59
  79. ultralytics/engine/tuner.py +23 -34
  80. ultralytics/engine/validator.py +39 -22
  81. ultralytics/hub/__init__.py +16 -19
  82. ultralytics/hub/auth.py +6 -12
  83. ultralytics/hub/google/__init__.py +7 -10
  84. ultralytics/hub/session.py +15 -25
  85. ultralytics/hub/utils.py +5 -8
  86. ultralytics/models/__init__.py +1 -1
  87. ultralytics/models/fastsam/__init__.py +1 -1
  88. ultralytics/models/fastsam/model.py +8 -10
  89. ultralytics/models/fastsam/predict.py +17 -29
  90. ultralytics/models/fastsam/utils.py +1 -2
  91. ultralytics/models/fastsam/val.py +5 -7
  92. ultralytics/models/nas/__init__.py +1 -1
  93. ultralytics/models/nas/model.py +5 -8
  94. ultralytics/models/nas/predict.py +7 -9
  95. ultralytics/models/nas/val.py +1 -2
  96. ultralytics/models/rtdetr/__init__.py +1 -1
  97. ultralytics/models/rtdetr/model.py +5 -8
  98. ultralytics/models/rtdetr/predict.py +15 -19
  99. ultralytics/models/rtdetr/train.py +10 -13
  100. ultralytics/models/rtdetr/val.py +21 -23
  101. ultralytics/models/sam/__init__.py +15 -2
  102. ultralytics/models/sam/amg.py +14 -20
  103. ultralytics/models/sam/build.py +26 -19
  104. ultralytics/models/sam/build_sam3.py +377 -0
  105. ultralytics/models/sam/model.py +29 -32
  106. ultralytics/models/sam/modules/blocks.py +83 -144
  107. ultralytics/models/sam/modules/decoders.py +19 -37
  108. ultralytics/models/sam/modules/encoders.py +44 -101
  109. ultralytics/models/sam/modules/memory_attention.py +16 -30
  110. ultralytics/models/sam/modules/sam.py +200 -73
  111. ultralytics/models/sam/modules/tiny_encoder.py +64 -83
  112. ultralytics/models/sam/modules/transformer.py +18 -28
  113. ultralytics/models/sam/modules/utils.py +174 -50
  114. ultralytics/models/sam/predict.py +2248 -350
  115. ultralytics/models/sam/sam3/__init__.py +3 -0
  116. ultralytics/models/sam/sam3/decoder.py +546 -0
  117. ultralytics/models/sam/sam3/encoder.py +529 -0
  118. ultralytics/models/sam/sam3/geometry_encoders.py +415 -0
  119. ultralytics/models/sam/sam3/maskformer_segmentation.py +286 -0
  120. ultralytics/models/sam/sam3/model_misc.py +199 -0
  121. ultralytics/models/sam/sam3/necks.py +129 -0
  122. ultralytics/models/sam/sam3/sam3_image.py +339 -0
  123. ultralytics/models/sam/sam3/text_encoder_ve.py +307 -0
  124. ultralytics/models/sam/sam3/vitdet.py +547 -0
  125. ultralytics/models/sam/sam3/vl_combiner.py +160 -0
  126. ultralytics/models/utils/loss.py +14 -26
  127. ultralytics/models/utils/ops.py +13 -17
  128. ultralytics/models/yolo/__init__.py +1 -1
  129. ultralytics/models/yolo/classify/predict.py +9 -12
  130. ultralytics/models/yolo/classify/train.py +11 -32
  131. ultralytics/models/yolo/classify/val.py +29 -28
  132. ultralytics/models/yolo/detect/predict.py +7 -10
  133. ultralytics/models/yolo/detect/train.py +11 -20
  134. ultralytics/models/yolo/detect/val.py +70 -58
  135. ultralytics/models/yolo/model.py +36 -53
  136. ultralytics/models/yolo/obb/predict.py +5 -14
  137. ultralytics/models/yolo/obb/train.py +11 -14
  138. ultralytics/models/yolo/obb/val.py +39 -36
  139. ultralytics/models/yolo/pose/__init__.py +1 -1
  140. ultralytics/models/yolo/pose/predict.py +6 -21
  141. ultralytics/models/yolo/pose/train.py +10 -15
  142. ultralytics/models/yolo/pose/val.py +38 -57
  143. ultralytics/models/yolo/segment/predict.py +14 -18
  144. ultralytics/models/yolo/segment/train.py +3 -6
  145. ultralytics/models/yolo/segment/val.py +93 -45
  146. ultralytics/models/yolo/world/train.py +8 -14
  147. ultralytics/models/yolo/world/train_world.py +11 -34
  148. ultralytics/models/yolo/yoloe/__init__.py +7 -7
  149. ultralytics/models/yolo/yoloe/predict.py +16 -23
  150. ultralytics/models/yolo/yoloe/train.py +30 -43
  151. ultralytics/models/yolo/yoloe/train_seg.py +5 -10
  152. ultralytics/models/yolo/yoloe/val.py +15 -20
  153. ultralytics/nn/__init__.py +7 -7
  154. ultralytics/nn/autobackend.py +145 -77
  155. ultralytics/nn/modules/__init__.py +60 -60
  156. ultralytics/nn/modules/activation.py +4 -6
  157. ultralytics/nn/modules/block.py +132 -216
  158. ultralytics/nn/modules/conv.py +52 -97
  159. ultralytics/nn/modules/head.py +50 -103
  160. ultralytics/nn/modules/transformer.py +76 -88
  161. ultralytics/nn/modules/utils.py +16 -21
  162. ultralytics/nn/tasks.py +94 -154
  163. ultralytics/nn/text_model.py +40 -67
  164. ultralytics/solutions/__init__.py +12 -12
  165. ultralytics/solutions/ai_gym.py +11 -17
  166. ultralytics/solutions/analytics.py +15 -16
  167. ultralytics/solutions/config.py +5 -6
  168. ultralytics/solutions/distance_calculation.py +10 -13
  169. ultralytics/solutions/heatmap.py +7 -13
  170. ultralytics/solutions/instance_segmentation.py +5 -8
  171. ultralytics/solutions/object_blurrer.py +7 -10
  172. ultralytics/solutions/object_counter.py +12 -19
  173. ultralytics/solutions/object_cropper.py +8 -14
  174. ultralytics/solutions/parking_management.py +33 -31
  175. ultralytics/solutions/queue_management.py +10 -12
  176. ultralytics/solutions/region_counter.py +9 -12
  177. ultralytics/solutions/security_alarm.py +15 -20
  178. ultralytics/solutions/similarity_search.py +10 -15
  179. ultralytics/solutions/solutions.py +75 -74
  180. ultralytics/solutions/speed_estimation.py +7 -10
  181. ultralytics/solutions/streamlit_inference.py +2 -4
  182. ultralytics/solutions/templates/similarity-search.html +7 -18
  183. ultralytics/solutions/trackzone.py +7 -10
  184. ultralytics/solutions/vision_eye.py +5 -8
  185. ultralytics/trackers/__init__.py +1 -1
  186. ultralytics/trackers/basetrack.py +3 -5
  187. ultralytics/trackers/bot_sort.py +10 -27
  188. ultralytics/trackers/byte_tracker.py +14 -30
  189. ultralytics/trackers/track.py +3 -6
  190. ultralytics/trackers/utils/gmc.py +11 -22
  191. ultralytics/trackers/utils/kalman_filter.py +37 -48
  192. ultralytics/trackers/utils/matching.py +12 -15
  193. ultralytics/utils/__init__.py +116 -116
  194. ultralytics/utils/autobatch.py +2 -4
  195. ultralytics/utils/autodevice.py +17 -18
  196. ultralytics/utils/benchmarks.py +32 -46
  197. ultralytics/utils/callbacks/base.py +8 -10
  198. ultralytics/utils/callbacks/clearml.py +5 -13
  199. ultralytics/utils/callbacks/comet.py +32 -46
  200. ultralytics/utils/callbacks/dvc.py +13 -18
  201. ultralytics/utils/callbacks/mlflow.py +4 -5
  202. ultralytics/utils/callbacks/neptune.py +7 -15
  203. ultralytics/utils/callbacks/platform.py +314 -38
  204. ultralytics/utils/callbacks/raytune.py +3 -4
  205. ultralytics/utils/callbacks/tensorboard.py +23 -31
  206. ultralytics/utils/callbacks/wb.py +10 -13
  207. ultralytics/utils/checks.py +99 -76
  208. ultralytics/utils/cpu.py +3 -8
  209. ultralytics/utils/dist.py +8 -12
  210. ultralytics/utils/downloads.py +20 -30
  211. ultralytics/utils/errors.py +6 -14
  212. ultralytics/utils/events.py +2 -4
  213. ultralytics/utils/export/__init__.py +4 -236
  214. ultralytics/utils/export/engine.py +237 -0
  215. ultralytics/utils/export/imx.py +91 -55
  216. ultralytics/utils/export/tensorflow.py +231 -0
  217. ultralytics/utils/files.py +24 -28
  218. ultralytics/utils/git.py +9 -11
  219. ultralytics/utils/instance.py +30 -51
  220. ultralytics/utils/logger.py +212 -114
  221. ultralytics/utils/loss.py +14 -22
  222. ultralytics/utils/metrics.py +126 -155
  223. ultralytics/utils/nms.py +13 -16
  224. ultralytics/utils/ops.py +107 -165
  225. ultralytics/utils/patches.py +33 -21
  226. ultralytics/utils/plotting.py +72 -80
  227. ultralytics/utils/tal.py +25 -39
  228. ultralytics/utils/torch_utils.py +52 -78
  229. ultralytics/utils/tqdm.py +20 -20
  230. ultralytics/utils/triton.py +13 -19
  231. ultralytics/utils/tuner.py +17 -5
  232. dgenerate_ultralytics_headless-8.3.214.dist-info/RECORD +0 -283
  233. {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/WHEEL +0 -0
  234. {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/entry_points.txt +0 -0
  235. {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/licenses/LICENSE +0 -0
  236. {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/top_level.txt +0 -0
@@ -44,6 +44,8 @@ TORCH_1_13 = check_version(TORCH_VERSION, "1.13.0")
44
44
  TORCH_2_0 = check_version(TORCH_VERSION, "2.0.0")
45
45
  TORCH_2_1 = check_version(TORCH_VERSION, "2.1.0")
46
46
  TORCH_2_4 = check_version(TORCH_VERSION, "2.4.0")
47
+ TORCH_2_8 = check_version(TORCH_VERSION, "2.8.0")
48
+ TORCH_2_9 = check_version(TORCH_VERSION, "2.9.0")
47
49
  TORCHVISION_0_10 = check_version(TORCHVISION_VERSION, "0.10.0")
48
50
  TORCHVISION_0_11 = check_version(TORCHVISION_VERSION, "0.11.0")
49
51
  TORCHVISION_0_13 = check_version(TORCHVISION_VERSION, "0.13.0")
@@ -82,8 +84,7 @@ def smart_inference_mode():
82
84
 
83
85
 
84
86
  def autocast(enabled: bool, device: str = "cuda"):
85
- """
86
- Get the appropriate autocast context manager based on PyTorch version and AMP setting.
87
+ """Get the appropriate autocast context manager based on PyTorch version and AMP setting.
87
88
 
88
89
  This function returns a context manager for automatic mixed precision (AMP) training that is compatible with both
89
90
  older and newer versions of PyTorch. It handles the differences in the autocast API between PyTorch versions.
@@ -95,14 +96,14 @@ def autocast(enabled: bool, device: str = "cuda"):
95
96
  Returns:
96
97
  (torch.amp.autocast): The appropriate autocast context manager.
97
98
 
98
- Notes:
99
- - For PyTorch versions 1.13 and newer, it uses `torch.amp.autocast`.
100
- - For older versions, it uses `torch.cuda.autocast`.
101
-
102
99
  Examples:
103
100
  >>> with autocast(enabled=True):
104
101
  ... # Your mixed precision operations here
105
102
  ... pass
103
+
104
+ Notes:
105
+ - For PyTorch versions 1.13 and newer, it uses `torch.amp.autocast`.
106
+ - For older versions, it uses `torch.cuda.autocast`.
106
107
  """
107
108
  if TORCH_1_13:
108
109
  return torch.amp.autocast(device, enabled=enabled)
@@ -131,8 +132,7 @@ def get_gpu_info(index):
131
132
 
132
133
 
133
134
  def select_device(device="", newline=False, verbose=True):
134
- """
135
- Select the appropriate PyTorch device based on the provided arguments.
135
+ """Select the appropriate PyTorch device based on the provided arguments.
136
136
 
137
137
  The function takes a string specifying the device or a torch.device object and returns a torch.device object
138
138
  representing the selected device. The function also validates the number of available devices and raises an
@@ -180,7 +180,7 @@ def select_device(device="", newline=False, verbose=True):
180
180
  cpu = device == "cpu"
181
181
  mps = device in {"mps", "mps:0"} # Apple Metal Performance Shaders (MPS)
182
182
  if cpu or mps:
183
- os.environ["CUDA_VISIBLE_DEVICES"] = "-1" # force torch.cuda.is_available() = False
183
+ os.environ["CUDA_VISIBLE_DEVICES"] = "" # force torch.cuda.is_available() = False
184
184
  elif device: # non-cpu device requested
185
185
  if device == "cuda":
186
186
  device = "0"
@@ -235,8 +235,7 @@ def time_sync():
235
235
 
236
236
 
237
237
  def fuse_conv_and_bn(conv, bn):
238
- """
239
- Fuse Conv2d and BatchNorm2d layers for inference optimization.
238
+ """Fuse Conv2d and BatchNorm2d layers for inference optimization.
240
239
 
241
240
  Args:
242
241
  conv (nn.Conv2d): Convolutional layer to fuse.
@@ -245,7 +244,7 @@ def fuse_conv_and_bn(conv, bn):
245
244
  Returns:
246
245
  (nn.Conv2d): The fused convolutional layer with gradients disabled.
247
246
 
248
- Example:
247
+ Examples:
249
248
  >>> conv = nn.Conv2d(3, 16, 3)
250
249
  >>> bn = nn.BatchNorm2d(16)
251
250
  >>> fused_conv = fuse_conv_and_bn(conv, bn)
@@ -269,8 +268,7 @@ def fuse_conv_and_bn(conv, bn):
269
268
 
270
269
 
271
270
  def fuse_deconv_and_bn(deconv, bn):
272
- """
273
- Fuse ConvTranspose2d and BatchNorm2d layers for inference optimization.
271
+ """Fuse ConvTranspose2d and BatchNorm2d layers for inference optimization.
274
272
 
275
273
  Args:
276
274
  deconv (nn.ConvTranspose2d): Transposed convolutional layer to fuse.
@@ -279,7 +277,7 @@ def fuse_deconv_and_bn(deconv, bn):
279
277
  Returns:
280
278
  (nn.ConvTranspose2d): The fused transposed convolutional layer with gradients disabled.
281
279
 
282
- Example:
280
+ Examples:
283
281
  >>> deconv = nn.ConvTranspose2d(16, 3, 3)
284
282
  >>> bn = nn.BatchNorm2d(3)
285
283
  >>> fused_deconv = fuse_deconv_and_bn(deconv, bn)
@@ -303,8 +301,7 @@ def fuse_deconv_and_bn(deconv, bn):
303
301
 
304
302
 
305
303
  def model_info(model, detailed=False, verbose=True, imgsz=640):
306
- """
307
- Print and return detailed model information layer by layer.
304
+ """Print and return detailed model information layer by layer.
308
305
 
309
306
  Args:
310
307
  model (nn.Module): Model to analyze.
@@ -333,10 +330,10 @@ def model_info(model, detailed=False, verbose=True, imgsz=640):
333
330
  if len(m._parameters):
334
331
  for pn, p in m.named_parameters():
335
332
  LOGGER.info(
336
- f"{i:>5g}{f'{mn}.{pn}':>40}{mt:>20}{p.requires_grad!r:>10}{p.numel():>12g}{str(list(p.shape)):>20}{p.mean():>10.3g}{p.std():>10.3g}{str(p.dtype).replace('torch.', ''):>15}"
333
+ f"{i:>5g}{f'{mn}.{pn}':>40}{mt:>20}{p.requires_grad!r:>10}{p.numel():>12g}{list(p.shape)!s:>20}{p.mean():>10.3g}{p.std():>10.3g}{str(p.dtype).replace('torch.', ''):>15}"
337
334
  )
338
335
  else: # layers with no learnable params
339
- LOGGER.info(f"{i:>5g}{mn:>40}{mt:>20}{False!r:>10}{0:>12g}{str([]):>20}{'-':>10}{'-':>10}{'-':>15}")
336
+ LOGGER.info(f"{i:>5g}{mn:>40}{mt:>20}{False!r:>10}{0:>12g}{[]!s:>20}{'-':>10}{'-':>10}{'-':>15}")
340
337
 
341
338
  flops = get_flops(model, imgsz) # imgsz may be int or list, i.e. imgsz=640 or imgsz=[640, 320]
342
339
  fused = " (fused)" if getattr(model, "is_fused", lambda: False)() else ""
@@ -358,8 +355,7 @@ def get_num_gradients(model):
358
355
 
359
356
 
360
357
  def model_info_for_loggers(trainer):
361
- """
362
- Return model info dict with useful model information.
358
+ """Return model info dict with useful model information.
363
359
 
364
360
  Args:
365
361
  trainer (ultralytics.engine.trainer.BaseTrainer): The trainer object containing model and validation data.
@@ -392,12 +388,10 @@ def model_info_for_loggers(trainer):
392
388
 
393
389
 
394
390
  def get_flops(model, imgsz=640):
395
- """
396
- Calculate FLOPs (floating point operations) for a model in billions.
391
+ """Calculate FLOPs (floating point operations) for a model in billions.
397
392
 
398
- Attempts two calculation methods: first with a stride-based tensor for efficiency,
399
- then falls back to full image size if needed (e.g., for RTDETR models). Returns 0.0
400
- if thop library is unavailable or calculation fails.
393
+ Attempts two calculation methods: first with a stride-based tensor for efficiency, then falls back to full image
394
+ size if needed (e.g., for RTDETR models). Returns 0.0 if thop library is unavailable or calculation fails.
401
395
 
402
396
  Args:
403
397
  model (nn.Module): The model to calculate FLOPs for.
@@ -434,8 +428,7 @@ def get_flops(model, imgsz=640):
434
428
 
435
429
 
436
430
  def get_flops_with_torch_profiler(model, imgsz=640):
437
- """
438
- Compute model FLOPs using torch profiler (alternative to thop package, but 2-10x slower).
431
+ """Compute model FLOPs using torch profiler (alternative to thop package, but 2-10x slower).
439
432
 
440
433
  Args:
441
434
  model (nn.Module): The model to calculate FLOPs for.
@@ -481,8 +474,7 @@ def initialize_weights(model):
481
474
 
482
475
 
483
476
  def scale_img(img, ratio=1.0, same_shape=False, gs=32):
484
- """
485
- Scale and pad an image tensor, optionally maintaining aspect ratio and padding to gs multiple.
477
+ """Scale and pad an image tensor, optionally maintaining aspect ratio and padding to gs multiple.
486
478
 
487
479
  Args:
488
480
  img (torch.Tensor): Input image tensor.
@@ -504,8 +496,7 @@ def scale_img(img, ratio=1.0, same_shape=False, gs=32):
504
496
 
505
497
 
506
498
  def copy_attr(a, b, include=(), exclude=()):
507
- """
508
- Copy attributes from object 'b' to object 'a', with options to include/exclude certain attributes.
499
+ """Copy attributes from object 'b' to object 'a', with options to include/exclude certain attributes.
509
500
 
510
501
  Args:
511
502
  a (Any): Destination object to copy attributes to.
@@ -521,8 +512,7 @@ def copy_attr(a, b, include=(), exclude=()):
521
512
 
522
513
 
523
514
  def intersect_dicts(da, db, exclude=()):
524
- """
525
- Return a dictionary of intersecting keys with matching shapes, excluding 'exclude' keys, using da values.
515
+ """Return a dictionary of intersecting keys with matching shapes, excluding 'exclude' keys, using da values.
526
516
 
527
517
  Args:
528
518
  da (dict): First dictionary.
@@ -536,8 +526,7 @@ def intersect_dicts(da, db, exclude=()):
536
526
 
537
527
 
538
528
  def is_parallel(model):
539
- """
540
- Return True if model is of type DP or DDP.
529
+ """Return True if model is of type DP or DDP.
541
530
 
542
531
  Args:
543
532
  model (nn.Module): Model to check.
@@ -549,8 +538,7 @@ def is_parallel(model):
549
538
 
550
539
 
551
540
  def unwrap_model(m: nn.Module) -> nn.Module:
552
- """
553
- Unwrap compiled and parallel models to get the base model.
541
+ """Unwrap compiled and parallel models to get the base model.
554
542
 
555
543
  Args:
556
544
  m (nn.Module): A model that may be wrapped by torch.compile (._orig_mod) or parallel wrappers such as
@@ -569,8 +557,7 @@ def unwrap_model(m: nn.Module) -> nn.Module:
569
557
 
570
558
 
571
559
  def one_cycle(y1=0.0, y2=1.0, steps=100):
572
- """
573
- Return a lambda function for sinusoidal ramp from y1 to y2 https://arxiv.org/pdf/1812.01187.pdf.
560
+ """Return a lambda function for sinusoidal ramp from y1 to y2 https://arxiv.org/pdf/1812.01187.pdf.
574
561
 
575
562
  Args:
576
563
  y1 (float, optional): Initial value.
@@ -584,8 +571,7 @@ def one_cycle(y1=0.0, y2=1.0, steps=100):
584
571
 
585
572
 
586
573
  def init_seeds(seed=0, deterministic=False):
587
- """
588
- Initialize random number generator (RNG) seeds https://pytorch.org/docs/stable/notes/randomness.html.
574
+ """Initialize random number generator (RNG) seeds https://pytorch.org/docs/stable/notes/randomness.html.
589
575
 
590
576
  Args:
591
577
  seed (int, optional): Random seed.
@@ -618,11 +604,10 @@ def unset_deterministic():
618
604
 
619
605
 
620
606
  class ModelEMA:
621
- """
622
- Updated Exponential Moving Average (EMA) implementation.
607
+ """Updated Exponential Moving Average (EMA) implementation.
623
608
 
624
- Keeps a moving average of everything in the model state_dict (parameters and buffers).
625
- For EMA details see References.
609
+ Keeps a moving average of everything in the model state_dict (parameters and buffers). For EMA details see
610
+ References.
626
611
 
627
612
  To disable EMA set the `enabled` attribute to `False`.
628
613
 
@@ -638,8 +623,7 @@ class ModelEMA:
638
623
  """
639
624
 
640
625
  def __init__(self, model, decay=0.9999, tau=2000, updates=0):
641
- """
642
- Initialize EMA for 'model' with given arguments.
626
+ """Initialize EMA for 'model' with given arguments.
643
627
 
644
628
  Args:
645
629
  model (nn.Module): Model to create EMA for.
@@ -655,8 +639,7 @@ class ModelEMA:
655
639
  self.enabled = True
656
640
 
657
641
  def update(self, model):
658
- """
659
- Update EMA parameters.
642
+ """Update EMA parameters.
660
643
 
661
644
  Args:
662
645
  model (nn.Module): Model to update EMA from.
@@ -673,8 +656,7 @@ class ModelEMA:
673
656
  # assert v.dtype == msd[k].dtype == torch.float32, f'{k}: EMA {v.dtype}, model {msd[k].dtype}'
674
657
 
675
658
  def update_attr(self, model, include=(), exclude=("process_group", "reducer")):
676
- """
677
- Update attributes and save stripped model with optimizer removed.
659
+ """Update attributes and save stripped model with optimizer removed.
678
660
 
679
661
  Args:
680
662
  model (nn.Module): Model to update attributes from.
@@ -685,9 +667,8 @@ class ModelEMA:
685
667
  copy_attr(self.ema, model, include, exclude)
686
668
 
687
669
 
688
- def strip_optimizer(f: str | Path = "best.pt", s: str = "", updates: dict[str, Any] = None) -> dict[str, Any]:
689
- """
690
- Strip optimizer from 'f' to finalize training, optionally save as 's'.
670
+ def strip_optimizer(f: str | Path = "best.pt", s: str = "", updates: dict[str, Any] | None = None) -> dict[str, Any]:
671
+ """Strip optimizer from 'f' to finalize training, optionally save as 's'.
691
672
 
692
673
  Args:
693
674
  f (str | Path): File path to model to strip the optimizer from.
@@ -747,8 +728,7 @@ def strip_optimizer(f: str | Path = "best.pt", s: str = "", updates: dict[str, A
747
728
 
748
729
 
749
730
  def convert_optimizer_state_dict_to_fp16(state_dict):
750
- """
751
- Convert the state_dict of a given optimizer to FP16, focusing on the 'state' key for tensor conversions.
731
+ """Convert the state_dict of a given optimizer to FP16, focusing on the 'state' key for tensor conversions.
752
732
 
753
733
  Args:
754
734
  state_dict (dict): Optimizer state dictionary.
@@ -766,12 +746,11 @@ def convert_optimizer_state_dict_to_fp16(state_dict):
766
746
 
767
747
  @contextmanager
768
748
  def cuda_memory_usage(device=None):
769
- """
770
- Monitor and manage CUDA memory usage.
749
+ """Monitor and manage CUDA memory usage.
771
750
 
772
- This function checks if CUDA is available and, if so, empties the CUDA cache to free up unused memory.
773
- It then yields a dictionary containing memory usage information, which can be updated by the caller.
774
- Finally, it updates the dictionary with the amount of memory reserved by CUDA on the specified device.
751
+ This function checks if CUDA is available and, if so, empties the CUDA cache to free up unused memory. It then
752
+ yields a dictionary containing memory usage information, which can be updated by the caller. Finally, it updates the
753
+ dictionary with the amount of memory reserved by CUDA on the specified device.
775
754
 
776
755
  Args:
777
756
  device (torch.device, optional): The CUDA device to query memory usage for.
@@ -791,8 +770,7 @@ def cuda_memory_usage(device=None):
791
770
 
792
771
 
793
772
  def profile_ops(input, ops, n=10, device=None, max_num_obj=0):
794
- """
795
- Ultralytics speed, memory and FLOPs profiler.
773
+ """Ultralytics speed, memory and FLOPs profiler.
796
774
 
797
775
  Args:
798
776
  input (torch.Tensor | list): Input tensor(s) to profile.
@@ -865,7 +843,7 @@ def profile_ops(input, ops, n=10, device=None, max_num_obj=0):
865
843
  mem += cuda_info["memory"] / 1e9 # (GB)
866
844
  s_in, s_out = (tuple(x.shape) if isinstance(x, torch.Tensor) else "list" for x in (x, y)) # shapes
867
845
  p = sum(x.numel() for x in m.parameters()) if isinstance(m, nn.Module) else 0 # parameters
868
- LOGGER.info(f"{p:12}{flops:12.4g}{mem:>14.3f}{tf:14.4g}{tb:14.4g}{str(s_in):>24s}{str(s_out):>24s}")
846
+ LOGGER.info(f"{p:12}{flops:12.4g}{mem:>14.3f}{tf:14.4g}{tb:14.4g}{s_in!s:>24s}{s_out!s:>24s}")
869
847
  results.append([p, flops, mem, tf, tb, s_in, s_out])
870
848
  except Exception as e:
871
849
  LOGGER.info(e)
@@ -877,8 +855,7 @@ def profile_ops(input, ops, n=10, device=None, max_num_obj=0):
877
855
 
878
856
 
879
857
  class EarlyStopping:
880
- """
881
- Early stopping class that stops training when a specified number of epochs have passed without improvement.
858
+ """Early stopping class that stops training when a specified number of epochs have passed without improvement.
882
859
 
883
860
  Attributes:
884
861
  best_fitness (float): Best fitness value observed.
@@ -888,8 +865,7 @@ class EarlyStopping:
888
865
  """
889
866
 
890
867
  def __init__(self, patience=50):
891
- """
892
- Initialize early stopping object.
868
+ """Initialize early stopping object.
893
869
 
894
870
  Args:
895
871
  patience (int, optional): Number of epochs to wait after fitness stops improving before stopping.
@@ -900,8 +876,7 @@ class EarlyStopping:
900
876
  self.possible_stop = False # possible stop may occur next epoch
901
877
 
902
878
  def __call__(self, epoch, fitness):
903
- """
904
- Check whether to stop training.
879
+ """Check whether to stop training.
905
880
 
906
881
  Args:
907
882
  epoch (int): Current epoch of training
@@ -938,8 +913,7 @@ def attempt_compile(
938
913
  warmup: bool = False,
939
914
  mode: bool | str = "default",
940
915
  ) -> torch.nn.Module:
941
- """
942
- Compile a model with torch.compile and optionally warm up the graph to reduce first-iteration latency.
916
+ """Compile a model with torch.compile and optionally warm up the graph to reduce first-iteration latency.
943
917
 
944
918
  This utility attempts to compile the provided model using the inductor backend with dynamic shapes enabled and an
945
919
  autotuning mode. If compilation is unavailable or fails, the original model is returned unchanged. An optional
@@ -957,15 +931,15 @@ def attempt_compile(
957
931
  Returns:
958
932
  model (torch.nn.Module): Compiled model if compilation succeeds, otherwise the original unmodified model.
959
933
 
960
- Notes:
961
- - If the current PyTorch build does not provide torch.compile, the function returns the input model immediately.
962
- - Warmup runs under torch.inference_mode and may use torch.autocast for CUDA/MPS to align compute precision.
963
- - CUDA devices are synchronized after warmup to account for asynchronous kernel execution.
964
-
965
934
  Examples:
966
935
  >>> device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
967
936
  >>> # Try to compile and warm up a model with a 640x640 input
968
937
  >>> model = attempt_compile(model, device=device, imgsz=640, use_autocast=True, warmup=True)
938
+
939
+ Notes:
940
+ - If the current PyTorch build does not provide torch.compile, the function returns the input model immediately.
941
+ - Warmup runs under torch.inference_mode and may use torch.autocast for CUDA/MPS to align compute precision.
942
+ - CUDA devices are synchronized after warmup to account for asynchronous kernel execution.
969
943
  """
970
944
  if not hasattr(torch, "compile") or not mode:
971
945
  return model
ultralytics/utils/tqdm.py CHANGED
@@ -16,13 +16,12 @@ def is_noninteractive_console() -> bool:
16
16
 
17
17
 
18
18
  class TQDM:
19
- """
20
- Lightweight zero-dependency progress bar for Ultralytics.
19
+ """Lightweight zero-dependency progress bar for Ultralytics.
21
20
 
22
- Provides clean, rich-style progress bars suitable for various environments including Weights & Biases,
23
- console outputs, and other logging systems. Features zero external dependencies, clean single-line output,
24
- rich-style progress bars with Unicode block characters, context manager support, iterator protocol support,
25
- and dynamic description updates.
21
+ Provides clean, rich-style progress bars suitable for various environments including Weights & Biases, console
22
+ outputs, and other logging systems. Features zero external dependencies, clean single-line output, rich-style
23
+ progress bars with Unicode block characters, context manager support, iterator protocol support, and dynamic
24
+ description updates.
26
25
 
27
26
  Attributes:
28
27
  iterable (object): Iterable to wrap with progress bar.
@@ -94,8 +93,7 @@ class TQDM:
94
93
  initial: int = 0,
95
94
  **kwargs,
96
95
  ) -> None:
97
- """
98
- Initialize the TQDM progress bar with specified configuration options.
96
+ """Initialize the TQDM progress bar with specified configuration options.
99
97
 
100
98
  Args:
101
99
  iterable (object, optional): Iterable to wrap with progress bar.
@@ -111,11 +109,6 @@ class TQDM:
111
109
  bar_format (str, optional): Custom bar format string.
112
110
  initial (int, optional): Initial counter value.
113
111
  **kwargs (Any): Additional keyword arguments for compatibility (ignored).
114
-
115
- Examples:
116
- >>> pbar = TQDM(range(100), desc="Processing")
117
- >>> with TQDM(total=1000, unit="B", unit_scale=True) as pbar:
118
- ... pbar.update(1024) # Updates by 1KB
119
112
  """
120
113
  # Disable if not verbose
121
114
  if disable is None:
@@ -150,7 +143,7 @@ class TQDM:
150
143
  self.start_t = time.time()
151
144
  self.last_rate = 0.0
152
145
  self.closed = False
153
- self.is_bytes = unit_scale and unit in ("B", "bytes")
146
+ self.is_bytes = unit_scale and unit in {"B", "bytes"}
154
147
  self.scales = (
155
148
  [(1073741824, "GB/s"), (1048576, "MB/s"), (1024, "KB/s")]
156
149
  if self.is_bytes
@@ -161,9 +154,17 @@ class TQDM:
161
154
  self._display()
162
155
 
163
156
  def _format_rate(self, rate: float) -> str:
164
- """Format rate with units."""
157
+ """Format rate with units, switching between it/s and s/it for readability."""
165
158
  if rate <= 0:
166
159
  return ""
160
+
161
+ inv_rate = 1 / rate if rate else None
162
+
163
+ # Use s/it format when inv_rate > 1 (i.e., rate < 1 it/s) for better readability
164
+ if inv_rate and inv_rate > 1:
165
+ return f"{inv_rate:.1f}s/B" if self.is_bytes else f"{inv_rate:.1f}s/{self.unit}"
166
+
167
+ # Use it/s format for fast iterations
167
168
  fallback = f"{rate:.1f}B/s" if self.is_bytes else f"{rate:.1f}{self.unit}/s"
168
169
  return next((f"{rate / t:.1f}{u}" for t, u in self.scales if rate >= t), fallback)
169
170
 
@@ -178,7 +179,8 @@ class TQDM:
178
179
  num /= self.unit_divisor
179
180
  return f"{num:.1f}PB"
180
181
 
181
- def _format_time(self, seconds: float) -> str:
182
+ @staticmethod
183
+ def _format_time(seconds: float) -> str:
182
184
  """Format time duration."""
183
185
  if seconds < 60:
184
186
  return f"{seconds:.1f}s"
@@ -250,10 +252,8 @@ class TQDM:
250
252
  percent = (self.n / self.total) * 100
251
253
  n_str = self._format_num(self.n)
252
254
  t_str = self._format_num(self.total)
253
- if self.is_bytes:
254
- # Collapse suffix only when identical (e.g. "5.4/5.4MB")
255
- if n_str[-2] == t_str[-2]:
256
- n_str = n_str.rstrip("KMGTPB") # Remove unit suffix from current if different than total
255
+ if self.is_bytes and n_str[-2] == t_str[-2]: # Collapse suffix only when identical (e.g. "5.4/5.4MB")
256
+ n_str = n_str.rstrip("KMGTPB")
257
257
  else:
258
258
  percent = 0.0
259
259
  n_str, t_str = self._format_num(self.n), "?"
@@ -2,17 +2,17 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import ast
5
6
  from urllib.parse import urlsplit
6
7
 
7
8
  import numpy as np
8
9
 
9
10
 
10
11
  class TritonRemoteModel:
11
- """
12
- Client for interacting with a remote Triton Inference Server model.
12
+ """Client for interacting with a remote Triton Inference Server model.
13
13
 
14
- This class provides a convenient interface for sending inference requests to a Triton Inference Server
15
- and processing the responses. Supports both HTTP and gRPC communication protocols.
14
+ This class provides a convenient interface for sending inference requests to a Triton Inference Server and
15
+ processing the responses. Supports both HTTP and gRPC communication protocols.
16
16
 
17
17
  Attributes:
18
18
  endpoint (str): The name of the model on the Triton server.
@@ -38,8 +38,7 @@ class TritonRemoteModel:
38
38
  """
39
39
 
40
40
  def __init__(self, url: str, endpoint: str = "", scheme: str = ""):
41
- """
42
- Initialize the TritonRemoteModel for interacting with a remote Triton Inference Server.
41
+ """Initialize the TritonRemoteModel for interacting with a remote Triton Inference Server.
43
42
 
44
43
  Arguments may be provided individually or parsed from a collective 'url' argument of the form
45
44
  <scheme>://<netloc>/<endpoint>/<task_name>
@@ -48,10 +47,6 @@ class TritonRemoteModel:
48
47
  url (str): The URL of the Triton server.
49
48
  endpoint (str, optional): The name of the model on the Triton server.
50
49
  scheme (str, optional): The communication scheme ('http' or 'grpc').
51
-
52
- Examples:
53
- >>> model = TritonRemoteModel(url="localhost:8000", endpoint="yolov8", scheme="http")
54
- >>> model = TritonRemoteModel(url="http://localhost:8000/yolov8")
55
50
  """
56
51
  if not endpoint and not scheme: # Parse all args from URL string
57
52
  splits = urlsplit(url)
@@ -64,12 +59,12 @@ class TritonRemoteModel:
64
59
 
65
60
  # Choose the Triton client based on the communication scheme
66
61
  if scheme == "http":
67
- import tritonclient.http as client # noqa
62
+ import tritonclient.http as client
68
63
 
69
64
  self.triton_client = client.InferenceServerClient(url=self.url, verbose=False, ssl=False)
70
65
  config = self.triton_client.get_model_config(endpoint)
71
66
  else:
72
- import tritonclient.grpc as client # noqa
67
+ import tritonclient.grpc as client
73
68
 
74
69
  self.triton_client = client.InferenceServerClient(url=self.url, verbose=False, ssl=False)
75
70
  config = self.triton_client.get_model_config(endpoint, as_json=True)["config"]
@@ -85,19 +80,18 @@ class TritonRemoteModel:
85
80
  self.np_input_formats = [type_map[x] for x in self.input_formats]
86
81
  self.input_names = [x["name"] for x in config["input"]]
87
82
  self.output_names = [x["name"] for x in config["output"]]
88
- self.metadata = eval(config.get("parameters", {}).get("metadata", {}).get("string_value", "None"))
83
+ self.metadata = ast.literal_eval(config.get("parameters", {}).get("metadata", {}).get("string_value", "None"))
89
84
 
90
85
  def __call__(self, *inputs: np.ndarray) -> list[np.ndarray]:
91
- """
92
- Call the model with the given inputs and return inference results.
86
+ """Call the model with the given inputs and return inference results.
93
87
 
94
88
  Args:
95
- *inputs (np.ndarray): Input data to the model. Each array should match the expected shape and type
96
- for the corresponding model input.
89
+ *inputs (np.ndarray): Input data to the model. Each array should match the expected shape and type for the
90
+ corresponding model input.
97
91
 
98
92
  Returns:
99
- (list[np.ndarray]): Model outputs with the same dtype as the input. Each element in the list
100
- corresponds to one of the model's output tensors.
93
+ (list[np.ndarray]): Model outputs with the same dtype as the input. Each element in the list corresponds to
94
+ one of the model's output tensors.
101
95
 
102
96
  Examples:
103
97
  >>> model = TritonRemoteModel(url="localhost:8000", endpoint="yolov8", scheme="http")
@@ -1,19 +1,20 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from ultralytics.cfg import TASK2DATA, TASK2METRIC, get_cfg, get_save_dir
4
6
  from ultralytics.utils import DEFAULT_CFG, DEFAULT_CFG_DICT, LOGGER, NUM_THREADS, checks, colorstr
5
7
 
6
8
 
7
9
  def run_ray_tune(
8
10
  model,
9
- space: dict = None,
11
+ space: dict | None = None,
10
12
  grace_period: int = 10,
11
- gpu_per_trial: int = None,
13
+ gpu_per_trial: int | None = None,
12
14
  max_samples: int = 10,
13
15
  **train_args,
14
16
  ):
15
- """
16
- Run hyperparameter tuning using Ray Tune.
17
+ """Run hyperparameter tuning using Ray Tune.
17
18
 
18
19
  Args:
19
20
  model (YOLO): Model to run the tuner on.
@@ -76,7 +77,7 @@ def run_ray_tune(
76
77
  "perspective": tune.uniform(0.0, 0.001), # image perspective (+/- fraction), range 0-0.001
77
78
  "flipud": tune.uniform(0.0, 1.0), # image flip up-down (probability)
78
79
  "fliplr": tune.uniform(0.0, 1.0), # image flip left-right (probability)
79
- "bgr": tune.uniform(0.0, 1.0), # image channel BGR (probability)
80
+ "bgr": tune.uniform(0.0, 1.0), # swap RGB↔BGR channels (probability)
80
81
  "mosaic": tune.uniform(0.0, 1.0), # image mosaic (probability)
81
82
  "mixup": tune.uniform(0.0, 1.0), # image mixup (probability)
82
83
  "cutmix": tune.uniform(0.0, 1.0), # image cutmix (probability)
@@ -86,12 +87,23 @@ def run_ray_tune(
86
87
  # Put the model in ray store
87
88
  task = model.task
88
89
  model_in_store = ray.put(model)
90
+ base_name = train_args.get("name", "tune")
89
91
 
90
92
  def _tune(config):
91
93
  """Train the YOLO model with the specified hyperparameters and return results."""
92
94
  model_to_train = ray.get(model_in_store) # get the model from ray store for tuning
93
95
  model_to_train.reset_callbacks()
94
96
  config.update(train_args)
97
+
98
+ # Set trial-specific name for W&B logging
99
+ try:
100
+ trial_id = tune.get_trial_id() # Get current trial ID (e.g., "2c2fc_00000")
101
+ trial_suffix = trial_id.split("_")[-1] if "_" in trial_id else trial_id
102
+ config["name"] = f"{base_name}_{trial_suffix}"
103
+ except Exception:
104
+ # Not in Ray Tune context or error getting trial ID, use base name
105
+ config["name"] = base_name
106
+
95
107
  results = model_to_train.train(**config)
96
108
  return results.results_dict
97
109