mirror of
https://github.com/ultralytics/ultralytics
synced 2026-04-21 14:07:18 +00:00
ultralytics 8.4.27 Improved Platform training integration (#24008)
Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com> Co-authored-by: UltralyticsAssistant <web@ultralytics.com>
This commit is contained in:
parent
a630384aa7
commit
8d8358767f
5 changed files with 40 additions and 11 deletions
|
|
@ -23,6 +23,10 @@ keywords: platform callbacks, training callbacks, console logging, YOLO11 traini
|
|||
|
||||
<br><br><hr><br>
|
||||
|
||||
## ::: ultralytics.utils.callbacks.platform._sanitize_json_value
|
||||
|
||||
<br><br><hr><br>
|
||||
|
||||
## ::: ultralytics.utils.callbacks.platform._send
|
||||
|
||||
<br><br><hr><br>
|
||||
|
|
@ -31,6 +35,10 @@ keywords: platform callbacks, training callbacks, console logging, YOLO11 traini
|
|||
|
||||
<br><br><hr><br>
|
||||
|
||||
## ::: ultralytics.utils.callbacks.platform._handle_control_response
|
||||
|
||||
<br><br><hr><br>
|
||||
|
||||
## ::: ultralytics.utils.callbacks.platform._upload_model
|
||||
|
||||
<br><br><hr><br>
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@
|
|||
| `device` | `str` | `None` | Specifies the device for exporting: GPU (`device=0`), CPU (`device=cpu`), MPS for Apple silicon (`device=mps`), Huawei Ascend NPU (`device=npu` or `device=npu:0`), or DLA for NVIDIA Jetson (`device=dla:0` or `device=dla:1`). TensorRT exports automatically use GPU. |
|
||||
| `data` | `str` | `'coco8.yaml'` | Path to the [dataset](https://docs.ultralytics.com/datasets/) configuration file, essential for INT8 quantization calibration. If not specified with INT8 enabled, `coco8.yaml` will be used as a fallback for calibration. |
|
||||
| `fraction` | `float` | `1.0` | Specifies the fraction of the dataset to use for INT8 quantization calibration. Allows for calibrating on a subset of the full dataset, useful for experiments or when resources are limited. If not specified with INT8 enabled, the full dataset will be used. |
|
||||
| `end2end` | `bool` | `None` | Overrides the end-to-end mode in YOLO models that support NMS-free inference (YOLO26, YOLOv10). Setting it to `False` lets you export these models to be compatible with the traditional NMS-based postprocessing pipeline. See the [End-to-End Detection guide](../guides/end2end-detection.md) for details. |
|
||||
| `end2end` | `bool` | `None` | Overrides the end-to-end mode in YOLO models that support NMS-free inference (YOLO26, YOLOv10). Setting it to `False` lets you export these models to be compatible with the traditional NMS-based postprocessing pipeline. See the [End-to-End Detection guide](../guides/end2end-detection.md) for details. |
|
||||
|
|
|
|||
|
|
@ -22,4 +22,4 @@
|
|||
| `stream` | `bool` | `False` | Enables memory-efficient processing for long videos or numerous images by returning a generator of Results objects instead of loading all frames into memory at once. |
|
||||
| `verbose` | `bool` | `True` | Controls whether to display detailed inference logs in the terminal, providing real-time feedback on the prediction process. |
|
||||
| `compile` | `bool` or `str` | `False` | Enables PyTorch 2.x `torch.compile` graph compilation with `backend='inductor'`. Accepts `True` → `"default"`, `False` → disables, or a string mode such as `"default"`, `"reduce-overhead"`, `"max-autotune-no-cudagraphs"`. Falls back to eager with a warning if unsupported. |
|
||||
| `end2end` | `bool` | `None` | Overrides the end-to-end mode in YOLO models that support NMS-free inference (YOLO26, YOLOv10). Setting it to `False` lets you run prediction using the traditional NMS pipeline, additionally allowing you to make use of the `iou` argument. See the [End-to-End Detection guide](../guides/end2end-detection.md) for details. |
|
||||
| `end2end` | `bool` | `None` | Overrides the end-to-end mode in YOLO models that support NMS-free inference (YOLO26, YOLOv10). Setting it to `False` lets you run prediction using the traditional NMS pipeline, additionally allowing you to make use of the `iou` argument. See the [End-to-End Detection guide](../guides/end2end-detection.md) for details. |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
__version__ = "8.4.26"
|
||||
__version__ = "8.4.27"
|
||||
|
||||
import importlib
|
||||
import os
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import re
|
|||
import socket
|
||||
import sys
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from math import isfinite
|
||||
from pathlib import Path
|
||||
from time import sleep, time
|
||||
|
||||
|
|
@ -157,9 +158,20 @@ def _interp_plot(plot, n=101):
|
|||
return result
|
||||
|
||||
|
||||
def _sanitize_json_value(value):
|
||||
"""Replace non-finite floats in payloads with None so requests JSON encoding succeeds."""
|
||||
if isinstance(value, dict):
|
||||
return {k: _sanitize_json_value(v) for k, v in value.items()}
|
||||
if isinstance(value, (list, tuple)):
|
||||
return [_sanitize_json_value(v) for v in value]
|
||||
if isinstance(value, float):
|
||||
return value if isfinite(value) else None # avoid "Out of range float values are not JSON compliant" warnings
|
||||
return value
|
||||
|
||||
|
||||
def _send(event, data, project, name, model_id=None, retry=2):
|
||||
"""Send event to Platform endpoint with retry logic."""
|
||||
payload = {"event": event, "project": project, "name": name, "data": data}
|
||||
payload = {"event": event, "project": project, "name": name, "data": _sanitize_json_value(data)}
|
||||
if model_id:
|
||||
payload["modelId"] = model_id
|
||||
|
||||
|
|
@ -193,6 +205,20 @@ def _send_async(event, data, project, name, model_id=None):
|
|||
_executor.submit(_send, event, data, project, name, model_id)
|
||||
|
||||
|
||||
def _handle_control_response(trainer, ctx, response):
|
||||
"""Apply centralized stop signals returned by Platform webhook responses.
|
||||
|
||||
Notes:
|
||||
``ctx["cancelled"]`` is the durable cancellation signal. During startup, trainer setup later resets
|
||||
``trainer.stop``, so early stop requests still rely on ``on_pretrain_routine_end()`` to reapply the flag after
|
||||
setup completes.
|
||||
"""
|
||||
if response and response.get("cancelled"):
|
||||
ctx["cancelled"] = True
|
||||
trainer.stop = True
|
||||
LOGGER.info(f"{PREFIX}Training cancelled from Platform ⚠️")
|
||||
|
||||
|
||||
def _upload_model(model_path, project, name, progress=False, retry=1, model_id=None):
|
||||
"""Upload model checkpoint to Platform via signed URL."""
|
||||
from ultralytics.utils.uploads import safe_upload
|
||||
|
|
@ -347,10 +373,8 @@ def on_pretrain_routine_start(trainer):
|
|||
ctx["model_slug"] = response["modelSlug"]
|
||||
url = f"{PLATFORM_URL}/{project}/{ctx['model_slug']}"
|
||||
LOGGER.info(f"{PREFIX}View model at {url}")
|
||||
# Check for immediate cancellation (cancelled before training started)
|
||||
# Note: trainer.stop is set in on_pretrain_routine_end (after _setup_train resets it)
|
||||
if response.get("cancelled"):
|
||||
ctx["cancelled"] = True
|
||||
_handle_control_response(trainer, ctx, response)
|
||||
else:
|
||||
LOGGER.warning(f"{PREFIX}Training will not be tracked on Platform")
|
||||
trainer.platform = None # Disable further callbacks
|
||||
|
|
@ -411,10 +435,7 @@ def on_fit_epoch_end(trainer):
|
|||
def _send_and_check_cancel():
|
||||
"""Send epoch_end and check response for cancellation (runs in background thread)."""
|
||||
response = _send("epoch_end", payload, project, name, ctx["model_id"], retry=1)
|
||||
if response and response.get("cancelled"):
|
||||
LOGGER.info(f"{PREFIX}Training cancelled from Platform ✅")
|
||||
trainer.stop = True
|
||||
ctx["cancelled"] = True
|
||||
_handle_control_response(trainer, ctx, response)
|
||||
|
||||
_executor.submit(_send_and_check_cancel)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue