def check_anchors(dataset, model, thr=4.0, imgsz=640): # Check anchor fit to data, recompute if necessary m = model.module.model[-1] if hasattr(model, 'module') else model.model[-1] # Detect() shapes = imgsz * dataset.shapes / dataset.shapes.max(1, keepdims=True) scale = np.random.uniform(0.9, 1.1, size=(shapes.shape[0], 1)) # augment scale wh = torch.tensor(np.concatenate([l[:, 3:5] * s for s, l in zip(shapes * scale, dataset.labels)])).float() # wh def metric(k): # compute metric r = wh[:, None] / k[None] x = torch.min(r, 1 / r).min(2)[0] # ratio metric best = x.max(1)[0] # best_x aat = (x > 1 / thr).float().sum(1).mean() # anchors above threshold bpr = (best > 1 / thr).float().mean() # best possible recall return bpr, aat anchors = m.anchors.clone() * m.stride.to(m.anchors.device).view(-1, 1, 1) # current anchors bpr, aat = metric(anchors.cpu().view(-1, 2)) s = f'\n{PREFIX}{aat:.2f} anchors/target, {bpr:.3f} Best Possible Recall (BPR). ' if bpr > 0.98: # threshold to recompute LOGGER.info(emojis(f'{s}Current anchors are a good fit to dataset тЬЕ')) else: LOGGER.info(emojis(f'{s}Anchors are a poor fit to dataset тЪая╕П, attempting to improve...')) na = m.anchors.numel() // 2 # number of anchors try: anchors = kmean_anchors(dataset, n=na, img_size=imgsz, thr=thr, gen=1000, verbose=False) except Exception as e: LOGGER.info(f'{PREFIX}ERROR: {e}') new_bpr = metric(anchors)[0] if new_bpr > bpr: # replace anchors anchors = torch.tensor(anchors, device=m.anchors.device).type_as(m.anchors) m.anchors[:] = anchors.clone().view_as(m.anchors) / m.stride.to(m.anchors.device).view(-1, 1, 1) # loss check_anchor_order(m) LOGGER.info(f'{PREFIX}New anchors saved to model. Update model *.yaml to use these anchors in the future.') else: LOGGER.info(f'{PREFIX}Original anchors better than new anchors. Proceeding with original anchors.')
def start(self): self.csv = True # always log to csv # Message try: import wandb except ImportError: prefix = colorstr('Weights & Biases: ') s = f"{prefix}run 'pip install wandb' to automatically track and visualize YOLOv5 🚀 runs (RECOMMENDED)" print(emojis(s)) # TensorBoard s = self.save_dir if 'tb' in self.include and not self.opt.evolve: prefix = colorstr('TensorBoard: ') self.logger.info( f"{prefix}Start with 'tensorboard --logdir {s.parent}', view at http://localhost:6006/" ) self.tb = SummaryWriter(str(s)) # W&B try: assert 'wandb' in self.include and wandb run_id = torch.load( self.weights).get('wandb_id') if self.opt.resume else None self.opt.hyp = self.hyp # add hyperparameters self.wandb = WandbLogger(self.opt, run_id, self.data_dict) except: self.wandb = None return self
def start(self): self.csv = True # always log to csv # Message if not wandb: prefix = colorstr('Weights & Biases: ') s = f"{prefix}run 'pip install wandb' to automatically track and visualize YOLOv5 🚀 runs (RECOMMENDED)" print(emojis(s)) # TensorBoard s = self.save_dir if 'tb' in self.include and not self.opt.evolve: prefix = colorstr('TensorBoard: ') self.logger.info( f"{prefix}Start with 'tensorboard --logdir {s.parent}', view at http://localhost:6006/" ) self.tb = SummaryWriter(str(s)) # W&B if wandb and 'wandb' in self.include: wandb_artifact_resume = isinstance( self.opt.resume, str) and self.opt.resume.startswith('wandb-artifact://') run_id = torch.load(self.weights).get( 'wandb_id' ) if self.opt.resume and not wandb_artifact_resume else None self.opt.hyp = self.hyp # add hyperparameters self.wandb = WandbLogger(self.opt, run_id) else: self.wandb = None return self
def main(opt): check_requirements(requirements=ROOT / 'requirements.txt', exclude=('tensorboard', 'thop')) if opt.task in ('train', 'val', 'test'): # run normally if opt.conf_thres > 0.001: # https://github.com/ultralytics/yolov5/issues/1466 LOGGER.info(emojis(f'WARNING: confidence threshold {opt.conf_thres} > 0.001 produces invalid results тЪая╕П')) run(**vars(opt)) else: weights = opt.weights if isinstance(opt.weights, list) else [opt.weights] opt.half = True # FP16 for fastest results if opt.task == 'speed': # speed benchmarks # python val.py --task speed --data coco.yaml --batch 1 --weights yolov5n.pt yolov5s.pt... opt.conf_thres, opt.iou_thres, opt.save_json = 0.25, 0.45, False for opt.weights in weights: run(**vars(opt), plots=False) elif opt.task == 'study': # speed vs mAP benchmarks # python val.py --task study --data coco.yaml --iou 0.7 --weights yolov5n.pt yolov5s.pt... for opt.weights in weights: f = f'study_{Path(opt.data).stem}_{Path(opt.weights).stem}.txt' # filename to save to x, y = list(range(256, 1536 + 128, 128)), [] # x axis (image sizes), y axis for opt.imgsz in x: # img-size LOGGER.info(f'\nRunning {f} --imgsz {opt.imgsz}...') r, _, t = run(**vars(opt), plots=False) y.append(r + t) # results and times np.savetxt(f, y, fmt='%10.4g') # save os.system('zip -r study.zip study_*.txt') plot_val_study(x=x) # plot
def notebook_init(verbose=True): # Check system software and hardware print('Checking setup...') import os import shutil from utils.general import check_requirements, emojis, is_colab from utils.torch_utils import select_device # imports check_requirements(('psutil', 'IPython')) import psutil from IPython import display # to display images and clear console output if is_colab(): shutil.rmtree( '/content/sample_data', ignore_errors=True) # remove colab /sample_data directory if verbose: # System info # gb = 1 / 1000 ** 3 # bytes to GB gib = 1 / 1024**3 # bytes to GiB ram = psutil.virtual_memory().total total, used, free = shutil.disk_usage("/") display.clear_output() s = f'({os.cpu_count()} CPUs, {ram * gib:.1f} GB RAM, {(total - free) * gib:.1f}/{total * gib:.1f} GB disk)' else: s = '' select_device(newline=False) print(emojis(f'Setup complete ✅ {s}')) return display
def __init__(self, save_dir=None, weights=None, opt=None, hyp=None, logger=None, include=LOGGERS): self.save_dir = save_dir self.weights = weights self.opt = opt self.hyp = hyp self.logger = logger # for printing results to console self.include = include self.keys = [ 'train/box_loss', 'train/obj_loss', 'train/cls_loss', # train loss 'metrics/precision', 'metrics/recall', 'metrics/mAP_0.5', 'metrics/mAP_0.5:0.95', # metrics 'val/box_loss', 'val/obj_loss', 'val/cls_loss', # val loss 'x/lr0', 'x/lr1', 'x/lr2' ] # params for k in LOGGERS: setattr(self, k, None) # init empty logger dictionary self.csv = True # always log to csv # Message if not wandb: prefix = colorstr('Weights & Biases: ') s = f"{prefix}run 'pip install wandb' to automatically track and visualize YOLOv5 🚀 runs (RECOMMENDED)" print(emojis(s)) # TensorBoard s = self.save_dir if 'tb' in self.include and not self.opt.evolve: prefix = colorstr('TensorBoard: ') self.logger.info( f"{prefix}Start with 'tensorboard --logdir {s.parent}', view at http://localhost:6006/" ) self.tb = SummaryWriter(str(s)) # W&B if wandb and 'wandb' in self.include: wandb_artifact_resume = isinstance( self.opt.resume, str) and self.opt.resume.startswith('wandb-artifact://') run_id = torch.load(self.weights).get( 'wandb_id' ) if self.opt.resume and not wandb_artifact_resume else None self.opt.hyp = self.hyp # add hyperparameters self.wandb = WandbLogger(self.opt, run_id) else: self.wandb = None
def autobatch(model, imgsz=640, fraction=0.9, batch_size=16): # Automatically estimate best batch size to use `fraction` of available CUDA memory # Usage: # import torch # from utils.autobatch import autobatch # model = torch.hub.load('ultralytics/yolov5', 'yolov5s', autoshape=False) # print(autobatch(model)) # Check device prefix = colorstr('AutoBatch: ') LOGGER.info(f'{prefix}Computing optimal batch size for --imgsz {imgsz}') device = next(model.parameters()).device # get model device if device.type == 'cpu': LOGGER.info( f'{prefix}CUDA not detected, using default CPU batch-size {batch_size}' ) return batch_size # Inspect CUDA memory gb = 1 << 30 # bytes to GiB (1024 ** 3) d = str(device).upper() # 'CUDA:0' properties = torch.cuda.get_device_properties(device) # device properties t = properties.total_memory / gb # GiB total r = torch.cuda.memory_reserved(device) / gb # GiB reserved a = torch.cuda.memory_allocated(device) / gb # GiB allocated f = t - (r + a) # GiB free LOGGER.info( f'{prefix}{d} ({properties.name}) {t:.2f}G total, {r:.2f}G reserved, {a:.2f}G allocated, {f:.2f}G free' ) # Profile batch sizes batch_sizes = [1, 2, 4, 8, 16] try: img = [torch.zeros(b, 3, imgsz, imgsz) for b in batch_sizes] results = profile(img, model, n=3, device=device) except Exception as e: LOGGER.warning(f'{prefix}{e}') # Fit a solution y = [x[2] for x in results if x] # memory [2] p = np.polyfit(batch_sizes[:len(y)], y, deg=1) # first degree polynomial fit b = int((f * fraction - p[1]) / p[0]) # y intercept (optimal batch size) if None in results: # some sizes failed i = results.index(None) # first fail index if b >= batch_sizes[i]: # y intercept above failure point b = batch_sizes[max(i - 1, 0)] # select prior safe point fraction = np.polyval(p, b) / t # actual fraction predicted LOGGER.info( emojis( f'{prefix}Using batch-size {b} for {d} {t * fraction:.2f}G/{t:.2f}G ({fraction * 100:.0f}%) ✅' )) return b
def notebook_init(): # For YOLOv5 notebooks print('Checking setup...') from IPython import display # to display images and clear console output from utils.general import emojis from utils.torch_utils import select_device # YOLOv5 imports display.clear_output() select_device(newline=False) print(emojis('Setup complete ✅')) return display