网站上线流程图,在网站上可以做哪些互动活动,网站建设和编程,饰品交易网站怎么做本系列文章记录本人硕士阶段YOLO系列目标检测算法自学及其代码实现的过程。其中算法具体实现借鉴于ultralytics YOLO源码Github#xff0c;删减了源码中部分内容#xff0c;满足个人科研需求。 本系列文章主要以YOLOv5为例完成算法的实现#xff0c;后续修改、增加相关模… 本系列文章记录本人硕士阶段YOLO系列目标检测算法自学及其代码实现的过程。其中算法具体实现借鉴于ultralytics YOLO源码Github删减了源码中部分内容满足个人科研需求。 本系列文章主要以YOLOv5为例完成算法的实现后续修改、增加相关模块即可实现其他版本的YOLO算法。 文章地址 YOLOv5算法实现(一)算法框架概述 YOLOv5算法实现(二)模型加载 YOLOv5算法实现(三)数据集加载 YOLOv5算法实现(四)损失计算 YOLOv5算法实现(五)预测结果后处理 YOLOv5算法实现(六)评价指标及实现 YOLOv5算法实现(七)模型训练 YOLOv5算法实现(八)模型验证 YOLOv5算法实现(九)模型预测(编辑中…) 本文目录 1 引言2 模型验证(validation.py) 1 引言 本篇文章综合之前文章中的功能实现模型的验证。模型验证的逻辑如图1所示。
图1 模型验证流程 2 模型验证(validation.py)
def validation(parser_data):device torch.device(parser_data.device if torch.cuda.is_available() else cpu)print(Using {} device validation..format(device.type))# read class_indictlabel_json_path ./data/object.jsonassert os.path.exists(label_json_path), json file {} dose not exist..format(label_json_path)with open(label_json_path, r) as f:class_dict json.load(f)category_index {v: k for k, v in class_dict.items()}data_dict parse_data_cfg(parser_data.data)test_path data_dict[valid]# 注意这里的collate_fn是自定义的因为读取的数据包括image和targets不能直接使用默认的方法合成batchbatch_size parser_data.batch_sizenw min([os.cpu_count(), batch_size if batch_size 1 else 0, 8]) # number of workersprint(Using %g dataloader workers % nw)# load validation data setval_dataset LoadImagesAndLabels(test_path, parser_data.img_size, batch_size,hypparser_data.hyp,rectFalse) # 将每个batch的图像调整到合适大小可减少运算量(并不是512x512标准尺寸)val_dataset_loader torch.utils.data.DataLoader(val_dataset,batch_sizebatch_size,shuffleTrue,num_workersnw,pin_memoryTrue,collate_fnval_dataset.collate_fn)# create modelmodel Model(parser_data.cfg, ch3, ncparser_data.nc)weights_dict torch.load(parser_data.weights, map_locationcpu)weights_dict weights_dict[model] if model in weights_dict else weights_dictmodel.load_state_dict(weights_dict, strictFalse)model.to(device)# evaluate on the test dataset# 计算PR曲线和APstats []iouv torch.linspace(0.5, 0.95, 10, devicedevice) # iou vector for mAP0.5:0.95niou iouv.numel()# 混淆矩阵confusion_matrix ConfusionMatrix(nc3, conf0.6)model.eval()with torch.no_grad():for imgs, targets, paths, shapes, img_index in tqdm(val_dataset_loader, descvalidation...):imgs imgs.to(device).float() / 255.0 # uint8 to float32, 0 - 255 to 0.0 - 1.0nb, _, height, width imgs.shape # batch size, channels, height, widthtargets targets.to(device)preds model(imgs)[0] # only get inference resultpreds non_max_suppression(preds, conf_thres0.3, iou_thres0.6, multi_labelFalse)targets[:, 2:] * torch.tensor((width, height, width, height), devicedevice)outputs []for si, pred in enumerate(preds):labels: [clas, x, y, w, h] (训练图像上绝对坐标)pred: [x,y,x,y,obj,cls] (训练图像上绝对坐标)predn: [x,y,x,y,obj,cls] (输入图像上绝对坐标)labels: [x,y,x,y,class] (输入图像上绝对坐标)shapes[si][0]: 输入图像大小shapes[si][1]labels targets[targets[:, 0] si, 1:] # 当前图片的标签信息nl labels.shape[0] # number of labels # 当前图片标签数量if pred is None:npr 0else:npr pred.shape[0] # 预测结果数量correct torch.zeros(npr, niou, dtypetorch.bool, devicedevice) # 判断在不同IoU下预测是否预测正确path, shape Path(paths[si]), shapes[si][0] # 当前图片shape(原图大小)if npr 0: # 若没有预测结果if nl: # 没有预测结果但有实际目标# 不同IoU阈值下预测准确率,目标类别置信度,预测类别,实际类别stats.append((correct, *torch.zeros((2, 0), devicedevice), labels[:, 0]))# 混淆矩阵计算(类别信息)confusion_matrix.process_batch(detectionsNone, labelslabels[:, 0])continuepredn pred.clone()scale_boxes(imgs[si].shape[1:], predn[:, :4], shape, shapes[si][1]) # native-space predif nl: # 有预测结果且有实际目标tbox xywh2xyxy(labels[:, 1:5]) # target boxesscale_boxes(imgs[si].shape[1:], tbox, shape, shapes[si][1]) # native-space labelslabelsn torch.cat((labels[:, 0:1], tbox), 1) # native-space labelscorrect process_batch(predn, labelsn, iouv)confusion_matrix.process_batch(predn, labelsn)stats.append((correct, pred[:, 4], pred[:, 5], labels[:, 0])) # 预测结果在不同IoU是否预测正确, 预测置信度, 预测类别, 实际类别confusion_matrix.plot(save_dirparser_data.save_path, names[normal, defect, leakage])# 图片:预测结果在不同IoU下预测结果,预测置信度,预测类别,实际类别stats [torch.cat(x, 0).cpu().numpy() for x in zip(*stats)] # to numpyif len(stats) and stats[0].any():tp, fp, p, r, f1, ap, ap_class ap_per_class(*stats, names[normal, defect, leakage])ap50, ap ap[:, 0], ap.mean(1) # AP0.5, AP0.5:0.95mp, mr, map50, map p.mean(), r.mean(), ap50.mean(), ap.mean()print(map50)if __name__ __main__:import argparseparser argparse.ArgumentParser(description__doc__)# 使用设备类型parser.add_argument(--device, defaultcuda, helpdevice)# 检测目标类别数parser.add_argument(--nc, typeint, default3, helpnumber of classes)file yolov5scfg fcfg/models/{file}.yamlparser.add_argument(--cfg, typestr, defaultcfg, help*.cfg path)parser.add_argument(--data, typestr, defaultdata/my_data.data, help*.data path)parser.add_argument(--hyp, typestr, defaultcfg/hyps/hyp.scratch-med.yaml, helphyperparameters path)parser.add_argument(--img-size, typeint, default640, helptest size)# 训练好的权重文件weight_1 f./weights/{file}/{file} -best_map.ptweight_2 f./weights/{file}/{file} .ptweight weight_1 if os.path.exists(weight_1) else weight_2parser.add_argument(--weights, defaultweight, typestr, helptraining weights)parser.add_argument(--save_path, defaultfresults/{file}, typestr, helpresult save path)# batch sizeparser.add_argument(--batch_size, default2, typeint, metavarN,helpbatch size when validation.)args parser.parse_args()validation(args)