Override fixes and general updates (#129)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Kalen Michael <kalenmike@gmail.com>
This commit is contained in:
Glenn Jocher
2023-01-02 15:55:32 +01:00
committed by GitHub
parent d76d7af566
commit af6e3c536b
10 changed files with 64 additions and 50 deletions

View File

@ -1,11 +1,11 @@
# YOLO 🚀 by Ultralytics, GPL-3.0 license
# Default training settings and hyperparameters for medium-augmentation COCO training
task: "classify" # choices=['detect', 'segment', 'classify', 'init'] # init is a special case. Specify task to run.
task: "detect" # choices=['detect', 'segment', 'classify', 'init'] # init is a special case. Specify task to run.
mode: "train" # choices=['train', 'val', 'predict'] # mode to run task in.
# Train settings -------------------------------------------------------------------------------------------------------
model: null # i.e. yolov5s.pt, yolo.yaml. Path to model file
model: null # i.e. yolov8n.pt, yolov8n.yaml. Path to model file
data: null # i.e. coco128.yaml. Path to data file
epochs: 100 # number of epochs to train for
patience: 50 # TODO: epochs to wait for no observable improvement for early stopping of training

View File

@ -137,8 +137,6 @@ class Exporter:
"""
if overrides is None:
overrides = {}
if 'batch_size' not in overrides:
overrides['batch_size'] = 1 # set default export batch size
self.args = get_config(config, overrides)
project = self.args.project or f"runs/{self.args.task}"
name = self.args.name or "exp" # hardcode mode as export doesn't require it
@ -166,6 +164,8 @@ class Exporter:
assert not self.args.dynamic, '--half not compatible with --dynamic, i.e. use either --half or --dynamic'
# Checks
if self.args.batch_size == 16:
self.args.batch_size = 1 # TODO: resolve batch_size 16 default in config.yaml
self.imgsz = check_imgsz(self.args.imgsz, stride=model.stride, min_dim=2) # check image size
if self.args.optimize:
assert self.device.type == 'cpu', '--optimize not compatible with cuda devices, i.e. use --device cpu'

View File

@ -1,6 +1,7 @@
import torch
from pathlib import Path
import torch
from ultralytics import yolo # noqa
from ultralytics.nn.tasks import ClassificationModel, DetectionModel, SegmentationModel, attempt_load_weights
from ultralytics.yolo.configs import get_config

View File

@ -107,6 +107,8 @@ class BaseTrainer:
self.device = utils.torch_utils.select_device(self.args.device, self.batch_size)
self.amp = self.device.type != 'cpu'
self.scaler = amp.GradScaler(enabled=self.amp)
if self.device.type == 'cpu':
self.args.workers = 0 # faster CPU training as time dominated by inference, not dataloading
# Model and Dataloaders.
self.model = self.args.model

View File

@ -6,6 +6,7 @@ import platform
import sys
import tempfile
import threading
import uuid
from pathlib import Path
import cv2
@ -160,7 +161,7 @@ def get_user_config_dir(sub_dir='Ultralytics'):
raise ValueError(f'Unsupported operating system: {os_name}')
# GCP and AWS lambda fix, only /tmp is writeable
if not is_dir_writeable(path.parent):
if not is_dir_writeable(str(path.parent)):
path = Path('/tmp') / sub_dir
# Create the subdirectory if it does not exist
@ -172,9 +173,9 @@ def get_user_config_dir(sub_dir='Ultralytics'):
USER_CONFIG_DIR = get_user_config_dir() # Ultralytics settings dir
def emojis(str=''):
def emojis(string=''):
# Return platform-dependent emoji-safe version of string
return str.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else str
return string.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else string
def colorstr(*input):
@ -282,27 +283,39 @@ def yaml_load(file='data.yaml'):
"""
with open(file, errors='ignore') as f:
# Add YAML filename to dict and return
return {**yaml.safe_load(f), 'yaml_file': file}
return {**yaml.safe_load(f), 'yaml_file': str(file)}
def get_settings(file=USER_CONFIG_DIR / 'settings.yaml'):
"""
Function that loads a global settings YAML, or creates it and populates it with default values if it does not exist.
Loads a global settings YAML file or creates one with default values if it does not exist.
If the datasets or weights directories are set to None, the current working directory will be used.
The 'sync' setting determines whether analytics will be synced to help with YOLO development.
Args:
file (Path): Path to the settings YAML file. Defaults to 'settings.yaml' in the USER_CONFIG_DIR.
Returns:
dict: Dictionary of settings key-value pairs.
"""
from ultralytics.yolo.utils.torch_utils import torch_distributed_zero_first
defaults = {
'datasets_dir': None, # default datasets directory. If None, current working directory is used.
'weights_dir': None, # default weights directory. If None, current working directory is used.
'runs_dir': None, # default runs directory. If None, current working directory is used.
'sync': True, # sync analytics to help with YOLO development
'uuid': uuid.getnode(), # device UUID to align analytics
'yaml_file': str(file)} # setting YAML file path
with torch_distributed_zero_first(RANK):
if not file.exists():
settings = {
'datasets_dir': None, # default datasets directory. If None, current working directory is used.
'weights_dir': None, # default weights directory. If None, current working directory is used.
'sync': True} # sync analytics to help with YOLO development
yaml_save(file, settings)
yaml_save(file, defaults)
return yaml_load(file)
settings = yaml_load(file)
if settings.keys() != defaults.keys():
settings = {**defaults, **settings} # merge **defaults with **settings (prefer **settings)
yaml_save(file, settings) # save updated defaults
return settings
# Run below code on utils init -----------------------------------------------------------------------------------------

View File

@ -48,7 +48,7 @@ def on_train_end(trainer):
# Upload final model and metrics with exponential standoff
LOGGER.info(f"{PREFIX}Training completed successfully ✅\n"
f"{PREFIX}Uploading final {session.model_id}")
session.upload_model(trainer.epoch, trainer.best, map=trainer.metrics['metrics/mAP50(B)'], final=True)
session.upload_model(trainer.epoch, trainer.best, map=trainer.metrics['metrics/mAP50-95(B)'], final=True)
session.alive = False # stop heartbeats
LOGGER.info(f"{PREFIX}View model at https://hub.ultralytics.com/models/{session.model_id} 🚀")

View File

@ -201,7 +201,7 @@ def copy_attr(a, b, include=(), exclude=()):
setattr(a, k, v)
def intersect_state_dicts(da, db, exclude=()):
def intersect_dicts(da, db, exclude=()):
# Dictionary intersection of matching keys and shapes, omitting 'exclude' keys, using da values
return {k: v for k, v in da.items() if k in db and all(x not in k for x in exclude) and v.shape == db[k].shape}