From 63c7a74691f887c05f2ef429b30db5b06057076a Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sun, 1 Jan 2023 17:50:06 +0100 Subject: [PATCH] Replace `nosave` and `noval` with `save` and `val` (#127) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- ultralytics/yolo/configs/default.yaml | 114 ++++++++++++------------ ultralytics/yolo/data/build.py | 2 +- ultralytics/yolo/engine/predictor.py | 7 +- ultralytics/yolo/engine/trainer.py | 22 ++--- ultralytics/yolo/v8/classify/predict.py | 2 +- ultralytics/yolo/v8/detect/predict.py | 2 +- ultralytics/yolo/v8/segment/predict.py | 2 +- 7 files changed, 74 insertions(+), 77 deletions(-) diff --git a/ultralytics/yolo/configs/default.yaml b/ultralytics/yolo/configs/default.yaml index b7132ba..96b9c49 100644 --- a/ultralytics/yolo/configs/default.yaml +++ b/ultralytics/yolo/configs/default.yaml @@ -1,71 +1,69 @@ # YOLO 🚀 by Ultralytics, GPL-3.0 license # Default training settings and hyperparameters for medium-augmentation COCO training -# Task and Mode -task: "classify" # choices=['detect', 'segment', 'classify', 'init'] # init is a special case -mode: "train" # choice=['train', 'val', 'predict'] +task: "classify" # 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 -data: null # i.e. coco128.yaml -epochs: 100 -batch_size: 16 -imgsz: 640 -nosave: False -cache: False # True/ram, disk or False -device: '' # cuda device, i.e. 0 or 0,1,2,3 or cpu -workers: 8 -project: null -name: null -exist_ok: False -pretrained: False -optimizer: 'SGD' # choices=['SGD', 'Adam', 'AdamW', 'RMSProp'] -verbose: False -seed: 0 -deterministic: True -local_rank: -1 -single_cls: False # train multi-class data as single-class -image_weights: False # use weighted image selection for training -rect: False # support rectangular training -cos_lr: False # use cosine LR scheduler -close_mosaic: 10 # disable mosaic for final 10 epochs -resume: False +model: null # i.e. yolov5s.pt, yolo.yaml. Path to model file +data: null # i.e. coco128.yaml. Path to data file +epochs: 100 # number of epochs to train for +batch_size: 16 # number of images per batch +imgsz: 640 # size of input images +save: True # save checkpoints +cache: False # True/ram, disk or False. Use cache for data loading +device: '' # cuda device, i.e. 0 or 0,1,2,3 or cpu. Device to run on +workers: 8 # number of worker threads for data loading +project: null # project name +name: null # experiment name +exist_ok: False # whether to overwrite existing experiment +pretrained: False # whether to use a pretrained model +optimizer: 'SGD' # optimizer to use, choices=['SGD', 'Adam', 'AdamW', 'RMSProp'] +verbose: False # whether to print verbose output +seed: 0 # random seed for reproducibility +deterministic: True # whether to enable deterministic mode +local_rank: -1 # local rank for distributed training +single_cls: False # train multi-class data as single-class +image_weights: False # use weighted image selection for training +rect: False # support rectangular training +cos_lr: False # use cosine learning rate scheduler +close_mosaic: 10 # disable mosaic augmentation for final 10 epochs +resume: False # resume training from last checkpoint # Segmentation -overlap_mask: True # masks overlap -mask_ratio: 4 # mask downsample ratio +overlap_mask: True # masks should overlap during training +mask_ratio: 4 # mask downsample ratio # Classification -dropout: False # use dropout - +dropout: False # use dropout regularization # Val/Test settings ---------------------------------------------------------------------------------------------------- -noval: False -save_json: False -save_hybrid: False -conf_thres: 0.001 -iou_thres: 0.7 -max_det: 300 -half: False -dnn: False # use OpenCV DNN for ONNX inference -plots: True +val: True # validate/test during training +save_json: False # save results to JSON file +save_hybrid: False # save hybrid version of labels (labels + additional predictions) +conf_thres: 0.001 # object confidence threshold for detection +iou_thres: 0.7 # intersection over union threshold for NMS +max_det: 300 # maximum number of detections per image +half: False # use half precision (FP16) +dnn: False # use OpenCV DNN for ONNX inference +plots: True # show plots during training # Prediction settings -------------------------------------------------------------------------------------------------- -source: "ultralytics/assets/" -view_img: False -save_txt: False -save_conf: False -save_crop: False -hide_labels: False # hide labels -hide_conf: False -vid_stride: 1 # video frame-rate stride -line_thickness: 3 # bounding box thickness (pixels) -update: False # Update all models -visualize: False -augment: False -agnostic_nms: False # class-agnostic NMS -retina_masks: False +source: "ultralytics/assets" # source directory for images or videos +show: False # show results if possible +save_txt: False # save results as .txt file +save_conf: False # save results with confidence scores +save_crop: False # save cropped images with results +hide_labels: False # hide labels +hide_conf: False # hide confidence scores +vid_stride: 1 # video frame-rate stride +line_thickness: 3 # bounding box thickness (pixels) +update: False # Update all models +visualize: False # visualize results +augment: False # apply data augmentation to images +agnostic_nms: False # class-agnostic NMS +retina_masks: False # use retina masks for object detection # Export settings ------------------------------------------------------------------------------------------------------ -format: torchscript +format: torchscript # format to export to keras: False # use Keras optimize: False # TorchScript: optimize for mobile int8: False # CoreML/TF INT8 quantization @@ -103,11 +101,11 @@ mosaic: 1.0 # image mosaic (probability) mixup: 0.0 # image mixup (probability) copy_paste: 0.0 # segment copy-paste (probability) -# For debugging. Don't change -v5loader: False - # Hydra configs -------------------------------------------------------------------------------------------------------- hydra: output_subdir: null # disable hydra directory creation run: dir: . + +# Debug, do not modify ------------------------------------------------------------------------------------------------- +v5loader: False # use legacy YOLOv5 dataloader diff --git a/ultralytics/yolo/data/build.py b/ultralytics/yolo/data/build.py index 1fa0cb2..807d8ff 100644 --- a/ultralytics/yolo/data/build.py +++ b/ultralytics/yolo/data/build.py @@ -67,7 +67,7 @@ def build_dataloader(cfg, batch_size, img_path, stride=32, label_path=None, rank augment=mode == "train", # augmentation hyp=cfg, # TODO: probably add a get_hyps_from_cfg function rect=cfg.rect if mode == "train" else True, # rectangular batches - cache=None if cfg.noval else cfg.get("cache", None), + cache=cfg.get("cache", None), single_cls=cfg.get("single_cls", False), stride=int(stride), pad=0.0 if mode == "train" else 0.5, diff --git a/ultralytics/yolo/engine/predictor.py b/ultralytics/yolo/engine/predictor.py index 3fe3c23..0792dc7 100644 --- a/ultralytics/yolo/engine/predictor.py +++ b/ultralytics/yolo/engine/predictor.py @@ -104,7 +104,6 @@ class BasePredictor: def setup(self, source=None, model=None): # source source = str(source or self.args.source) - self.save_img = not self.args.nosave and not source.endswith('.txt') is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS) is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://')) webcam = source.isnumeric() or source.endswith('.streams') or (is_url and not is_file) @@ -168,10 +167,10 @@ class BasePredictor: p = Path(path) s += self.write_results(i, preds, (p, im, im0s)) - if self.args.view_img: + if self.args.show: self.show(p) - if self.save_img: + if self.args.save: self.save_preds(vid_cap, i, str(self.save_dir / p.name)) # Print time (inference-only) @@ -182,7 +181,7 @@ class BasePredictor: LOGGER.info( f'Speed: %.1fms pre-process, %.1fms inference, %.1fms postprocess per image at shape {(1, 3, *self.imgsz)}' % t) - if self.args.save_txt or self.save_img: + if self.args.save_txt or self.args.save: s = f"\n{len(list(self.save_dir.glob('labels/*.txt')))} labels saved to {self.save_dir / 'labels'}" if self.args.save_txt else '' LOGGER.info(f"Results saved to {colorstr('bold', self.save_dir)}{s}") diff --git a/ultralytics/yolo/engine/trainer.py b/ultralytics/yolo/engine/trainer.py index cdb042e..a126847 100644 --- a/ultralytics/yolo/engine/trainer.py +++ b/ultralytics/yolo/engine/trainer.py @@ -244,12 +244,12 @@ class BaseTrainer: for i, batch in pbar: self.trigger_callbacks("on_train_batch_start") - # update dataloader attributes (optional) + # Update dataloader attributes (optional) if epoch == (self.epochs - self.args.close_mosaic) and hasattr(self.train_loader.dataset, 'mosaic'): LOGGER.info("Closing dataloader mosaic") self.train_loader.dataset.mosaic = False - # warmup + # Warmup ni = i + nb * epoch if ni <= nw: xi = [0, nw] # x interp @@ -261,7 +261,7 @@ class BaseTrainer: if 'momentum' in x: x['momentum'] = np.interp(ni, xi, [self.args.warmup_momentum, self.args.momentum]) - # forward + # Forward with torch.cuda.amp.autocast(self.amp): batch = self.preprocess_batch(batch) preds = self.model(batch["img"]) @@ -271,15 +271,15 @@ class BaseTrainer: self.tloss = (self.tloss * i + self.loss_items) / (i + 1) if self.tloss is not None \ else self.loss_items - # backward + # Backward self.scaler.scale(self.loss).backward() - # optimize - https://pytorch.org/docs/master/notes/amp_examples.html + # Optimize - https://pytorch.org/docs/master/notes/amp_examples.html if ni - last_opt_step >= self.accumulate: self.optimizer_step() last_opt_step = ni - # log + # Log mem = f'{torch.cuda.memory_reserved() / 1E9 if torch.cuda.is_available() else 0:.3g}G' # (GB) loss_len = self.tloss.shape[0] if len(self.tloss.size()) else 1 losses = self.tloss if loss_len > 1 else torch.unsqueeze(self.tloss, 0) @@ -298,17 +298,17 @@ class BaseTrainer: self.trigger_callbacks("on_train_epoch_end") if rank in {-1, 0}: - # validation + # Validation self.trigger_callbacks('on_val_start') self.ema.update_attr(self.model, include=['yaml', 'nc', 'args', 'names', 'stride', 'class_weights']) final_epoch = (epoch + 1 == self.epochs) - if not self.args.noval or final_epoch: + if self.args.val or final_epoch: self.metrics, self.fitness = self.validate() self.trigger_callbacks('on_val_end') self.save_metrics(metrics={**self.label_loss_items(self.tloss), **self.metrics, **lr}) - # save model - if (not self.args.nosave) or (epoch + 1 == self.epochs): + # Save model + if self.args.save or (epoch + 1 == self.epochs): self.save_model() self.trigger_callbacks('on_model_save') @@ -319,7 +319,7 @@ class BaseTrainer: # TODO: termination condition if rank in {-1, 0}: - # do the last evaluation with best.pt + # Do final val with best.pt self.log(f'\n{epoch - self.start_epoch + 1} epochs completed in ' f'{(time.time() - self.train_time_start) / 3600:.3f} hours.') self.final_eval() diff --git a/ultralytics/yolo/v8/classify/predict.py b/ultralytics/yolo/v8/classify/predict.py index 2d16ff9..47501cc 100644 --- a/ultralytics/yolo/v8/classify/predict.py +++ b/ultralytics/yolo/v8/classify/predict.py @@ -43,7 +43,7 @@ class ClassificationPredictor(BasePredictor): # write text = '\n'.join(f'{prob[j]:.2f} {self.model.names[j]}' for j in top5i) - if self.save_img or self.args.view_img: # Add bbox to image + if self.args.save or self.args.show: # Add bbox to image self.annotator.text((32, 32), text, txt_color=(255, 255, 255)) if self.args.save_txt: # Write to file with open(f'{self.txt_path}.txt', 'a') as f: diff --git a/ultralytics/yolo/v8/detect/predict.py b/ultralytics/yolo/v8/detect/predict.py index 38ebcae..dff7ced 100644 --- a/ultralytics/yolo/v8/detect/predict.py +++ b/ultralytics/yolo/v8/detect/predict.py @@ -66,7 +66,7 @@ class DetectionPredictor(BasePredictor): with open(f'{self.txt_path}.txt', 'a') as f: f.write(('%g ' * len(line)).rstrip() % line + '\n') - if self.save_img or self.args.save_crop or self.args.view_img: # Add bbox to image + if self.args.save or self.args.save_crop or self.args.show: # Add bbox to image c = int(cls) # integer class label = None if self.args.hide_labels else ( self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}') diff --git a/ultralytics/yolo/v8/segment/predict.py b/ultralytics/yolo/v8/segment/predict.py index d4bd1d8..942bb8d 100644 --- a/ultralytics/yolo/v8/segment/predict.py +++ b/ultralytics/yolo/v8/segment/predict.py @@ -81,7 +81,7 @@ class SegmentationPredictor(DetectionPredictor): with open(f'{self.txt_path}.txt', 'a') as f: f.write(('%g ' * len(line)).rstrip() % line + '\n') - if self.save_img or self.args.save_crop or self.args.view_img: + if self.args.save or self.args.save_crop or self.args.show: c = int(cls) # integer class label = None if self.args.hide_labels else ( self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}')