{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### SIIM-FISABIO-RSNA COVID-19 Detection using yolov5","metadata":{"id":"woNse5Fl1Ejk"}},{"cell_type":"code","source":"","metadata":{"id":"NAONdZO0Gv68","outputId":"a83bf149-8fb9-4e9c-fbfe-181b47e2af0d"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /content/drive/MyDrive/YOLOV5_COVID","metadata":{"id":"H2FcI1JfiMQo","outputId":"d5862fee-a04b-4537-d1f3-e47f21838212"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Clone the Github Repo","metadata":{"id":"cZhZzwE21RYk"}},{"cell_type":"code","source":"!git clone https://github.com/ultralytics/yolov5 \n%cd yolov5\n!git reset --hard 68211f72c99915a15855f7b99bf5d93f5631330f","metadata":{"id":"5iYsrurgi8zj","outputId":"f2d76dd3-21ac-4cbb-b98f-1913c795d2b6","execution":{"iopub.status.busy":"2021-08-09T13:08:21.379489Z","iopub.execute_input":"2021-08-09T13:08:21.38006Z","iopub.status.idle":"2021-08-09T13:08:24.749542Z","shell.execute_reply.started":"2021-08-09T13:08:21.379958Z","shell.execute_reply":"2021-08-09T13:08:24.748237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"<a href=\"./yolov5/weights\"> Download File </a>","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"## Installing requirements","metadata":{"id":"S7iJUL_u1YZA"}},{"cell_type":"code","source":"!pip install -qr requirements.txt  # install dependencies (ignore errors)\nimport torch\n\nfrom IPython.display import Image, clear_output  # to display images\nfrom utils.google_utils import gdrive_download  # to download models/datasets\n\n# clear_output()\nprint('Setup complete. Using torch %s %s' % (torch.__version__, torch.cuda.get_device_properties(0) if torch.cuda.is_available() else 'CPU'))","metadata":{"id":"VL2-4bcNjJXp","outputId":"13de688d-58df-4432-fb35-d74d053c544e"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Unzipping our Dataset","metadata":{"id":"z1F1pROB1lzb"}},{"cell_type":"markdown","source":"## Checking the number of classes in our dataset","metadata":{"id":"RkvA97Pk1rql"}},{"cell_type":"code","source":"cd /content/drive/MyDrive/YOLOV5_COVID/yolov5","metadata":{"id":"5ALaUsqMbic3","outputId":"7ce0b055-28a5-4dee-fcc4-b6df329caa3c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cat data.yaml","metadata":{"id":"FU8bdUEcjzWq","outputId":"2d7951fe-b217-480d-8065-6da1ab202840"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## # Defining number of classes","metadata":{"id":"DjYWoqrB1208"}},{"cell_type":"code","source":"import yaml\nwith open(\"data.yaml\", 'r') as stream:\n    num_classes = str(yaml.safe_load(stream)['nc'])","metadata":{"id":"sB6xZtePk5sa"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model configuration for YoloV5","metadata":{"id":"A2KLmbuX2Bv2"}},{"cell_type":"code","source":"%cat /content/drive/MyDrive/YOLOV5_COVID/yolov5/models/yolov5s.yaml","metadata":{"id":"5sBjOjcYmF9g","outputId":"fe22247f-9653-4639-9d95-396ff62047e4"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Customize iPython writefile so we can write variables\n","metadata":{"id":"JDQn-lUs2etK"}},{"cell_type":"code","source":"from IPython.core.magic import register_line_cell_magic\n\n@register_line_cell_magic\ndef writetemplate(line, cell):\n    with open(line, 'w') as f:\n        f.write(cell.format(**globals()))","metadata":{"id":"hQzlwlb9mOm6"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model Configuration for our Model","metadata":{"id":"y8KCKKzJ2jaD"}},{"cell_type":"code","source":"%%writetemplate /content/drive/MyDrive/YOLOV5_CUSTOM/yolov5/models/custom_yolov5s.yaml\n\n# parameters\nnc: {num_classes}  # number of classes\ndepth_multiple: 0.33  # model depth multiple\nwidth_multiple: 0.50  # layer channel multiple\n\n# anchors\nanchors:\n  - [10,13, 16,30, 33,23]  # P3/8\n  - [30,61, 62,45, 59,119]  # P4/16\n  - [116,90, 156,198, 373,326]  # P5/32\n\n# YOLOv5 backbone\nbackbone:\n  # [from, number, module, args]\n  [[-1, 1, Focus, [64, 3]],  # 0-P1/2\n   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4\n   [-1, 3, BottleneckCSP, [128]],\n   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8\n   [-1, 9, BottleneckCSP, [256]],\n   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16\n   [-1, 9, BottleneckCSP, [512]],\n   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32\n   [-1, 1, SPP, [1024, [5, 9, 13]]],\n   [-1, 3, BottleneckCSP, [1024, False]],  # 9\n  ]\n\n# YOLOv5 head\nhead:\n  [[-1, 1, Conv, [512, 1, 1]],\n   [-1, 1, nn.Upsample, [None, 2, 'nearest']],\n   [[-1, 6], 1, Concat, [1]],  # cat backbone P4\n   [-1, 3, BottleneckCSP, [512, False]],  # 13\n\n   [-1, 1, Conv, [256, 1, 1]],\n   [-1, 1, nn.Upsample, [None, 2, 'nearest']],\n   [[-1, 4], 1, Concat, [1]],  # cat backbone P3\n   [-1, 3, BottleneckCSP, [256, False]],  # 17 (P3/8-small)\n\n   [-1, 1, Conv, [256, 3, 2]],\n   [[-1, 14], 1, Concat, [1]],  # cat head P4\n   [-1, 3, BottleneckCSP, [512, False]],  # 20 (P4/16-medium)\n\n   [-1, 1, Conv, [512, 3, 2]],\n   [[-1, 10], 1, Concat, [1]],  # cat head P5\n   [-1, 3, BottleneckCSP, [1024, False]],  # 23 (P5/32-large)\n\n   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)\n  ]","metadata":{"id":"fo_aZXJUmUZB"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Doing Changes in train.py for training","metadata":{"id":"C_B7ARek26rW"}},{"cell_type":"code","source":"%%writefile /content/drive/MyDrive/YOLOV5_CUSTOM/yolov5/utils/train.py\nimport argparse\nimport logging\nimport math\nimport os\nimport random\nimport time\nfrom pathlib import Path\nfrom warnings import warn\n\nimport numpy as np\nimport torch.distributed as dist\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport torch.optim.lr_scheduler as lr_scheduler\nimport torch.utils.data\nimport yaml\nfrom torch.cuda import amp\nfrom torch.nn.parallel import DistributedDataParallel as DDP\nfrom torch.utils.tensorboard import SummaryWriter\nfrom tqdm import tqdm\n\nimport test  # import test.py to get mAP after each epoch\nfrom models.yolo import Model\nfrom utils.autoanchor import check_anchors\nfrom utils.datasets import create_dataloader\nfrom utils.general import labels_to_class_weights, increment_path, labels_to_image_weights, init_seeds, \\\n    fitness, strip_optimizer, get_latest_run, check_dataset, check_file, check_git_status, check_img_size, \\\n    print_mutation, set_logging\nfrom utils.google_utils import attempt_download\nfrom utils.loss import compute_loss\nfrom utils.plots import plot_images, plot_labels, plot_results, plot_evolution\nfrom utils.torch_utils import ModelEMA, select_device, intersect_dicts, torch_distributed_zero_first\n\nlogger = logging.getLogger(__name__)\n\ntry:\n    import wandb\nexcept ImportError:\n    wandb = None\n    logger.info(\"Install Weights & Biases for experiment logging via 'pip install wandb' (recommended)\")\n\n\ndef train(hyp, opt, device, tb_writer=None, wandb=None):\n    logger.info(f'Hyperparameters {hyp}')\n    save_dir, epochs, batch_size, total_batch_size, weights, rank = \\\n        Path(opt.save_dir), opt.epochs, opt.batch_size, opt.total_batch_size, opt.weights, opt.global_rank\n\n    # Directories\n    wdir = save_dir / 'weights'\n    wdir.mkdir(parents=True, exist_ok=True)  # make dir\n    last = wdir / 'last.pt'\n    best = wdir / 'best.pt'\n    results_file = save_dir / 'results.txt'\n\n    # Save run settings\n    with open(save_dir / 'hyp.yaml', 'w') as f:\n        yaml.dump(hyp, f, sort_keys=False)\n    with open(save_dir / 'opt.yaml', 'w') as f:\n        yaml.dump(vars(opt), f, sort_keys=False)\n\n    # Configure\n    plots = not opt.evolve  # create plots\n    cuda = device.type != 'cpu'\n    init_seeds(2 + rank)\n    with open(opt.data) as f:\n        data_dict = yaml.load(f, Loader=yaml.FullLoader)  # data dict\n    with torch_distributed_zero_first(rank):\n        check_dataset(data_dict)  # check\n    train_path = data_dict['train']\n    test_path = data_dict['val']\n    nc, names = (1, ['item']) if opt.single_cls else (int(data_dict['nc']), data_dict['names'])  # number classes, names\n    assert len(names) == nc, '%g names found for nc=%g dataset in %s' % (len(names), nc, opt.data)  # check\n\n    # Model\n    pretrained = weights.endswith('.pt')\n    if pretrained:\n        with torch_distributed_zero_first(rank):\n            attempt_download(weights)  # download if not found locally\n        ckpt = torch.load(weights, map_location=device)  # load checkpoint\n        if hyp.get('anchors'):\n            ckpt['model'].yaml['anchors'] = round(hyp['anchors'])  # force autoanchor\n        model = Model(opt.cfg or ckpt['model'].yaml, ch=3, nc=nc).to(device)  # create\n        exclude = ['anchor'] if opt.cfg or hyp.get('anchors') else []  # exclude keys\n        state_dict = ckpt['model'].float().state_dict()  # to FP32\n        state_dict = intersect_dicts(state_dict, model.state_dict(), exclude=exclude)  # intersect\n        model.load_state_dict(state_dict, strict=False)  # load\n        logger.info('Transferred %g/%g items from %s' % (len(state_dict), len(model.state_dict()), weights))  # report\n    else:\n        model = Model(opt.cfg, ch=3, nc=nc).to(device)  # create\n\n    # Freeze\n    freeze = []  # parameter names to freeze (full or partial)\n    for k, v in model.named_parameters():\n        v.requires_grad = True  # train all layers\n        if any(x in k for x in freeze):\n            print('freezing %s' % k)\n            v.requires_grad = False\n\n    # Optimizer\n    nbs = 64  # nominal batch size\n    accumulate = max(round(nbs / total_batch_size), 1)  # accumulate loss before optimizing\n    hyp['weight_decay'] *= total_batch_size * accumulate / nbs  # scale weight_decay\n\n    pg0, pg1, pg2 = [], [], []  # optimizer parameter groups\n    for k, v in model.named_modules():\n        if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):\n            pg2.append(v.bias)  # biases\n        if isinstance(v, nn.BatchNorm2d):\n            pg0.append(v.weight)  # no decay\n        elif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):\n            pg1.append(v.weight)  # apply decay\n\n    if opt.adam:\n        optimizer = optim.Adam(pg0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999))  # adjust beta1 to momentum\n    else:\n        optimizer = optim.SGD(pg0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)\n\n    optimizer.add_param_group({'params': pg1, 'weight_decay': hyp['weight_decay']})  # add pg1 with weight_decay\n    optimizer.add_param_group({'params': pg2})  # add pg2 (biases)\n    logger.info('Optimizer groups: %g .bias, %g conv.weight, %g other' % (len(pg2), len(pg1), len(pg0)))\n    del pg0, pg1, pg2\n\n    # Scheduler https://arxiv.org/pdf/1812.01187.pdf\n    # https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html#OneCycleLR\n    lf = lambda x: ((1 + math.cos(x * math.pi / epochs)) / 2) * (1 - hyp['lrf']) + hyp['lrf']  # cosine\n    scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)\n    # plot_lr_scheduler(optimizer, scheduler, epochs)\n\n    # Logging\n    if wandb and wandb.run is None:\n        opt.hyp = hyp  # add hyperparameters\n        wandb_run = wandb.init(config=opt, resume=\"allow\",\n                               project='YOLOv5' if opt.project == 'runs/train' else Path(opt.project).stem,\n                               name=save_dir.stem,\n                               id=ckpt.get('wandb_id') if 'ckpt' in locals() else None)\n\n    # Resume\n    start_epoch, best_fitness = 0, 0.0\n    if pretrained:\n        # Optimizer\n        if ckpt['optimizer'] is not None:\n            optimizer.load_state_dict(ckpt['optimizer'])\n            best_fitness = ckpt['best_fitness']\n\n        # Results\n        if ckpt.get('training_results') is not None:\n            with open(results_file, 'w') as file:\n                file.write(ckpt['training_results'])  # write results.txt\n\n        # Epochs\n        start_epoch = ckpt['epoch'] + 1\n        if opt.resume:\n            assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)\n        if epochs < start_epoch:\n            logger.info('%s has been trained for %g epochs. Fine-tuning for %g additional epochs.' %\n                        (weights, ckpt['epoch'], epochs))\n            epochs += ckpt['epoch']  # finetune additional epochs\n\n        del ckpt, state_dict\n\n    # Image sizes\n    gs = int(max(model.stride))  # grid size (max stride)\n    imgsz, imgsz_test = [check_img_size(x, gs) for x in opt.img_size]  # verify imgsz are gs-multiples\n\n    # DP mode\n    if cuda and rank == -1 and torch.cuda.device_count() > 1:\n        model = torch.nn.DataParallel(model)\n\n    # SyncBatchNorm\n    if opt.sync_bn and cuda and rank != -1:\n        model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model).to(device)\n        logger.info('Using SyncBatchNorm()')\n\n    # EMA\n    ema = ModelEMA(model) if rank in [-1, 0] else None\n\n    # DDP mode\n    if cuda and rank != -1:\n        model = DDP(model, device_ids=[opt.local_rank], output_device=opt.local_rank)\n\n    # Trainloader\n    dataloader, dataset = create_dataloader(train_path, imgsz, batch_size, gs, opt,\n                                            hyp=hyp, augment=True, cache=opt.cache_images, rect=opt.rect, rank=rank,\n                                            world_size=opt.world_size, workers=opt.workers)\n    mlc = np.concatenate(dataset.labels, 0)[:, 0].max()  # max label class\n    nb = len(dataloader)  # number of batches\n    assert mlc < nc, 'Label class %g exceeds nc=%g in %s. Possible class labels are 0-%g' % (mlc, nc, opt.data, nc - 1)\n\n    # Process 0\n    if rank in [-1, 0]:\n        ema.updates = start_epoch * nb // accumulate  # set EMA updates\n        testloader = create_dataloader(test_path, imgsz_test, total_batch_size, gs, opt,\n                                       hyp=hyp, cache=opt.cache_images and not opt.notest, rect=True,\n                                       rank=-1, world_size=opt.world_size, workers=opt.workers)[0]  # testloader\n\n        if not opt.resume:\n            labels = np.concatenate(dataset.labels, 0)\n            c = torch.tensor(labels[:, 0])  # classes\n            # cf = torch.bincount(c.long(), minlength=nc) + 1.  # frequency\n            # model._initialize_biases(cf.to(device))\n            if plots:\n                plot_labels(labels, save_dir=save_dir)\n                if tb_writer:\n                    tb_writer.add_histogram('classes', c, 0)\n                if wandb:\n                    wandb.log({\"Labels\": [wandb.Image(str(x), caption=x.name) for x in save_dir.glob('*labels*.png')]})\n\n            # Anchors\n            if not opt.noautoanchor:\n                check_anchors(dataset, model=model, thr=hyp['anchor_t'], imgsz=imgsz)\n\n    # Model parameters\n    hyp['cls'] *= nc / 80.  # scale coco-tuned hyp['cls'] to current dataset\n    model.nc = nc  # attach number of classes to model\n    model.hyp = hyp  # attach hyperparameters to model\n    model.gr = 1.0  # iou loss ratio (obj_loss = 1.0 or iou)\n    model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device)  # attach class weights\n    model.names = names\n\n    # Start training\n    t0 = time.time()\n    nw = max(round(hyp['warmup_epochs'] * nb), 1000)  # number of warmup iterations, max(3 epochs, 1k iterations)\n    # nw = min(nw, (epochs - start_epoch) / 2 * nb)  # limit warmup to < 1/2 of training\n    maps = np.zeros(nc)  # mAP per class\n    results = (0, 0, 0, 0, 0, 0, 0)  # P, R, mAP@.5, mAP@.5-.95, val_loss(box, obj, cls)\n    scheduler.last_epoch = start_epoch - 1  # do not move\n    scaler = amp.GradScaler(enabled=cuda)\n    logger.info('Image sizes %g train, %g test\\n'\n                'Using %g dataloader workers\\nLogging results to %s\\n'\n                'Starting training for %g epochs...' % (imgsz, imgsz_test, dataloader.num_workers, save_dir, epochs))\n    for epoch in range(start_epoch, epochs):  # epoch ------------------------------------------------------------------\n        model.train()\n\n        # Update image weights (optional)\n        if opt.image_weights:\n            # Generate indices\n            if rank in [-1, 0]:\n                cw = model.class_weights.cpu().numpy() * (1 - maps) ** 2  # class weights\n                iw = labels_to_image_weights(dataset.labels, nc=nc, class_weights=cw)  # image weights\n                dataset.indices = random.choices(range(dataset.n), weights=iw, k=dataset.n)  # rand weighted idx\n            # Broadcast if DDP\n            if rank != -1:\n                indices = (torch.tensor(dataset.indices) if rank == 0 else torch.zeros(dataset.n)).int()\n                dist.broadcast(indices, 0)\n                if rank != 0:\n                    dataset.indices = indices.cpu().numpy()\n\n        # Update mosaic border\n        # b = int(random.uniform(0.25 * imgsz, 0.75 * imgsz + gs) // gs * gs)\n        # dataset.mosaic_border = [b - imgsz, -b]  # height, width borders\n\n        mloss = torch.zeros(4, device=device)  # mean losses\n        if rank != -1:\n            dataloader.sampler.set_epoch(epoch)\n        pbar = enumerate(dataloader)\n        logger.info(('\\n' + '%10s' * 8) % ('Epoch', 'gpu_mem', 'box', 'obj', 'cls', 'total', 'targets', 'img_size'))\n        if rank in [-1, 0]:\n            pbar = tqdm(pbar, total=nb)  # progress bar\n        optimizer.zero_grad()\n        for i, (imgs, targets, paths, _) in pbar:  # batch -------------------------------------------------------------\n            ni = i + nb * epoch  # number integrated batches (since train start)\n            imgs = imgs.to(device, non_blocking=True).float() / 255.0  # uint8 to float32, 0-255 to 0.0-1.0\n\n            # Warmup\n            if ni <= nw:\n                xi = [0, nw]  # x interp\n                # model.gr = np.interp(ni, xi, [0.0, 1.0])  # iou loss ratio (obj_loss = 1.0 or iou)\n                accumulate = max(1, np.interp(ni, xi, [1, nbs / total_batch_size]).round())\n                for j, x in enumerate(optimizer.param_groups):\n                    # bias lr falls from 0.1 to lr0, all other lrs rise from 0.0 to lr0\n                    x['lr'] = np.interp(ni, xi, [hyp['warmup_bias_lr'] if j == 2 else 0.0, x['initial_lr'] * lf(epoch)])\n                    if 'momentum' in x:\n                        x['momentum'] = np.interp(ni, xi, [hyp['warmup_momentum'], hyp['momentum']])\n\n            # Multi-scale\n            if opt.multi_scale:\n                sz = random.randrange(imgsz * 0.5, imgsz * 1.5 + gs) // gs * gs  # size\n                sf = sz / max(imgs.shape[2:])  # scale factor\n                if sf != 1:\n                    ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]]  # new shape (stretched to gs-multiple)\n                    imgs = F.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)\n\n            # Forward\n            with amp.autocast(enabled=cuda):\n                pred = model(imgs)  # forward\n                loss, loss_items = compute_loss(pred, targets.to(device), model)  # loss scaled by batch_size\n                if rank != -1:\n                    loss *= opt.world_size  # gradient averaged between devices in DDP mode\n\n            # Backward\n            scaler.scale(loss).backward()\n\n            # Optimize\n            if ni % accumulate == 0:\n                scaler.step(optimizer)  # optimizer.step\n                scaler.update()\n                optimizer.zero_grad()\n                if ema:\n                    ema.update(model)\n\n            # Print\n            if rank in [-1, 0]:\n                mloss = (mloss * i + loss_items) / (i + 1)  # update mean losses\n                mem = '%.3gG' % (torch.cuda.memory_reserved() / 1E9 if torch.cuda.is_available() else 0)  # (GB)\n                s = ('%10s' * 2 + '%10.4g' * 6) % (\n                    '%g/%g' % (epoch, epochs - 1), mem, *mloss, targets.shape[0], imgs.shape[-1])\n                pbar.set_description(s)\n\n                # Plot\n                if plots and ni < 3:\n                    f = save_dir / f'train_batch{ni}.jpg'  # filename\n                    plot_images(images=imgs, targets=targets, paths=paths, fname=f)\n                    # if tb_writer:\n                    #     tb_writer.add_image(f, result, dataformats='HWC', global_step=epoch)\n                    #     tb_writer.add_graph(model, imgs)  # add model to tensorboard\n                elif plots and ni == 3 and wandb:\n                    wandb.log({\"Mosaics\": [wandb.Image(str(x), caption=x.name) for x in save_dir.glob('train*.jpg')]})\n\n            # end batch ------------------------------------------------------------------------------------------------\n        # end epoch ----------------------------------------------------------------------------------------------------\n\n        # Scheduler\n        lr = [x['lr'] for x in optimizer.param_groups]  # for tensorboard\n        scheduler.step()\n\n        # DDP process 0 or single-GPU\n        if rank in [-1, 0]:\n            # mAP\n            if ema:\n                ema.update_attr(model, include=['yaml', 'nc', 'hyp', 'gr', 'names', 'stride'])\n            final_epoch = epoch + 1 == epochs\n            if not opt.notest or final_epoch:  # Calculate mAP\n                results, maps, times = test.test(opt.data,\n                                                 batch_size=total_batch_size,\n                                                 imgsz=imgsz_test,\n                                                 model=ema.ema,\n                                                 single_cls=opt.single_cls,\n                                                 dataloader=testloader,\n                                                 save_dir=save_dir,\n                                                 plots=plots and final_epoch,\n                                                 log_imgs=opt.log_imgs if wandb else 0)\n\n            # Write\n            with open(results_file, 'a') as f:\n                f.write(s + '%10.4g' * 7 % results + '\\n')  # P, R, mAP@.5, mAP@.5-.95, val_loss(box, obj, cls)\n            if len(opt.name) and opt.bucket:\n                os.system('gsutil cp %s gs://%s/results/results%s.txt' % (results_file, opt.bucket, opt.name))\n\n            # Log\n            tags = ['train/box_loss', 'train/obj_loss', 'train/cls_loss',  # train loss\n                    'metrics/precision', 'metrics/recall', 'metrics/mAP_0.5', 'metrics/mAP_0.5:0.95',\n                    'val/box_loss', 'val/obj_loss', 'val/cls_loss',  # val loss\n                    'x/lr0', 'x/lr1', 'x/lr2']  # params\n            for x, tag in zip(list(mloss[:-1]) + list(results) + lr, tags):\n                if tb_writer:\n                    tb_writer.add_scalar(tag, x, epoch)  # tensorboard\n                if wandb:\n                    wandb.log({tag: x})  # W&B\n\n            # Update best mAP\n            fi = fitness(np.array(results).reshape(1, -1))  # weighted combination of [P, R, mAP@.5, mAP@.5-.95]\n            if fi > best_fitness:\n                best_fitness = fi\n\n            # Save model\n            save = (not opt.nosave) or (final_epoch and not opt.evolve)\n            if save:\n                with open(results_file, 'r') as f:  # create checkpoint\n                    ckpt = {'epoch': epoch,\n                            'best_fitness': best_fitness,\n                            'training_results': f.read(),\n                            'model': ema.ema,\n                            'optimizer': None if final_epoch else optimizer.state_dict(),\n                            'wandb_id': wandb_run.id if wandb else None}\n\n                # Save last, best and delete\n                torch.save(ckpt, last)\n                if best_fitness == fi:\n                    torch.save(ckpt, best)\n                del ckpt\n        # end epoch ----------------------------------------------------------------------------------------------------\n    # end training\n\n    if rank in [-1, 0]:\n        # Strip optimizers\n        n = opt.name if opt.name.isnumeric() else ''\n        fresults, flast, fbest = save_dir / f'results{n}.txt', wdir / f'last{n}.pt', wdir / f'best{n}.pt'\n        for f1, f2 in zip([wdir / 'last.pt', wdir / 'best.pt', results_file], [flast, fbest, fresults]):\n            if f1.exists():\n                os.rename(f1, f2)  # rename\n                if str(f2).endswith('.pt'):  # is *.pt\n                    strip_optimizer(f2)  # strip optimizer\n                    os.system('gsutil cp %s gs://%s/weights' % (f2, opt.bucket)) if opt.bucket else None  # upload\n        # Finish\n        if plots:\n            plot_results(save_dir=save_dir)  # save as results.png\n            if wandb:\n                files = ['results.png', 'precision_recall_curve.png', 'confusion_matrix.png']\n                wandb.log({\"Results\": [wandb.Image(str(save_dir / f), caption=f) for f in files\n                                       if (save_dir / f).exists()]})\n        logger.info('%g epochs completed in %.3f hours.\\n' % (epoch - start_epoch + 1, (time.time() - t0) / 3600))\n    else:\n        dist.destroy_process_group()\n\n    wandb.run.finish() if wandb and wandb.run else None\n    torch.cuda.empty_cache()\n    return results\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')\n    parser.add_argument('--cfg', type=str, default='', help='model.yaml path')\n    parser.add_argument('--data', type=str, default='data/coco128.yaml', help='data.yaml path')\n    parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')\n    parser.add_argument('--epochs', type=int, default=300)\n    parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')\n    parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')\n    parser.add_argument('--rect', action='store_true', help='rectangular training')\n    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')\n    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')\n    parser.add_argument('--notest', action='store_true', help='only test final epoch')\n    parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')\n    parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')\n    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')\n    parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')\n    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')\n    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')\n    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')\n    parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')\n    parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')\n    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')\n    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')\n    parser.add_argument('--log-imgs', type=int, default=16, help='number of images for W&B logging, max 100')\n    parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')\n    parser.add_argument('--project', default='runs/train', help='save to project/name')\n    parser.add_argument('--name', default='exp', help='save to project/name')\n    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')\n    opt = parser.parse_args()\n\n    # Set DDP variables\n    opt.total_batch_size = opt.batch_size\n    opt.world_size = int(os.environ['WORLD_SIZE']) if 'WORLD_SIZE' in os.environ else 1\n    opt.global_rank = int(os.environ['RANK']) if 'RANK' in os.environ else -1\n    set_logging(opt.global_rank)\n    if opt.global_rank in [-1, 0]:\n        check_git_status()\n\n    # Resume\n    if opt.resume:  # resume an interrupted run\n        ckpt = opt.resume if isinstance(opt.resume, str) else get_latest_run()  # specified or most recent path\n        assert os.path.isfile(ckpt), 'ERROR: --resume checkpoint does not exist'\n        with open(Path(ckpt).parent.parent / 'opt.yaml') as f:\n            opt = argparse.Namespace(**yaml.load(f, Loader=yaml.FullLoader))  # replace\n        opt.cfg, opt.weights, opt.resume = '', ckpt, True\n        logger.info('Resuming training from %s' % ckpt)\n    else:\n        # opt.hyp = opt.hyp or ('hyp.finetune.yaml' if opt.weights else 'hyp.scratch.yaml')\n        opt.data, opt.cfg, opt.hyp = check_file(opt.data), check_file(opt.cfg), check_file(opt.hyp)  # check files\n        assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'\n        opt.img_size.extend([opt.img_size[-1]] * (2 - len(opt.img_size)))  # extend to 2 sizes (train, test)\n        opt.name = 'evolve' if opt.evolve else opt.name\n        opt.save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok | opt.evolve)  # increment run\n\n    # DDP mode\n    device = select_device(opt.device, batch_size=opt.batch_size)\n    if opt.local_rank != -1:\n        assert torch.cuda.device_count() > opt.local_rank\n        torch.cuda.set_device(opt.local_rank)\n        device = torch.device('cuda', opt.local_rank)\n        dist.init_process_group(backend='nccl', init_method='env://')  # distributed backend\n        assert opt.batch_size % opt.world_size == 0, '--batch-size must be multiple of CUDA device count'\n        opt.batch_size = opt.total_batch_size // opt.world_size\n\n    # Hyperparameters\n    with open(opt.hyp) as f:\n        hyp = yaml.load(f, Loader=yaml.FullLoader)  # load hyps\n        if 'box' not in hyp:\n            warn('Compatibility: %s missing \"box\" which was renamed from \"giou\" in %s' %\n                 (opt.hyp, 'https://github.com/ultralytics/yolov5/pull/1120'))\n            hyp['box'] = hyp.pop('giou')\n\n    # Train\n    logger.info(opt)\n    if not opt.evolve:\n        tb_writer = None  # init loggers\n        if opt.global_rank in [-1, 0]:\n            logger.info(f'Start Tensorboard with \"tensorboard --logdir {opt.project}\", view at http://localhost:6006/')\n            tb_writer = SummaryWriter(opt.save_dir)  # Tensorboard\n        train(hyp, opt, device, tb_writer, wandb)\n\n    # Evolve hyperparameters (optional)\n    else:\n        # Hyperparameter evolution metadata (mutation scale 0-1, lower_limit, upper_limit)\n        meta = {'lr0': (1, 1e-5, 1e-1),  # initial learning rate (SGD=1E-2, Adam=1E-3)\n                'lrf': (1, 0.01, 1.0),  # final OneCycleLR learning rate (lr0 * lrf)\n                'momentum': (0.3, 0.6, 0.98),  # SGD momentum/Adam beta1\n                'weight_decay': (1, 0.0, 0.001),  # optimizer weight decay\n                'warmup_epochs': (1, 0.0, 5.0),  # warmup epochs (fractions ok)\n                'warmup_momentum': (1, 0.0, 0.95),  # warmup initial momentum\n                'warmup_bias_lr': (1, 0.0, 0.2),  # warmup initial bias lr\n                'box': (1, 0.02, 0.2),  # box loss gain\n                'cls': (1, 0.2, 4.0),  # cls loss gain\n                'cls_pw': (1, 0.5, 2.0),  # cls BCELoss positive_weight\n                'obj': (1, 0.2, 4.0),  # obj loss gain (scale with pixels)\n                'obj_pw': (1, 0.5, 2.0),  # obj BCELoss positive_weight\n                'iou_t': (0, 0.1, 0.7),  # IoU training threshold\n                'anchor_t': (1, 2.0, 8.0),  # anchor-multiple threshold\n                'anchors': (2, 2.0, 10.0),  # anchors per output grid (0 to ignore)\n                'fl_gamma': (0, 0.0, 2.0),  # focal loss gamma (efficientDet default gamma=1.5)\n                'hsv_h': (1, 0.0, 0.1),  # image HSV-Hue augmentation (fraction)\n                'hsv_s': (1, 0.0, 0.9),  # image HSV-Saturation augmentation (fraction)\n                'hsv_v': (1, 0.0, 0.9),  # image HSV-Value augmentation (fraction)\n                'degrees': (1, 0.0, 45.0),  # image rotation (+/- deg)\n                'translate': (1, 0.0, 0.9),  # image translation (+/- fraction)\n                'scale': (1, 0.0, 0.9),  # image scale (+/- gain)\n                'shear': (1, 0.0, 10.0),  # image shear (+/- deg)\n                'perspective': (0, 0.0, 0.001),  # image perspective (+/- fraction), range 0-0.001\n                'flipud': (1, 0.0, 1.0),  # image flip up-down (probability)\n                'fliplr': (0, 0.0, 1.0),  # image flip left-right (probability)\n                'mosaic': (1, 0.0, 1.0),  # image mixup (probability)\n                'mixup': (1, 0.0, 1.0)}  # image mixup (probability)\n\n        assert opt.local_rank == -1, 'DDP mode not implemented for --evolve'\n        opt.notest, opt.nosave = True, True  # only test/save final epoch\n        # ei = [isinstance(x, (int, float)) for x in hyp.values()]  # evolvable indices\n        yaml_file = Path(opt.save_dir) / 'hyp_evolved.yaml'  # save best result here\n        if opt.bucket:\n            os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket)  # download evolve.txt if exists\n\n        for _ in range(300):  # generations to evolve\n            if Path('evolve.txt').exists():  # if evolve.txt exists: select best hyps and mutate\n                # Select parent(s)\n                parent = 'single'  # parent selection method: 'single' or 'weighted'\n                x = np.loadtxt('evolve.txt', ndmin=2)\n                n = min(5, len(x))  # number of previous results to consider\n                x = x[np.argsort(-fitness(x))][:n]  # top n mutations\n                w = fitness(x) - fitness(x).min()  # weights\n                if parent == 'single' or len(x) == 1:\n                    # x = x[random.randint(0, n - 1)]  # random selection\n                    x = x[random.choices(range(n), weights=w)[0]]  # weighted selection\n                elif parent == 'weighted':\n                    x = (x * w.reshape(n, 1)).sum(0) / w.sum()  # weighted combination\n\n                # Mutate\n                mp, s = 0.8, 0.2  # mutation probability, sigma\n                npr = np.random\n                npr.seed(int(time.time()))\n                g = np.array([x[0] for x in meta.values()])  # gains 0-1\n                ng = len(meta)\n                v = np.ones(ng)\n                while all(v == 1):  # mutate until a change occurs (prevent duplicates)\n                    v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)\n                for i, k in enumerate(hyp.keys()):  # plt.hist(v.ravel(), 300)\n                    hyp[k] = float(x[i + 7] * v[i])  # mutate\n\n            # Constrain to limits\n            for k, v in meta.items():\n                hyp[k] = max(hyp[k], v[1])  # lower limit\n                hyp[k] = min(hyp[k], v[2])  # upper limit\n                hyp[k] = round(hyp[k], 5)  # significant digits\n\n            # Train mutation\n            results = train(hyp.copy(), opt, device, wandb=wandb)\n\n            # Write mutation results\n            print_mutation(hyp.copy(), results, yaml_file, opt.bucket)\n\n        # Plot results\n        plot_evolution(yaml_file)\n        print(f'Hyperparameter evolution complete. Best results saved as: {yaml_file}\\n'\n              f'Command to train a new model with these hyperparameters: $ python train.py --hyp {yaml_file}')\n","metadata":{"id":"kBaqvv4hndhN","outputId":"85c6efd3-a159-4207-cba4-bc34d9c47eec"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Let's Start Training","metadata":{"id":"MPbw9vkS3JMn"}},{"cell_type":"code","source":"!pip install torch==1.7.0+cu110 torchvision==0.8.1+cu110 torchaudio===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html","metadata":{"id":"tfxbPWQdjreh","outputId":"bdba3293-b31d-47de-8221-3495e4093fe5"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train yolov5s on custom data for 100 epochs\n# time its performance\n%%time\n%cd /content/drive/MyDrive/YOLOV5_COVID/yolov5\n!python train.py --img 1024 --batch 8 --epochs 2000 --data '/content/drive/MyDrive/YOLOV5_COVID/yolov5/data.yaml' --cfg /content/drive/MyDrive/YOLOV5_COVID/yolov5/models/yolov5s.yaml --weights '' --name yolov5s_results  --cache","metadata":{"id":"NS31XwQDmal9","outputId":"5b1bd4ca-4fd0-4a84-e5f3-0d4a0eb22083"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python train.py --resume","metadata":{"id":"WqVR4DoUetqw","outputId":"1eeeb430-7202-49db-a36a-f55760ee8bb9"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inferencing with our custom Trained Model","metadata":{"id":"ToJ-TRyH3XTQ"}},{"cell_type":"code","source":"%cd /content/drive/MyDrive/YOLOV5_COVID/yolov5\n!python detect.py --weights /content/drive/MyDrive/YOLOV5_COVID/yolov5/runs/train/yolov5s_results20/weights/best.pt --img 416 --conf 0.3 --source /content/drive/MyDrive/YOLOV5_COVID/yolov5/small-dataset/images/validation","metadata":{"id":"bPozSfZjyNxO","outputId":"b9926270-a77a-417c-b786-c3f81cb928ba"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom scipy import misc\nimport numpy as np\nimport os, json, cv2, random\nfrom google.colab.patches import cv2_imshow\nimport matplotlib.image as mpimg\n","metadata":{"id":"2RE3_3kbpvIb"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\nfrom PIL import Image\nimport os\n\npath = \"/content/drive/MyDrive/YOLOV5_COVID/yolov5/runs/detect/exp2\"\ndirs = os.listdir(path)\nimage_random_number = 16\nimage_lists = os.listdir(path)\n\ndef process(img):\n    image = mpimg.imread(img)\n    plt.figure()\n    plt.imshow(image)\n\n\nprint(image_lists)\nfor i in range(image_random_number):\n  index = random.randint(1,image_random_number)\n  image = image_lists[index]\n  img = os.path.join(path,image)\n  process(img)\n","metadata":{"id":"pgGO6yZcmJxF","outputId":"5c9cf710-c3e8-4482-fbf3-0b4be4ba059f"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"6Py4fP4KnyS2"},"execution_count":null,"outputs":[]}]}