mirror of
https://github.com/THU-MIG/yolov10.git
synced 2025-05-23 21:44:22 +08:00
ultralytics 8.0.181
RTDETR, MLFlow fixes and Examples updates (#4927)
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Jordane Sikati <jordanesikati@pusan.ac.kr> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Akash A Desai <62583018+akashAD98@users.noreply.github.com> Co-authored-by: Lukas Hennies <45569834+Gornoka@users.noreply.github.com> Co-authored-by: 唐洁 <tangjie1953479@tongji.edu.cn>
This commit is contained in:
parent
5702b2dccd
commit
742ec7fb1d
@ -2,7 +2,6 @@ include *.md
|
|||||||
include requirements.txt
|
include requirements.txt
|
||||||
include LICENSE
|
include LICENSE
|
||||||
include setup.py
|
include setup.py
|
||||||
recursive-exclude __pycache__ *
|
|
||||||
include ultralytics/assets/bus.jpg
|
include ultralytics/assets/bus.jpg
|
||||||
include ultralytics/assets/zidane.jpg
|
include ultralytics/assets/zidane.jpg
|
||||||
recursive-include ultralytics *.yaml
|
recursive-include ultralytics *.yaml
|
||||||
|
@ -83,6 +83,7 @@ Without further ado, let's dive in!
|
|||||||
3. Now, read the contents of the dataset YAML file and extract the indices of the class labels.
|
3. Now, read the contents of the dataset YAML file and extract the indices of the class labels.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
yaml_file = 'path/to/data.yaml' # your data YAML with data directories and names dictionary
|
||||||
with open(yaml_file, 'r', encoding="utf8") as y:
|
with open(yaml_file, 'r', encoding="utf8") as y:
|
||||||
classes = yaml.safe_load(y)['names']
|
classes = yaml.safe_load(y)['names']
|
||||||
cls_idx = sorted(classes.keys())
|
cls_idx = sorted(classes.keys())
|
||||||
@ -177,10 +178,18 @@ The ideal scenario is for all class ratios to be reasonably similar for each spl
|
|||||||
4. Next, we create the directories and dataset YAML files for each split.
|
4. Next, we create the directories and dataset YAML files for each split.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
supported_extensions = ['.jpg', '.jpeg', '.png']
|
||||||
|
|
||||||
|
# Initialize an empty list to store image file paths
|
||||||
|
images = []
|
||||||
|
|
||||||
|
# Loop through supported extensions and gather image files
|
||||||
|
for ext in supported_extensions:
|
||||||
|
images.extend(sorted((dataset_path / 'images').rglob(f"*{ext}")))
|
||||||
|
|
||||||
|
# Create the necessary directories and dataset YAML files (unchanged)
|
||||||
save_path = Path(dataset_path / f'{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val')
|
save_path = Path(dataset_path / f'{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val')
|
||||||
save_path.mkdir(parents=True, exist_ok=True)
|
save_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
images = sorted((dataset_path / 'images').rglob("*.jpg")) # change file extension as needed
|
|
||||||
ds_yamls = []
|
ds_yamls = []
|
||||||
|
|
||||||
for split in folds_df.columns:
|
for split in folds_df.columns:
|
||||||
@ -216,8 +225,7 @@ The ideal scenario is for all class ratios to be reasonably similar for each spl
|
|||||||
img_to_path = save_path / split / k_split / 'images'
|
img_to_path = save_path / split / k_split / 'images'
|
||||||
lbl_to_path = save_path / split / k_split / 'labels'
|
lbl_to_path = save_path / split / k_split / 'labels'
|
||||||
|
|
||||||
# Copy image and label files to new directory
|
# Copy image and label files to new directory (SamefileError if file already exists)
|
||||||
# Might throw a SamefileError if file already exists
|
|
||||||
shutil.copy(image, img_to_path / image.name)
|
shutil.copy(image, img_to_path / image.name)
|
||||||
shutil.copy(label, lbl_to_path / label.name)
|
shutil.copy(label, lbl_to_path / label.name)
|
||||||
```
|
```
|
||||||
@ -244,9 +252,15 @@ fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
|
# Define your additional arguments here
|
||||||
|
batch = 16
|
||||||
|
project = 'kfold_demo'
|
||||||
|
epochs = 100
|
||||||
|
|
||||||
for k in range(ksplit):
|
for k in range(ksplit):
|
||||||
dataset_yaml = ds_yamls[k]
|
dataset_yaml = ds_yamls[k]
|
||||||
model.train(data=dataset_yaml, *args, **kwargs) # Include any training arguments
|
model.train(data=dataset_yaml,epochs=epochs, batch=batch, project=project) # include any train arguments
|
||||||
results[k] = model.metrics # save output metrics for further analysis
|
results[k] = model.metrics # save output metrics for further analysis
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Example: pip install -r requirements.txt
|
# Example: pip install -r requirements.txt
|
||||||
|
|
||||||
# Base ----------------------------------------
|
# Base ----------------------------------------
|
||||||
matplotlib>=3.2.2
|
matplotlib>=3.3.0
|
||||||
numpy>=1.22.2 # pinned by Snyk to avoid a vulnerability
|
numpy>=1.22.2 # pinned by Snyk to avoid a vulnerability
|
||||||
opencv-python>=4.6.0
|
opencv-python>=4.6.0
|
||||||
pillow>=7.1.2
|
pillow>=7.1.2
|
||||||
|
@ -6,7 +6,10 @@ from pathlib import Path
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ultralytics.utils import ASSETS, SETTINGS
|
from ultralytics.utils import ASSETS, SETTINGS
|
||||||
|
from ultralytics.utils.checks import cuda_device_count, cuda_is_available
|
||||||
|
|
||||||
|
CUDA_IS_AVAILABLE = cuda_is_available()
|
||||||
|
CUDA_DEVICE_COUNT = cuda_device_count()
|
||||||
WEIGHTS_DIR = Path(SETTINGS['weights_dir'])
|
WEIGHTS_DIR = Path(SETTINGS['weights_dir'])
|
||||||
TASK_ARGS = [
|
TASK_ARGS = [
|
||||||
('detect', 'yolov8n', 'coco8.yaml'),
|
('detect', 'yolov8n', 'coco8.yaml'),
|
||||||
@ -117,6 +120,8 @@ def test_mobilesam():
|
|||||||
# Slow Tests -----------------------------------------------------------------------------------------------------------
|
# Slow Tests -----------------------------------------------------------------------------------------------------------
|
||||||
@pytest.mark.slow
|
@pytest.mark.slow
|
||||||
@pytest.mark.parametrize('task,model,data', TASK_ARGS)
|
@pytest.mark.parametrize('task,model,data', TASK_ARGS)
|
||||||
|
@pytest.mark.skipif(not CUDA_IS_AVAILABLE, reason='CUDA is not available')
|
||||||
|
@pytest.mark.skipif(CUDA_DEVICE_COUNT < 2, reason='DDP is not available')
|
||||||
def test_train_gpu(task, model, data):
|
def test_train_gpu(task, model, data):
|
||||||
run(f'yolo train {task} model={model}.yaml data={data} imgsz=32 epochs=1 device=0') # single GPU
|
run(f'yolo train {task} model={model}.yaml data={data} imgsz=32 epochs=1 device=0') # single GPU
|
||||||
run(f'yolo train {task} model={model}.pt data={data} imgsz=32 epochs=1 device=0,1') # multi GPU
|
run(f'yolo train {task} model={model}.pt data={data} imgsz=32 epochs=1 device=0,1') # multi GPU
|
||||||
|
@ -7,9 +7,10 @@ import torch
|
|||||||
|
|
||||||
from ultralytics import YOLO, download
|
from ultralytics import YOLO, download
|
||||||
from ultralytics.utils import ASSETS, SETTINGS
|
from ultralytics.utils import ASSETS, SETTINGS
|
||||||
|
from ultralytics.utils.checks import cuda_device_count, cuda_is_available
|
||||||
|
|
||||||
CUDA_IS_AVAILABLE = torch.cuda.is_available()
|
CUDA_IS_AVAILABLE = cuda_is_available()
|
||||||
CUDA_DEVICE_COUNT = torch.cuda.device_count()
|
CUDA_DEVICE_COUNT = cuda_device_count()
|
||||||
|
|
||||||
DATASETS_DIR = Path(SETTINGS['datasets_dir'])
|
DATASETS_DIR = Path(SETTINGS['datasets_dir'])
|
||||||
WEIGHTS_DIR = Path(SETTINGS['weights_dir'])
|
WEIGHTS_DIR = Path(SETTINGS['weights_dir'])
|
||||||
@ -18,10 +19,8 @@ DATA = 'coco8.yaml'
|
|||||||
|
|
||||||
|
|
||||||
def test_checks():
|
def test_checks():
|
||||||
from ultralytics.utils.checks import cuda_device_count, cuda_is_available
|
assert torch.cuda.is_available() == CUDA_IS_AVAILABLE
|
||||||
|
assert torch.cuda.device_count() == CUDA_DEVICE_COUNT
|
||||||
assert cuda_device_count() == CUDA_DEVICE_COUNT
|
|
||||||
assert cuda_is_available() == CUDA_IS_AVAILABLE
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not CUDA_IS_AVAILABLE, reason='CUDA is not available')
|
@pytest.mark.skipif(not CUDA_IS_AVAILABLE, reason='CUDA is not available')
|
||||||
|
@ -14,7 +14,7 @@ from torchvision.transforms import ToTensor
|
|||||||
from ultralytics import RTDETR, YOLO
|
from ultralytics import RTDETR, YOLO
|
||||||
from ultralytics.cfg import TASK2DATA
|
from ultralytics.cfg import TASK2DATA
|
||||||
from ultralytics.data.build import load_inference_source
|
from ultralytics.data.build import load_inference_source
|
||||||
from ultralytics.utils import ASSETS, DEFAULT_CFG, LINUX, MACOS, ONLINE, ROOT, SETTINGS, WINDOWS
|
from ultralytics.utils import ASSETS, DEFAULT_CFG, LINUX, MACOS, ONLINE, ROOT, SETTINGS, WINDOWS, is_dir_writeable
|
||||||
from ultralytics.utils.downloads import download
|
from ultralytics.utils.downloads import download
|
||||||
from ultralytics.utils.torch_utils import TORCH_1_9
|
from ultralytics.utils.torch_utils import TORCH_1_9
|
||||||
|
|
||||||
@ -23,6 +23,7 @@ MODEL = WEIGHTS_DIR / 'path with spaces' / 'yolov8n.pt' # test spaces in path
|
|||||||
CFG = 'yolov8n.yaml'
|
CFG = 'yolov8n.yaml'
|
||||||
SOURCE = ASSETS / 'bus.jpg'
|
SOURCE = ASSETS / 'bus.jpg'
|
||||||
TMP = (ROOT / '../tests/tmp').resolve() # temp directory for test files
|
TMP = (ROOT / '../tests/tmp').resolve() # temp directory for test files
|
||||||
|
IS_TMP_WRITEABLE = is_dir_writeable(TMP)
|
||||||
|
|
||||||
|
|
||||||
def test_model_forward():
|
def test_model_forward():
|
||||||
@ -58,6 +59,7 @@ def test_model_profile():
|
|||||||
_ = model.predict(im, profile=True)
|
_ = model.predict(im, profile=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not IS_TMP_WRITEABLE, reason='directory is not writeable')
|
||||||
def test_predict_txt():
|
def test_predict_txt():
|
||||||
# Write a list of sources (file, dir, glob, recursive glob) to a txt file
|
# Write a list of sources (file, dir, glob, recursive glob) to a txt file
|
||||||
txt_file = TMP / 'sources.txt'
|
txt_file = TMP / 'sources.txt'
|
||||||
@ -128,6 +130,7 @@ def test_predict_grey_and_4ch():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not ONLINE, reason='environment is offline')
|
@pytest.mark.skipif(not ONLINE, reason='environment is offline')
|
||||||
|
@pytest.mark.skipif(not IS_TMP_WRITEABLE, reason='directory is not writeable')
|
||||||
def test_track_stream():
|
def test_track_stream():
|
||||||
# Test YouTube streaming inference (short 10 frame video) with non-default ByteTrack tracker
|
# Test YouTube streaming inference (short 10 frame video) with non-default ByteTrack tracker
|
||||||
# imgsz=160 required for tracking for higher confidence and better matches
|
# imgsz=160 required for tracking for higher confidence and better matches
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||||
|
|
||||||
__version__ = '8.0.180'
|
__version__ = '8.0.181'
|
||||||
|
|
||||||
from ultralytics.models import RTDETR, SAM, YOLO
|
from ultralytics.models import RTDETR, SAM, YOLO
|
||||||
from ultralytics.models.fastsam import FastSAM
|
from ultralytics.models.fastsam import FastSAM
|
||||||
|
@ -103,6 +103,9 @@ class HungarianMatcher(nn.Module):
|
|||||||
if self.with_mask:
|
if self.with_mask:
|
||||||
C += self._cost_mask(bs, gt_groups, masks, gt_mask)
|
C += self._cost_mask(bs, gt_groups, masks, gt_mask)
|
||||||
|
|
||||||
|
# Set invalid values (NaNs and infinities) to 0 (fixes ValueError: matrix contains invalid numeric entries)
|
||||||
|
C[C.isnan() | C.isinf()] = 0.0
|
||||||
|
|
||||||
C = C.view(bs, nq, -1).cpu()
|
C = C.view(bs, nq, -1).cpu()
|
||||||
indices = [linear_sum_assignment(c[i]) for i, c in enumerate(C.split(gt_groups, -1))]
|
indices = [linear_sum_assignment(c[i]) for i, c in enumerate(C.split(gt_groups, -1))]
|
||||||
gt_groups = torch.as_tensor([0, *gt_groups[:-1]]).cumsum_(0)
|
gt_groups = torch.as_tensor([0, *gt_groups[:-1]]).cumsum_(0)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||||
|
|
||||||
from ultralytics.utils import LOGGER, ROOT, SETTINGS, TESTS_RUNNING, colorstr
|
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
|
||||||
|
|
||||||
try:
|
try:
|
||||||
assert not TESTS_RUNNING # do not log pytest
|
assert not TESTS_RUNNING # do not log pytest
|
||||||
@ -8,7 +8,7 @@ try:
|
|||||||
import mlflow
|
import mlflow
|
||||||
|
|
||||||
assert hasattr(mlflow, '__version__') # verify package is not directory
|
assert hasattr(mlflow, '__version__') # verify package is not directory
|
||||||
|
PREFIX = colorstr('MLFlow:')
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -25,15 +25,13 @@ def on_pretrain_routine_end(trainer):
|
|||||||
|
|
||||||
if mlflow:
|
if mlflow:
|
||||||
mlflow_location = os.environ['MLFLOW_TRACKING_URI'] # "http://192.168.xxx.xxx:5000"
|
mlflow_location = os.environ['MLFLOW_TRACKING_URI'] # "http://192.168.xxx.xxx:5000"
|
||||||
|
LOGGER.debug(f'{PREFIX} tracking uri: {mlflow_location}')
|
||||||
mlflow.set_tracking_uri(mlflow_location)
|
mlflow.set_tracking_uri(mlflow_location)
|
||||||
|
|
||||||
experiment_name = os.environ.get('MLFLOW_EXPERIMENT_NAME') or trainer.args.project or '/Shared/YOLOv8'
|
experiment_name = os.environ.get('MLFLOW_EXPERIMENT_NAME') or trainer.args.project or '/Shared/YOLOv8'
|
||||||
run_name = os.environ.get('MLFLOW_RUN') or trainer.args.name
|
run_name = os.environ.get('MLFLOW_RUN') or trainer.args.name
|
||||||
experiment = mlflow.get_experiment_by_name(experiment_name)
|
experiment = mlflow.set_experiment(experiment_name) # change since mlflow does this now by default
|
||||||
if experiment is None:
|
|
||||||
mlflow.create_experiment(experiment_name)
|
|
||||||
mlflow.set_experiment(experiment_name)
|
|
||||||
|
|
||||||
|
mlflow.autolog()
|
||||||
prefix = colorstr('MLFlow: ')
|
prefix = colorstr('MLFlow: ')
|
||||||
try:
|
try:
|
||||||
run, active_run = mlflow, mlflow.active_run()
|
run, active_run = mlflow, mlflow.active_run()
|
||||||
@ -58,10 +56,9 @@ def on_train_end(trainer):
|
|||||||
if mlflow:
|
if mlflow:
|
||||||
run.log_artifact(trainer.last)
|
run.log_artifact(trainer.last)
|
||||||
run.log_artifact(trainer.best)
|
run.log_artifact(trainer.best)
|
||||||
run.pyfunc.log_model(artifact_path=experiment_name,
|
run.log_artifact(trainer.save_dir)
|
||||||
code_path=[str(ROOT.parent)],
|
mlflow.end_run()
|
||||||
artifacts={'model_path': str(trainer.save_dir)},
|
LOGGER.debug(f'{PREFIX} ending run')
|
||||||
python_model=run.pyfunc.PythonModel())
|
|
||||||
|
|
||||||
|
|
||||||
callbacks = {
|
callbacks = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user