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.
- {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/METADATA +13 -14
- dgenerate_ultralytics_headless-8.3.248.dist-info/RECORD +298 -0
- tests/__init__.py +5 -7
- tests/conftest.py +8 -15
- tests/test_cli.py +1 -1
- tests/test_cuda.py +5 -8
- tests/test_engine.py +1 -1
- tests/test_exports.py +57 -12
- tests/test_integrations.py +4 -4
- tests/test_python.py +84 -53
- tests/test_solutions.py +160 -151
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +56 -62
- ultralytics/cfg/datasets/Argoverse.yaml +7 -6
- ultralytics/cfg/datasets/DOTAv1.5.yaml +1 -1
- ultralytics/cfg/datasets/DOTAv1.yaml +1 -1
- ultralytics/cfg/datasets/ImageNet.yaml +1 -1
- ultralytics/cfg/datasets/VOC.yaml +15 -16
- ultralytics/cfg/datasets/african-wildlife.yaml +1 -1
- ultralytics/cfg/datasets/coco-pose.yaml +21 -0
- ultralytics/cfg/datasets/coco128-seg.yaml +1 -1
- ultralytics/cfg/datasets/coco8-pose.yaml +21 -0
- ultralytics/cfg/datasets/dog-pose.yaml +28 -0
- ultralytics/cfg/datasets/dota8-multispectral.yaml +1 -1
- ultralytics/cfg/datasets/dota8.yaml +2 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +26 -2
- ultralytics/cfg/datasets/kitti.yaml +27 -0
- ultralytics/cfg/datasets/lvis.yaml +5 -5
- ultralytics/cfg/datasets/open-images-v7.yaml +1 -1
- ultralytics/cfg/datasets/tiger-pose.yaml +16 -0
- ultralytics/cfg/datasets/xView.yaml +16 -16
- ultralytics/cfg/default.yaml +1 -1
- ultralytics/cfg/models/11/yolo11-pose.yaml +1 -1
- ultralytics/cfg/models/11/yoloe-11-seg.yaml +2 -2
- ultralytics/cfg/models/11/yoloe-11.yaml +2 -2
- ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +1 -1
- ultralytics/cfg/models/v10/yolov10b.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10l.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10m.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10n.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10s.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10x.yaml +2 -2
- ultralytics/cfg/models/v3/yolov3-tiny.yaml +1 -1
- ultralytics/cfg/models/v6/yolov6.yaml +1 -1
- ultralytics/cfg/models/v8/yoloe-v8-seg.yaml +9 -6
- ultralytics/cfg/models/v8/yoloe-v8.yaml +9 -6
- ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-obb.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-p2.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-world.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-worldv2.yaml +6 -6
- ultralytics/cfg/models/v9/yolov9s.yaml +1 -1
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/annotator.py +3 -4
- ultralytics/data/augment.py +285 -475
- ultralytics/data/base.py +18 -26
- ultralytics/data/build.py +147 -25
- ultralytics/data/converter.py +36 -46
- ultralytics/data/dataset.py +46 -74
- ultralytics/data/loaders.py +42 -49
- ultralytics/data/split.py +5 -6
- ultralytics/data/split_dota.py +8 -15
- ultralytics/data/utils.py +34 -43
- ultralytics/engine/exporter.py +319 -237
- ultralytics/engine/model.py +148 -188
- ultralytics/engine/predictor.py +29 -38
- ultralytics/engine/results.py +177 -311
- ultralytics/engine/trainer.py +83 -59
- ultralytics/engine/tuner.py +23 -34
- ultralytics/engine/validator.py +39 -22
- ultralytics/hub/__init__.py +16 -19
- ultralytics/hub/auth.py +6 -12
- ultralytics/hub/google/__init__.py +7 -10
- ultralytics/hub/session.py +15 -25
- ultralytics/hub/utils.py +5 -8
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +8 -10
- ultralytics/models/fastsam/predict.py +17 -29
- ultralytics/models/fastsam/utils.py +1 -2
- ultralytics/models/fastsam/val.py +5 -7
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +5 -8
- ultralytics/models/nas/predict.py +7 -9
- ultralytics/models/nas/val.py +1 -2
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +5 -8
- ultralytics/models/rtdetr/predict.py +15 -19
- ultralytics/models/rtdetr/train.py +10 -13
- ultralytics/models/rtdetr/val.py +21 -23
- ultralytics/models/sam/__init__.py +15 -2
- ultralytics/models/sam/amg.py +14 -20
- ultralytics/models/sam/build.py +26 -19
- ultralytics/models/sam/build_sam3.py +377 -0
- ultralytics/models/sam/model.py +29 -32
- ultralytics/models/sam/modules/blocks.py +83 -144
- ultralytics/models/sam/modules/decoders.py +19 -37
- ultralytics/models/sam/modules/encoders.py +44 -101
- ultralytics/models/sam/modules/memory_attention.py +16 -30
- ultralytics/models/sam/modules/sam.py +200 -73
- ultralytics/models/sam/modules/tiny_encoder.py +64 -83
- ultralytics/models/sam/modules/transformer.py +18 -28
- ultralytics/models/sam/modules/utils.py +174 -50
- ultralytics/models/sam/predict.py +2248 -350
- ultralytics/models/sam/sam3/__init__.py +3 -0
- ultralytics/models/sam/sam3/decoder.py +546 -0
- ultralytics/models/sam/sam3/encoder.py +529 -0
- ultralytics/models/sam/sam3/geometry_encoders.py +415 -0
- ultralytics/models/sam/sam3/maskformer_segmentation.py +286 -0
- ultralytics/models/sam/sam3/model_misc.py +199 -0
- ultralytics/models/sam/sam3/necks.py +129 -0
- ultralytics/models/sam/sam3/sam3_image.py +339 -0
- ultralytics/models/sam/sam3/text_encoder_ve.py +307 -0
- ultralytics/models/sam/sam3/vitdet.py +547 -0
- ultralytics/models/sam/sam3/vl_combiner.py +160 -0
- ultralytics/models/utils/loss.py +14 -26
- ultralytics/models/utils/ops.py +13 -17
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +9 -12
- ultralytics/models/yolo/classify/train.py +11 -32
- ultralytics/models/yolo/classify/val.py +29 -28
- ultralytics/models/yolo/detect/predict.py +7 -10
- ultralytics/models/yolo/detect/train.py +11 -20
- ultralytics/models/yolo/detect/val.py +70 -58
- ultralytics/models/yolo/model.py +36 -53
- ultralytics/models/yolo/obb/predict.py +5 -14
- ultralytics/models/yolo/obb/train.py +11 -14
- ultralytics/models/yolo/obb/val.py +39 -36
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +6 -21
- ultralytics/models/yolo/pose/train.py +10 -15
- ultralytics/models/yolo/pose/val.py +38 -57
- ultralytics/models/yolo/segment/predict.py +14 -18
- ultralytics/models/yolo/segment/train.py +3 -6
- ultralytics/models/yolo/segment/val.py +93 -45
- ultralytics/models/yolo/world/train.py +8 -14
- ultralytics/models/yolo/world/train_world.py +11 -34
- ultralytics/models/yolo/yoloe/__init__.py +7 -7
- ultralytics/models/yolo/yoloe/predict.py +16 -23
- ultralytics/models/yolo/yoloe/train.py +30 -43
- ultralytics/models/yolo/yoloe/train_seg.py +5 -10
- ultralytics/models/yolo/yoloe/val.py +15 -20
- ultralytics/nn/__init__.py +7 -7
- ultralytics/nn/autobackend.py +145 -77
- ultralytics/nn/modules/__init__.py +60 -60
- ultralytics/nn/modules/activation.py +4 -6
- ultralytics/nn/modules/block.py +132 -216
- ultralytics/nn/modules/conv.py +52 -97
- ultralytics/nn/modules/head.py +50 -103
- ultralytics/nn/modules/transformer.py +76 -88
- ultralytics/nn/modules/utils.py +16 -21
- ultralytics/nn/tasks.py +94 -154
- ultralytics/nn/text_model.py +40 -67
- ultralytics/solutions/__init__.py +12 -12
- ultralytics/solutions/ai_gym.py +11 -17
- ultralytics/solutions/analytics.py +15 -16
- ultralytics/solutions/config.py +5 -6
- ultralytics/solutions/distance_calculation.py +10 -13
- ultralytics/solutions/heatmap.py +7 -13
- ultralytics/solutions/instance_segmentation.py +5 -8
- ultralytics/solutions/object_blurrer.py +7 -10
- ultralytics/solutions/object_counter.py +12 -19
- ultralytics/solutions/object_cropper.py +8 -14
- ultralytics/solutions/parking_management.py +33 -31
- ultralytics/solutions/queue_management.py +10 -12
- ultralytics/solutions/region_counter.py +9 -12
- ultralytics/solutions/security_alarm.py +15 -20
- ultralytics/solutions/similarity_search.py +10 -15
- ultralytics/solutions/solutions.py +75 -74
- ultralytics/solutions/speed_estimation.py +7 -10
- ultralytics/solutions/streamlit_inference.py +2 -4
- ultralytics/solutions/templates/similarity-search.html +7 -18
- ultralytics/solutions/trackzone.py +7 -10
- ultralytics/solutions/vision_eye.py +5 -8
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +3 -5
- ultralytics/trackers/bot_sort.py +10 -27
- ultralytics/trackers/byte_tracker.py +14 -30
- ultralytics/trackers/track.py +3 -6
- ultralytics/trackers/utils/gmc.py +11 -22
- ultralytics/trackers/utils/kalman_filter.py +37 -48
- ultralytics/trackers/utils/matching.py +12 -15
- ultralytics/utils/__init__.py +116 -116
- ultralytics/utils/autobatch.py +2 -4
- ultralytics/utils/autodevice.py +17 -18
- ultralytics/utils/benchmarks.py +32 -46
- ultralytics/utils/callbacks/base.py +8 -10
- ultralytics/utils/callbacks/clearml.py +5 -13
- ultralytics/utils/callbacks/comet.py +32 -46
- ultralytics/utils/callbacks/dvc.py +13 -18
- ultralytics/utils/callbacks/mlflow.py +4 -5
- ultralytics/utils/callbacks/neptune.py +7 -15
- ultralytics/utils/callbacks/platform.py +314 -38
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +23 -31
- ultralytics/utils/callbacks/wb.py +10 -13
- ultralytics/utils/checks.py +99 -76
- ultralytics/utils/cpu.py +3 -8
- ultralytics/utils/dist.py +8 -12
- ultralytics/utils/downloads.py +20 -30
- ultralytics/utils/errors.py +6 -14
- ultralytics/utils/events.py +2 -4
- ultralytics/utils/export/__init__.py +4 -236
- ultralytics/utils/export/engine.py +237 -0
- ultralytics/utils/export/imx.py +91 -55
- ultralytics/utils/export/tensorflow.py +231 -0
- ultralytics/utils/files.py +24 -28
- ultralytics/utils/git.py +9 -11
- ultralytics/utils/instance.py +30 -51
- ultralytics/utils/logger.py +212 -114
- ultralytics/utils/loss.py +14 -22
- ultralytics/utils/metrics.py +126 -155
- ultralytics/utils/nms.py +13 -16
- ultralytics/utils/ops.py +107 -165
- ultralytics/utils/patches.py +33 -21
- ultralytics/utils/plotting.py +72 -80
- ultralytics/utils/tal.py +25 -39
- ultralytics/utils/torch_utils.py +52 -78
- ultralytics/utils/tqdm.py +20 -20
- ultralytics/utils/triton.py +13 -19
- ultralytics/utils/tuner.py +17 -5
- dgenerate_ultralytics_headless-8.3.214.dist-info/RECORD +0 -283
- {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.214.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/top_level.txt +0 -0
ultralytics/utils/torch_utils.py
CHANGED
|
@@ -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"] = "
|
|
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
|
-
|
|
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
|
-
|
|
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}{
|
|
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}{
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
774
|
-
|
|
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}{
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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), "?"
|
ultralytics/utils/triton.py
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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")
|
ultralytics/utils/tuner.py
CHANGED
|
@@ -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), #
|
|
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
|
|