dgenerate-ultralytics-headless 8.3.196__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.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/METADATA +33 -34
- 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 +8 -10
- tests/test_cuda.py +9 -10
- tests/test_engine.py +29 -2
- tests/test_exports.py +69 -21
- tests/test_integrations.py +8 -11
- tests/test_python.py +109 -71
- tests/test_solutions.py +170 -159
- ultralytics/__init__.py +27 -9
- ultralytics/cfg/__init__.py +57 -64
- 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/Objects365.yaml +19 -15
- ultralytics/cfg/datasets/SKU-110K.yaml +1 -1
- ultralytics/cfg/datasets/VOC.yaml +19 -21
- ultralytics/cfg/datasets/VisDrone.yaml +5 -5
- ultralytics/cfg/datasets/african-wildlife.yaml +1 -1
- ultralytics/cfg/datasets/coco-pose.yaml +24 -2
- ultralytics/cfg/datasets/coco.yaml +2 -2
- ultralytics/cfg/datasets/coco128-seg.yaml +1 -1
- ultralytics/cfg/datasets/coco8-pose.yaml +21 -0
- ultralytics/cfg/datasets/construction-ppe.yaml +32 -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 +7 -7
- 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 +96 -94
- 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/cfg/trackers/botsort.yaml +16 -17
- ultralytics/cfg/trackers/bytetrack.yaml +9 -11
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/annotator.py +3 -4
- ultralytics/data/augment.py +286 -476
- ultralytics/data/base.py +18 -26
- ultralytics/data/build.py +151 -26
- ultralytics/data/converter.py +38 -50
- ultralytics/data/dataset.py +47 -75
- ultralytics/data/loaders.py +42 -49
- ultralytics/data/split.py +5 -6
- ultralytics/data/split_dota.py +8 -15
- ultralytics/data/utils.py +41 -45
- ultralytics/engine/exporter.py +462 -462
- ultralytics/engine/model.py +150 -191
- ultralytics/engine/predictor.py +30 -40
- ultralytics/engine/results.py +177 -311
- ultralytics/engine/trainer.py +193 -120
- ultralytics/engine/tuner.py +77 -63
- 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 +19 -30
- 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 +7 -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 +22 -40
- ultralytics/models/sam/modules/encoders.py +44 -101
- ultralytics/models/sam/modules/memory_attention.py +16 -30
- ultralytics/models/sam/modules/sam.py +206 -79
- 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 +2268 -366
- 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 +15 -41
- ultralytics/models/yolo/classify/val.py +34 -32
- ultralytics/models/yolo/detect/predict.py +8 -11
- ultralytics/models/yolo/detect/train.py +13 -32
- ultralytics/models/yolo/detect/val.py +75 -63
- ultralytics/models/yolo/model.py +37 -53
- ultralytics/models/yolo/obb/predict.py +5 -14
- ultralytics/models/yolo/obb/train.py +11 -14
- ultralytics/models/yolo/obb/val.py +42 -39
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +7 -22
- ultralytics/models/yolo/pose/train.py +10 -22
- ultralytics/models/yolo/pose/val.py +40 -59
- ultralytics/models/yolo/segment/predict.py +16 -20
- ultralytics/models/yolo/segment/train.py +3 -12
- ultralytics/models/yolo/segment/val.py +106 -56
- ultralytics/models/yolo/world/train.py +12 -16
- 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 +31 -56
- ultralytics/models/yolo/yoloe/train_seg.py +5 -10
- ultralytics/models/yolo/yoloe/val.py +16 -21
- ultralytics/nn/__init__.py +7 -7
- ultralytics/nn/autobackend.py +152 -80
- ultralytics/nn/modules/__init__.py +60 -60
- ultralytics/nn/modules/activation.py +4 -6
- ultralytics/nn/modules/block.py +133 -217
- ultralytics/nn/modules/conv.py +52 -97
- ultralytics/nn/modules/head.py +64 -116
- ultralytics/nn/modules/transformer.py +79 -89
- ultralytics/nn/modules/utils.py +16 -21
- ultralytics/nn/tasks.py +111 -156
- 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 +13 -17
- ultralytics/solutions/solutions.py +75 -74
- ultralytics/solutions/speed_estimation.py +7 -10
- ultralytics/solutions/streamlit_inference.py +4 -7
- 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 +70 -70
- 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 +151 -87
- ultralytics/utils/cpu.py +3 -8
- ultralytics/utils/dist.py +19 -15
- ultralytics/utils/downloads.py +29 -41
- ultralytics/utils/errors.py +6 -14
- ultralytics/utils/events.py +2 -4
- ultralytics/utils/export/__init__.py +7 -0
- ultralytics/utils/{export.py → export/engine.py} +16 -16
- ultralytics/utils/export/imx.py +325 -0
- 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 +15 -24
- ultralytics/utils/metrics.py +131 -160
- ultralytics/utils/nms.py +21 -30
- ultralytics/utils/ops.py +107 -165
- ultralytics/utils/patches.py +33 -21
- ultralytics/utils/plotting.py +122 -119
- ultralytics/utils/tal.py +28 -44
- ultralytics/utils/torch_utils.py +70 -187
- ultralytics/utils/tqdm.py +20 -20
- ultralytics/utils/triton.py +13 -19
- ultralytics/utils/tuner.py +17 -5
- dgenerate_ultralytics_headless-8.3.196.dist-info/RECORD +0 -281
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/top_level.txt +0 -0
ultralytics/engine/tuner.py
CHANGED
|
@@ -8,7 +8,7 @@ that yield the best model performance. This is particularly crucial in deep lear
|
|
|
8
8
|
where small changes in hyperparameters can lead to significant differences in model accuracy and efficiency.
|
|
9
9
|
|
|
10
10
|
Examples:
|
|
11
|
-
Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=
|
|
11
|
+
Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=10 for 300 tuning iterations.
|
|
12
12
|
>>> from ultralytics import YOLO
|
|
13
13
|
>>> model = YOLO("yolo11n.pt")
|
|
14
14
|
>>> model.tune(data="coco8.yaml", epochs=10, iterations=300, optimizer="AdamW", plots=False, save=False, val=False)
|
|
@@ -16,6 +16,7 @@ Examples:
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
+
import gc
|
|
19
20
|
import random
|
|
20
21
|
import shutil
|
|
21
22
|
import subprocess
|
|
@@ -23,6 +24,7 @@ import time
|
|
|
23
24
|
from datetime import datetime
|
|
24
25
|
|
|
25
26
|
import numpy as np
|
|
27
|
+
import torch
|
|
26
28
|
|
|
27
29
|
from ultralytics.cfg import get_cfg, get_save_dir
|
|
28
30
|
from ultralytics.utils import DEFAULT_CFG, LOGGER, YAML, callbacks, colorstr, remove_colorstr
|
|
@@ -32,12 +34,11 @@ from ultralytics.utils.plotting import plot_tune_results
|
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
class Tuner:
|
|
35
|
-
"""
|
|
36
|
-
A class for hyperparameter tuning of YOLO models.
|
|
37
|
+
"""A class for hyperparameter tuning of YOLO models.
|
|
37
38
|
|
|
38
39
|
The class evolves YOLO model hyperparameters over a given number of iterations by mutating them according to the
|
|
39
|
-
search space and retraining the model to evaluate their performance. Supports both local CSV storage and
|
|
40
|
-
|
|
40
|
+
search space and retraining the model to evaluate their performance. Supports both local CSV storage and distributed
|
|
41
|
+
MongoDB Atlas coordination for multi-machine hyperparameter optimization.
|
|
41
42
|
|
|
42
43
|
Attributes:
|
|
43
44
|
space (dict[str, tuple]): Hyperparameter search space containing bounds and scaling factors for mutation.
|
|
@@ -54,7 +55,7 @@ class Tuner:
|
|
|
54
55
|
__call__: Execute the hyperparameter evolution across multiple iterations.
|
|
55
56
|
|
|
56
57
|
Examples:
|
|
57
|
-
Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=
|
|
58
|
+
Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=10 for 300 tuning iterations.
|
|
58
59
|
>>> from ultralytics import YOLO
|
|
59
60
|
>>> model = YOLO("yolo11n.pt")
|
|
60
61
|
>>> model.tune(
|
|
@@ -81,8 +82,7 @@ class Tuner:
|
|
|
81
82
|
"""
|
|
82
83
|
|
|
83
84
|
def __init__(self, args=DEFAULT_CFG, _callbacks: list | None = None):
|
|
84
|
-
"""
|
|
85
|
-
Initialize the Tuner with configurations.
|
|
85
|
+
"""Initialize the Tuner with configurations.
|
|
86
86
|
|
|
87
87
|
Args:
|
|
88
88
|
args (dict): Configuration for hyperparameter evolution.
|
|
@@ -97,7 +97,7 @@ class Tuner:
|
|
|
97
97
|
"warmup_epochs": (0.0, 5.0), # warmup epochs (fractions ok)
|
|
98
98
|
"warmup_momentum": (0.0, 0.95), # warmup initial momentum
|
|
99
99
|
"box": (1.0, 20.0), # box loss gain
|
|
100
|
-
"cls": (0.
|
|
100
|
+
"cls": (0.1, 4.0), # cls loss gain (scale with pixels)
|
|
101
101
|
"dfl": (0.4, 6.0), # dfl loss gain
|
|
102
102
|
"hsv_h": (0.0, 0.1), # image HSV-Hue augmentation (fraction)
|
|
103
103
|
"hsv_s": (0.0, 0.9), # image HSV-Saturation augmentation (fraction)
|
|
@@ -114,6 +114,7 @@ class Tuner:
|
|
|
114
114
|
"mixup": (0.0, 1.0), # image mixup (probability)
|
|
115
115
|
"cutmix": (0.0, 1.0), # image cutmix (probability)
|
|
116
116
|
"copy_paste": (0.0, 1.0), # segment copy-paste (probability)
|
|
117
|
+
"close_mosaic": (0.0, 10.0), # close dataloader mosaic (epochs)
|
|
117
118
|
}
|
|
118
119
|
mongodb_uri = args.pop("mongodb_uri", None)
|
|
119
120
|
mongodb_db = args.pop("mongodb_db", "ultralytics")
|
|
@@ -139,8 +140,7 @@ class Tuner:
|
|
|
139
140
|
)
|
|
140
141
|
|
|
141
142
|
def _connect(self, uri: str = "mongodb+srv://username:password@cluster.mongodb.net/", max_retries: int = 3):
|
|
142
|
-
"""
|
|
143
|
-
Create MongoDB client with exponential backoff retry on connection failures.
|
|
143
|
+
"""Create MongoDB client with exponential backoff retry on connection failures.
|
|
144
144
|
|
|
145
145
|
Args:
|
|
146
146
|
uri (str): MongoDB connection string with credentials and cluster information.
|
|
@@ -180,12 +180,10 @@ class Tuner:
|
|
|
180
180
|
time.sleep(wait_time)
|
|
181
181
|
|
|
182
182
|
def _init_mongodb(self, mongodb_uri="", mongodb_db="", mongodb_collection=""):
|
|
183
|
-
"""
|
|
184
|
-
Initialize MongoDB connection for distributed tuning.
|
|
183
|
+
"""Initialize MongoDB connection for distributed tuning.
|
|
185
184
|
|
|
186
|
-
Connects to MongoDB Atlas for distributed hyperparameter optimization across multiple machines.
|
|
187
|
-
|
|
188
|
-
from all workers for evolution.
|
|
185
|
+
Connects to MongoDB Atlas for distributed hyperparameter optimization across multiple machines. Each worker
|
|
186
|
+
saves results to a shared collection and reads the latest best hyperparameters from all workers for evolution.
|
|
189
187
|
|
|
190
188
|
Args:
|
|
191
189
|
mongodb_uri (str): MongoDB connection string, e.g. 'mongodb+srv://username:password@cluster.mongodb.net/'.
|
|
@@ -203,8 +201,7 @@ class Tuner:
|
|
|
203
201
|
LOGGER.info(f"{self.prefix}Using MongoDB Atlas for distributed tuning")
|
|
204
202
|
|
|
205
203
|
def _get_mongodb_results(self, n: int = 5) -> list:
|
|
206
|
-
"""
|
|
207
|
-
Get top N results from MongoDB sorted by fitness.
|
|
204
|
+
"""Get top N results from MongoDB sorted by fitness.
|
|
208
205
|
|
|
209
206
|
Args:
|
|
210
207
|
n (int): Number of top results to retrieve.
|
|
@@ -218,8 +215,7 @@ class Tuner:
|
|
|
218
215
|
return []
|
|
219
216
|
|
|
220
217
|
def _save_to_mongodb(self, fitness: float, hyperparameters: dict[str, float], metrics: dict, iteration: int):
|
|
221
|
-
"""
|
|
222
|
-
Save results to MongoDB with proper type conversion.
|
|
218
|
+
"""Save results to MongoDB with proper type conversion.
|
|
223
219
|
|
|
224
220
|
Args:
|
|
225
221
|
fitness (float): Fitness score achieved with these hyperparameters.
|
|
@@ -230,7 +226,7 @@ class Tuner:
|
|
|
230
226
|
try:
|
|
231
227
|
self.collection.insert_one(
|
|
232
228
|
{
|
|
233
|
-
"fitness":
|
|
229
|
+
"fitness": fitness,
|
|
234
230
|
"hyperparameters": {k: (v.item() if hasattr(v, "item") else v) for k, v in hyperparameters.items()},
|
|
235
231
|
"metrics": metrics,
|
|
236
232
|
"timestamp": datetime.now(),
|
|
@@ -241,8 +237,7 @@ class Tuner:
|
|
|
241
237
|
LOGGER.warning(f"{self.prefix}MongoDB save failed: {e}")
|
|
242
238
|
|
|
243
239
|
def _sync_mongodb_to_csv(self):
|
|
244
|
-
"""
|
|
245
|
-
Sync MongoDB results to CSV for plotting compatibility.
|
|
240
|
+
"""Sync MongoDB results to CSV for plotting compatibility.
|
|
246
241
|
|
|
247
242
|
Downloads all results from MongoDB and writes them to the local CSV file in chronological order. This enables
|
|
248
243
|
the existing plotting functions to work seamlessly with distributed MongoDB data.
|
|
@@ -254,31 +249,42 @@ class Tuner:
|
|
|
254
249
|
return
|
|
255
250
|
|
|
256
251
|
# Write to CSV
|
|
257
|
-
headers = ",".join(["fitness"
|
|
252
|
+
headers = ",".join(["fitness", *list(self.space.keys())]) + "\n"
|
|
258
253
|
with open(self.tune_csv, "w", encoding="utf-8") as f:
|
|
259
254
|
f.write(headers)
|
|
260
255
|
for result in all_results:
|
|
261
256
|
fitness = result["fitness"]
|
|
262
257
|
hyp_values = [result["hyperparameters"][k] for k in self.space.keys()]
|
|
263
|
-
log_row = [round(fitness, 5)
|
|
258
|
+
log_row = [round(fitness, 5), *hyp_values]
|
|
264
259
|
f.write(",".join(map(str, log_row)) + "\n")
|
|
265
260
|
|
|
266
261
|
except Exception as e:
|
|
267
262
|
LOGGER.warning(f"{self.prefix}MongoDB to CSV sync failed: {e}")
|
|
268
263
|
|
|
264
|
+
@staticmethod
|
|
265
|
+
def _crossover(x: np.ndarray, alpha: float = 0.2, k: int = 9) -> np.ndarray:
|
|
266
|
+
"""BLX-α crossover from up to top-k parents (x[:,0]=fitness, rest=genes)."""
|
|
267
|
+
k = min(k, len(x))
|
|
268
|
+
# fitness weights (shifted to >0); fallback to uniform if degenerate
|
|
269
|
+
weights = x[:, 0] - x[:, 0].min() + 1e-6
|
|
270
|
+
if not np.isfinite(weights).all() or weights.sum() == 0:
|
|
271
|
+
weights = np.ones_like(weights)
|
|
272
|
+
idxs = random.choices(range(len(x)), weights=weights, k=k)
|
|
273
|
+
parents_mat = np.stack([x[i][1:] for i in idxs], 0) # (k, ng) strip fitness
|
|
274
|
+
lo, hi = parents_mat.min(0), parents_mat.max(0)
|
|
275
|
+
span = hi - lo
|
|
276
|
+
return np.random.uniform(lo - alpha * span, hi + alpha * span)
|
|
277
|
+
|
|
269
278
|
def _mutate(
|
|
270
279
|
self,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
mutation: float = 0.8,
|
|
280
|
+
n: int = 9,
|
|
281
|
+
mutation: float = 0.5,
|
|
274
282
|
sigma: float = 0.2,
|
|
275
283
|
) -> dict[str, float]:
|
|
276
|
-
"""
|
|
277
|
-
Mutate hyperparameters based on bounds and scaling factors specified in `self.space`.
|
|
284
|
+
"""Mutate hyperparameters based on bounds and scaling factors specified in `self.space`.
|
|
278
285
|
|
|
279
286
|
Args:
|
|
280
|
-
|
|
281
|
-
n (int): Number of parents to consider.
|
|
287
|
+
n (int): Number of top parents to consider.
|
|
282
288
|
mutation (float): Probability of a parameter mutation in any given iteration.
|
|
283
289
|
sigma (float): Standard deviation for Gaussian random number generator.
|
|
284
290
|
|
|
@@ -289,51 +295,51 @@ class Tuner:
|
|
|
289
295
|
|
|
290
296
|
# Try MongoDB first if available
|
|
291
297
|
if self.mongodb:
|
|
292
|
-
results
|
|
293
|
-
if results:
|
|
298
|
+
if results := self._get_mongodb_results(n):
|
|
294
299
|
# MongoDB already sorted by fitness DESC, so results[0] is best
|
|
295
300
|
x = np.array([[r["fitness"]] + [r["hyperparameters"][k] for k in self.space.keys()] for r in results])
|
|
296
|
-
|
|
301
|
+
elif self.collection.name in self.collection.database.list_collection_names(): # Tuner started elsewhere
|
|
302
|
+
x = np.array([[0.0] + [getattr(self.args, k) for k in self.space.keys()]])
|
|
297
303
|
|
|
298
304
|
# Fall back to CSV if MongoDB unavailable or empty
|
|
299
305
|
if x is None and self.tune_csv.exists():
|
|
300
306
|
csv_data = np.loadtxt(self.tune_csv, ndmin=2, delimiter=",", skiprows=1)
|
|
301
307
|
if len(csv_data) > 0:
|
|
302
308
|
fitness = csv_data[:, 0] # first column
|
|
303
|
-
|
|
304
|
-
x = csv_data[
|
|
309
|
+
order = np.argsort(-fitness)
|
|
310
|
+
x = csv_data[order][:n] # top-n sorted by fitness DESC
|
|
305
311
|
|
|
306
312
|
# Mutate if we have data, otherwise use defaults
|
|
307
313
|
if x is not None:
|
|
308
|
-
|
|
309
|
-
if parent == "single" or len(x) <= 1:
|
|
310
|
-
x = x[random.choices(range(n), weights=w)[0]] # weighted selection
|
|
311
|
-
elif parent == "weighted":
|
|
312
|
-
x = (x * w.reshape(n, 1)).sum(0) / w.sum() # weighted combination
|
|
313
|
-
|
|
314
|
-
# Mutate
|
|
315
|
-
r = np.random
|
|
316
|
-
r.seed(int(time.time()))
|
|
317
|
-
g = np.array([v[2] if len(v) == 3 else 1.0 for v in self.space.values()]) # gains 0-1
|
|
314
|
+
np.random.seed(int(time.time()))
|
|
318
315
|
ng = len(self.space)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
316
|
+
|
|
317
|
+
# Crossover
|
|
318
|
+
genes = self._crossover(x)
|
|
319
|
+
|
|
320
|
+
# Mutation
|
|
321
|
+
gains = np.array([v[2] if len(v) == 3 else 1.0 for v in self.space.values()]) # gains 0-1
|
|
322
|
+
factors = np.ones(ng)
|
|
323
|
+
while np.all(factors == 1): # mutate until a change occurs (prevent duplicates)
|
|
324
|
+
mask = np.random.random(ng) < mutation
|
|
325
|
+
step = np.random.randn(ng) * (sigma * gains)
|
|
326
|
+
factors = np.where(mask, np.exp(step), 1.0).clip(0.25, 4.0)
|
|
327
|
+
hyp = {k: float(genes[i] * factors[i]) for i, k in enumerate(self.space.keys())}
|
|
323
328
|
else:
|
|
324
329
|
hyp = {k: getattr(self.args, k) for k in self.space.keys()}
|
|
325
330
|
|
|
326
331
|
# Constrain to limits
|
|
327
332
|
for k, bounds in self.space.items():
|
|
328
|
-
hyp[k] = max(hyp[k], bounds[0])
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
hyp[k] = round(min(max(hyp[k], bounds[0]), bounds[1]), 5)
|
|
334
|
+
|
|
335
|
+
# Update types
|
|
336
|
+
if "close_mosaic" in hyp:
|
|
337
|
+
hyp["close_mosaic"] = round(hyp["close_mosaic"])
|
|
331
338
|
|
|
332
339
|
return hyp
|
|
333
340
|
|
|
334
341
|
def __call__(self, model=None, iterations: int = 10, cleanup: bool = True):
|
|
335
|
-
"""
|
|
336
|
-
Execute the hyperparameter evolution process when the Tuner instance is called.
|
|
342
|
+
"""Execute the hyperparameter evolution process when the Tuner instance is called.
|
|
337
343
|
|
|
338
344
|
This method iterates through the specified number of iterations, performing the following steps:
|
|
339
345
|
1. Sync MongoDB results to CSV (if using distributed mode)
|
|
@@ -361,8 +367,12 @@ class Tuner:
|
|
|
361
367
|
start = x.shape[0]
|
|
362
368
|
LOGGER.info(f"{self.prefix}Resuming tuning run {self.tune_dir} from iteration {start + 1}...")
|
|
363
369
|
for i in range(start, iterations):
|
|
370
|
+
# Linearly decay sigma from 0.2 → 0.1 over first 300 iterations
|
|
371
|
+
frac = min(i / 300.0, 1.0)
|
|
372
|
+
sigma_i = 0.2 - 0.1 * frac
|
|
373
|
+
|
|
364
374
|
# Mutate hyperparameters
|
|
365
|
-
mutated_hyp = self._mutate()
|
|
375
|
+
mutated_hyp = self._mutate(sigma=sigma_i)
|
|
366
376
|
LOGGER.info(f"{self.prefix}Starting iteration {i + 1}/{iterations} with hyperparameters: {mutated_hyp}")
|
|
367
377
|
|
|
368
378
|
metrics = {}
|
|
@@ -378,6 +388,11 @@ class Tuner:
|
|
|
378
388
|
metrics = torch_load(ckpt_file)["train_metrics"]
|
|
379
389
|
assert return_code == 0, "training failed"
|
|
380
390
|
|
|
391
|
+
# Cleanup
|
|
392
|
+
time.sleep(1)
|
|
393
|
+
gc.collect()
|
|
394
|
+
torch.cuda.empty_cache()
|
|
395
|
+
|
|
381
396
|
except Exception as e:
|
|
382
397
|
LOGGER.error(f"training failure for hyperparameter tuning iteration {i + 1}\n{e}")
|
|
383
398
|
|
|
@@ -395,7 +410,7 @@ class Tuner:
|
|
|
395
410
|
else:
|
|
396
411
|
# Save to CSV only if no MongoDB
|
|
397
412
|
log_row = [round(fitness, 5)] + [mutated_hyp[k] for k in self.space.keys()]
|
|
398
|
-
headers = "" if self.tune_csv.exists() else (",".join(["fitness"
|
|
413
|
+
headers = "" if self.tune_csv.exists() else (",".join(["fitness", *list(self.space.keys())]) + "\n")
|
|
399
414
|
with open(self.tune_csv, "a", encoding="utf-8") as f:
|
|
400
415
|
f.write(headers + ",".join(map(str, log_row)) + "\n")
|
|
401
416
|
|
|
@@ -405,12 +420,12 @@ class Tuner:
|
|
|
405
420
|
best_idx = fitness.argmax()
|
|
406
421
|
best_is_current = best_idx == i
|
|
407
422
|
if best_is_current:
|
|
408
|
-
best_save_dir = save_dir
|
|
423
|
+
best_save_dir = str(save_dir)
|
|
409
424
|
best_metrics = {k: round(v, 5) for k, v in metrics.items()}
|
|
410
425
|
for ckpt in weights_dir.glob("*.pt"):
|
|
411
426
|
shutil.copy2(ckpt, self.tune_dir / "weights")
|
|
412
|
-
elif cleanup:
|
|
413
|
-
shutil.rmtree(
|
|
427
|
+
elif cleanup and best_save_dir:
|
|
428
|
+
shutil.rmtree(best_save_dir, ignore_errors=True) # remove iteration dirs to reduce storage space
|
|
414
429
|
|
|
415
430
|
# Plot tune results
|
|
416
431
|
plot_tune_results(str(self.tune_csv))
|
|
@@ -421,8 +436,7 @@ class Tuner:
|
|
|
421
436
|
f"{self.prefix}Results saved to {colorstr('bold', self.tune_dir)}\n"
|
|
422
437
|
f"{self.prefix}Best fitness={fitness[best_idx]} observed at iteration {best_idx + 1}\n"
|
|
423
438
|
f"{self.prefix}Best fitness metrics are {best_metrics}\n"
|
|
424
|
-
f"{self.prefix}Best fitness model is {best_save_dir}
|
|
425
|
-
f"{self.prefix}Best fitness hyperparameters are printed below.\n"
|
|
439
|
+
f"{self.prefix}Best fitness model is {best_save_dir}"
|
|
426
440
|
)
|
|
427
441
|
LOGGER.info("\n" + header)
|
|
428
442
|
data = {k: float(x[best_idx, i + 1]) for i, k in enumerate(self.space.keys())}
|
ultralytics/engine/validator.py
CHANGED
|
@@ -29,26 +29,26 @@ from pathlib import Path
|
|
|
29
29
|
|
|
30
30
|
import numpy as np
|
|
31
31
|
import torch
|
|
32
|
+
import torch.distributed as dist
|
|
32
33
|
|
|
33
34
|
from ultralytics.cfg import get_cfg, get_save_dir
|
|
34
35
|
from ultralytics.data.utils import check_cls_dataset, check_det_dataset
|
|
35
36
|
from ultralytics.nn.autobackend import AutoBackend
|
|
36
|
-
from ultralytics.utils import LOGGER, TQDM, callbacks, colorstr, emojis
|
|
37
|
+
from ultralytics.utils import LOGGER, RANK, TQDM, callbacks, colorstr, emojis
|
|
37
38
|
from ultralytics.utils.checks import check_imgsz
|
|
38
39
|
from ultralytics.utils.ops import Profile
|
|
39
40
|
from ultralytics.utils.torch_utils import attempt_compile, select_device, smart_inference_mode, unwrap_model
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
class BaseValidator:
|
|
43
|
-
"""
|
|
44
|
-
A base class for creating validators.
|
|
44
|
+
"""A base class for creating validators.
|
|
45
45
|
|
|
46
46
|
This class provides the foundation for validation processes, including model evaluation, metric computation, and
|
|
47
47
|
result visualization.
|
|
48
48
|
|
|
49
49
|
Attributes:
|
|
50
50
|
args (SimpleNamespace): Configuration for the validator.
|
|
51
|
-
dataloader (DataLoader):
|
|
51
|
+
dataloader (DataLoader): DataLoader to use for validation.
|
|
52
52
|
model (nn.Module): Model to validate.
|
|
53
53
|
data (dict): Data dictionary containing dataset information.
|
|
54
54
|
device (torch.device): Device to use for validation.
|
|
@@ -61,8 +61,8 @@ class BaseValidator:
|
|
|
61
61
|
nc (int): Number of classes.
|
|
62
62
|
iouv (torch.Tensor): IoU thresholds from 0.50 to 0.95 in spaces of 0.05.
|
|
63
63
|
jdict (list): List to store JSON validation results.
|
|
64
|
-
speed (dict): Dictionary with keys 'preprocess', 'inference', 'loss', 'postprocess' and their respective
|
|
65
|
-
|
|
64
|
+
speed (dict): Dictionary with keys 'preprocess', 'inference', 'loss', 'postprocess' and their respective batch
|
|
65
|
+
processing times in milliseconds.
|
|
66
66
|
save_dir (Path): Directory to save results.
|
|
67
67
|
plots (dict): Dictionary to store plots for visualization.
|
|
68
68
|
callbacks (dict): Dictionary to store various callback functions.
|
|
@@ -92,11 +92,10 @@ class BaseValidator:
|
|
|
92
92
|
"""
|
|
93
93
|
|
|
94
94
|
def __init__(self, dataloader=None, save_dir=None, args=None, _callbacks=None):
|
|
95
|
-
"""
|
|
96
|
-
Initialize a BaseValidator instance.
|
|
95
|
+
"""Initialize a BaseValidator instance.
|
|
97
96
|
|
|
98
97
|
Args:
|
|
99
|
-
dataloader (torch.utils.data.DataLoader, optional):
|
|
98
|
+
dataloader (torch.utils.data.DataLoader, optional): DataLoader to be used for validation.
|
|
100
99
|
save_dir (Path, optional): Directory to save results.
|
|
101
100
|
args (SimpleNamespace, optional): Configuration for the validator.
|
|
102
101
|
_callbacks (dict, optional): Dictionary to store various callback functions.
|
|
@@ -130,8 +129,7 @@ class BaseValidator:
|
|
|
130
129
|
|
|
131
130
|
@smart_inference_mode()
|
|
132
131
|
def __call__(self, trainer=None, model=None):
|
|
133
|
-
"""
|
|
134
|
-
Execute validation process, running inference on dataloader and computing performance metrics.
|
|
132
|
+
"""Execute validation process, running inference on dataloader and computing performance metrics.
|
|
135
133
|
|
|
136
134
|
Args:
|
|
137
135
|
trainer (object, optional): Trainer object that contains the model to validate.
|
|
@@ -160,7 +158,7 @@ class BaseValidator:
|
|
|
160
158
|
callbacks.add_integration_callbacks(self)
|
|
161
159
|
model = AutoBackend(
|
|
162
160
|
model=model or self.args.model,
|
|
163
|
-
device=select_device(self.args.device,
|
|
161
|
+
device=select_device(self.args.device) if RANK == -1 else torch.device("cuda", RANK),
|
|
164
162
|
dnn=self.args.dnn,
|
|
165
163
|
data=self.args.data,
|
|
166
164
|
fp16=self.args.half,
|
|
@@ -223,21 +221,34 @@ class BaseValidator:
|
|
|
223
221
|
preds = self.postprocess(preds)
|
|
224
222
|
|
|
225
223
|
self.update_metrics(preds, batch)
|
|
226
|
-
if self.args.plots and batch_i < 3:
|
|
224
|
+
if self.args.plots and batch_i < 3 and RANK in {-1, 0}:
|
|
227
225
|
self.plot_val_samples(batch, batch_i)
|
|
228
226
|
self.plot_predictions(batch, preds, batch_i)
|
|
229
227
|
|
|
230
228
|
self.run_callbacks("on_val_batch_end")
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
self.
|
|
234
|
-
|
|
235
|
-
|
|
229
|
+
|
|
230
|
+
stats = {}
|
|
231
|
+
self.gather_stats()
|
|
232
|
+
if RANK in {-1, 0}:
|
|
233
|
+
stats = self.get_stats()
|
|
234
|
+
self.speed = dict(zip(self.speed.keys(), (x.t / len(self.dataloader.dataset) * 1e3 for x in dt)))
|
|
235
|
+
self.finalize_metrics()
|
|
236
|
+
self.print_results()
|
|
237
|
+
self.run_callbacks("on_val_end")
|
|
238
|
+
|
|
236
239
|
if self.training:
|
|
237
240
|
model.float()
|
|
238
|
-
|
|
241
|
+
# Reduce loss across all GPUs
|
|
242
|
+
loss = self.loss.clone().detach()
|
|
243
|
+
if trainer.world_size > 1:
|
|
244
|
+
dist.reduce(loss, dst=0, op=dist.ReduceOp.AVG)
|
|
245
|
+
if RANK > 0:
|
|
246
|
+
return
|
|
247
|
+
results = {**stats, **trainer.label_loss_items(loss.cpu() / len(self.dataloader), prefix="val")}
|
|
239
248
|
return {k: round(float(v), 5) for k, v in results.items()} # return results as 5 decimal place floats
|
|
240
249
|
else:
|
|
250
|
+
if RANK > 0:
|
|
251
|
+
return stats
|
|
241
252
|
LOGGER.info(
|
|
242
253
|
"Speed: {:.1f}ms preprocess, {:.1f}ms inference, {:.1f}ms loss, {:.1f}ms postprocess per image".format(
|
|
243
254
|
*tuple(self.speed.values())
|
|
@@ -255,8 +266,7 @@ class BaseValidator:
|
|
|
255
266
|
def match_predictions(
|
|
256
267
|
self, pred_classes: torch.Tensor, true_classes: torch.Tensor, iou: torch.Tensor, use_scipy: bool = False
|
|
257
268
|
) -> torch.Tensor:
|
|
258
|
-
"""
|
|
259
|
-
Match predictions to ground truth objects using IoU.
|
|
269
|
+
"""Match predictions to ground truth objects using IoU.
|
|
260
270
|
|
|
261
271
|
Args:
|
|
262
272
|
pred_classes (torch.Tensor): Predicted class indices of shape (N,).
|
|
@@ -336,6 +346,10 @@ class BaseValidator:
|
|
|
336
346
|
"""Return statistics about the model's performance."""
|
|
337
347
|
return {}
|
|
338
348
|
|
|
349
|
+
def gather_stats(self):
|
|
350
|
+
"""Gather statistics from all the GPUs during DDP training to GPU 0."""
|
|
351
|
+
pass
|
|
352
|
+
|
|
339
353
|
def print_results(self):
|
|
340
354
|
"""Print the results of the model's predictions."""
|
|
341
355
|
pass
|
|
@@ -350,7 +364,10 @@ class BaseValidator:
|
|
|
350
364
|
return []
|
|
351
365
|
|
|
352
366
|
def on_plot(self, name, data=None):
|
|
353
|
-
"""Register plots for visualization."""
|
|
367
|
+
"""Register plots for visualization, deduplicating by type."""
|
|
368
|
+
plot_type = data.get("type") if data else None
|
|
369
|
+
if plot_type and any((v.get("data") or {}).get("type") == plot_type for v in self.plots.values()):
|
|
370
|
+
return # Skip duplicate plot types
|
|
354
371
|
self.plots[Path(name)] = {"data": data, "timestamp": time.time()}
|
|
355
372
|
|
|
356
373
|
def plot_val_samples(self, batch, ni):
|
ultralytics/hub/__init__.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
from ultralytics.data.utils import HUBDatasetStats
|
|
4
6
|
from ultralytics.hub.auth import Auth
|
|
5
7
|
from ultralytics.hub.session import HUBTrainingSession
|
|
@@ -7,29 +9,28 @@ from ultralytics.hub.utils import HUB_API_ROOT, HUB_WEB_ROOT, PREFIX
|
|
|
7
9
|
from ultralytics.utils import LOGGER, SETTINGS, checks
|
|
8
10
|
|
|
9
11
|
__all__ = (
|
|
10
|
-
"PREFIX",
|
|
11
12
|
"HUB_WEB_ROOT",
|
|
13
|
+
"PREFIX",
|
|
12
14
|
"HUBTrainingSession",
|
|
13
|
-
"
|
|
14
|
-
"logout",
|
|
15
|
-
"reset_model",
|
|
15
|
+
"check_dataset",
|
|
16
16
|
"export_fmts_hub",
|
|
17
17
|
"export_model",
|
|
18
18
|
"get_export",
|
|
19
|
-
"
|
|
19
|
+
"login",
|
|
20
|
+
"logout",
|
|
21
|
+
"reset_model",
|
|
20
22
|
)
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
def login(api_key: str = None, save: bool = True) -> bool:
|
|
24
|
-
"""
|
|
25
|
-
Log in to the Ultralytics HUB API using the provided API key.
|
|
25
|
+
def login(api_key: str | None = None, save: bool = True) -> bool:
|
|
26
|
+
"""Log in to the Ultralytics HUB API using the provided API key.
|
|
26
27
|
|
|
27
28
|
The session is not stored; a new session is created when needed using the saved SETTINGS or the HUB_API_KEY
|
|
28
29
|
environment variable if successfully authenticated.
|
|
29
30
|
|
|
30
31
|
Args:
|
|
31
|
-
api_key (str, optional): API key to use for authentication. If not provided, it will be retrieved from
|
|
32
|
-
|
|
32
|
+
api_key (str, optional): API key to use for authentication. If not provided, it will be retrieved from SETTINGS
|
|
33
|
+
or HUB_API_KEY environment variable.
|
|
33
34
|
save (bool, optional): Whether to save the API key to SETTINGS if authentication is successful.
|
|
34
35
|
|
|
35
36
|
Returns:
|
|
@@ -85,12 +86,11 @@ def export_fmts_hub():
|
|
|
85
86
|
"""Return a list of HUB-supported export formats."""
|
|
86
87
|
from ultralytics.engine.exporter import export_formats
|
|
87
88
|
|
|
88
|
-
return list(export_formats()["Argument"][1:])
|
|
89
|
+
return [*list(export_formats()["Argument"][1:]), "ultralytics_tflite", "ultralytics_coreml"]
|
|
89
90
|
|
|
90
91
|
|
|
91
92
|
def export_model(model_id: str = "", format: str = "torchscript"):
|
|
92
|
-
"""
|
|
93
|
-
Export a model to a specified format for deployment via the Ultralytics HUB API.
|
|
93
|
+
"""Export a model to a specified format for deployment via the Ultralytics HUB API.
|
|
94
94
|
|
|
95
95
|
Args:
|
|
96
96
|
model_id (str): The ID of the model to export. An empty string will use the default model.
|
|
@@ -115,13 +115,11 @@ def export_model(model_id: str = "", format: str = "torchscript"):
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
def get_export(model_id: str = "", format: str = "torchscript"):
|
|
118
|
-
"""
|
|
119
|
-
Retrieve an exported model in the specified format from Ultralytics HUB using the model ID.
|
|
118
|
+
"""Retrieve an exported model in the specified format from Ultralytics HUB using the model ID.
|
|
120
119
|
|
|
121
120
|
Args:
|
|
122
121
|
model_id (str): The ID of the model to retrieve from Ultralytics HUB.
|
|
123
|
-
format (str): The export format to retrieve. Must be one of the supported formats returned by
|
|
124
|
-
export_fmts_hub().
|
|
122
|
+
format (str): The export format to retrieve. Must be one of the supported formats returned by export_fmts_hub().
|
|
125
123
|
|
|
126
124
|
Returns:
|
|
127
125
|
(dict): JSON response containing the exported model information.
|
|
@@ -146,8 +144,7 @@ def get_export(model_id: str = "", format: str = "torchscript"):
|
|
|
146
144
|
|
|
147
145
|
|
|
148
146
|
def check_dataset(path: str, task: str) -> None:
|
|
149
|
-
"""
|
|
150
|
-
Check HUB dataset Zip file for errors before upload.
|
|
147
|
+
"""Check HUB dataset Zip file for errors before upload.
|
|
151
148
|
|
|
152
149
|
Args:
|
|
153
150
|
path (str): Path to data.zip (with data.yaml inside data.zip).
|
ultralytics/hub/auth.py
CHANGED
|
@@ -7,8 +7,7 @@ API_KEY_URL = f"{HUB_WEB_ROOT}/settings?tab=api+keys"
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Auth:
|
|
10
|
-
"""
|
|
11
|
-
Manages authentication processes including API key handling, cookie-based authentication, and header generation.
|
|
10
|
+
"""Manages authentication processes including API key handling, cookie-based authentication, and header generation.
|
|
12
11
|
|
|
13
12
|
The class supports different methods of authentication:
|
|
14
13
|
1. Directly using an API key.
|
|
@@ -37,8 +36,7 @@ class Auth:
|
|
|
37
36
|
id_token = api_key = model_key = False
|
|
38
37
|
|
|
39
38
|
def __init__(self, api_key: str = "", verbose: bool = False):
|
|
40
|
-
"""
|
|
41
|
-
Initialize Auth class and authenticate user.
|
|
39
|
+
"""Initialize Auth class and authenticate user.
|
|
42
40
|
|
|
43
41
|
Handles API key validation, Google Colab authentication, and new key requests. Updates SETTINGS upon successful
|
|
44
42
|
authentication.
|
|
@@ -82,8 +80,7 @@ class Auth:
|
|
|
82
80
|
LOGGER.info(f"{PREFIX}Get API key from {API_KEY_URL} and then run 'yolo login API_KEY'")
|
|
83
81
|
|
|
84
82
|
def request_api_key(self, max_attempts: int = 3) -> bool:
|
|
85
|
-
"""
|
|
86
|
-
Prompt the user to input their API key.
|
|
83
|
+
"""Prompt the user to input their API key.
|
|
87
84
|
|
|
88
85
|
Args:
|
|
89
86
|
max_attempts (int): Maximum number of authentication attempts.
|
|
@@ -102,8 +99,7 @@ class Auth:
|
|
|
102
99
|
raise ConnectionError(emojis(f"{PREFIX}Failed to authenticate ❌"))
|
|
103
100
|
|
|
104
101
|
def authenticate(self) -> bool:
|
|
105
|
-
"""
|
|
106
|
-
Attempt to authenticate with the server using either id_token or API key.
|
|
102
|
+
"""Attempt to authenticate with the server using either id_token or API key.
|
|
107
103
|
|
|
108
104
|
Returns:
|
|
109
105
|
(bool): True if authentication is successful, False otherwise.
|
|
@@ -123,8 +119,7 @@ class Auth:
|
|
|
123
119
|
return False
|
|
124
120
|
|
|
125
121
|
def auth_with_cookies(self) -> bool:
|
|
126
|
-
"""
|
|
127
|
-
Attempt to fetch authentication via cookies and set id_token.
|
|
122
|
+
"""Attempt to fetch authentication via cookies and set id_token.
|
|
128
123
|
|
|
129
124
|
User must be logged in to HUB and running in a supported browser.
|
|
130
125
|
|
|
@@ -145,8 +140,7 @@ class Auth:
|
|
|
145
140
|
return False
|
|
146
141
|
|
|
147
142
|
def get_auth_header(self):
|
|
148
|
-
"""
|
|
149
|
-
Get the authentication header for making API requests.
|
|
143
|
+
"""Get the authentication header for making API requests.
|
|
150
144
|
|
|
151
145
|
Returns:
|
|
152
146
|
(dict | None): The authentication header if id_token or API key is set, None otherwise.
|
|
@@ -8,11 +8,10 @@ import time
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class GCPRegions:
|
|
11
|
-
"""
|
|
12
|
-
A class for managing and analyzing Google Cloud Platform (GCP) regions.
|
|
11
|
+
"""A class for managing and analyzing Google Cloud Platform (GCP) regions.
|
|
13
12
|
|
|
14
|
-
This class provides functionality to initialize, categorize, and analyze GCP regions based on their
|
|
15
|
-
|
|
13
|
+
This class provides functionality to initialize, categorize, and analyze GCP regions based on their geographical
|
|
14
|
+
location, tier classification, and network latency.
|
|
16
15
|
|
|
17
16
|
Attributes:
|
|
18
17
|
regions (dict[str, tuple[int, str, str]]): A dictionary of GCP regions with their tier, city, and country.
|
|
@@ -82,8 +81,7 @@ class GCPRegions:
|
|
|
82
81
|
|
|
83
82
|
@staticmethod
|
|
84
83
|
def _ping_region(region: str, attempts: int = 1) -> tuple[str, float, float, float, float]:
|
|
85
|
-
"""
|
|
86
|
-
Ping a specified GCP region and measure network latency statistics.
|
|
84
|
+
"""Ping a specified GCP region and measure network latency statistics.
|
|
87
85
|
|
|
88
86
|
Args:
|
|
89
87
|
region (str): The GCP region identifier to ping (e.g., 'us-central1').
|
|
@@ -126,8 +124,7 @@ class GCPRegions:
|
|
|
126
124
|
tier: int | None = None,
|
|
127
125
|
attempts: int = 1,
|
|
128
126
|
) -> list[tuple[str, float, float, float, float]]:
|
|
129
|
-
"""
|
|
130
|
-
Determine the GCP regions with the lowest latency based on ping tests.
|
|
127
|
+
"""Determine the GCP regions with the lowest latency based on ping tests.
|
|
131
128
|
|
|
132
129
|
Args:
|
|
133
130
|
top (int, optional): Number of top regions to return.
|
|
@@ -136,8 +133,8 @@ class GCPRegions:
|
|
|
136
133
|
attempts (int, optional): Number of ping attempts per region.
|
|
137
134
|
|
|
138
135
|
Returns:
|
|
139
|
-
(list[tuple[str, float, float, float, float]]): List of tuples containing region information and
|
|
140
|
-
|
|
136
|
+
(list[tuple[str, float, float, float, float]]): List of tuples containing region information and latency
|
|
137
|
+
statistics. Each tuple contains (region, mean_latency, std_dev, min_latency, max_latency).
|
|
141
138
|
|
|
142
139
|
Examples:
|
|
143
140
|
>>> regions = GCPRegions()
|