def evaluate(self, dataloader, epoch, writer, logger, data_name='val'): total_loss = 0. for i, sample in enumerate(dataloader): utils.progress_bar(i, len(dataloader), 'Eva... ') with torch.no_grad(): loss = self.forward(sample) total_loss += loss.item() logger.info( f'Eva({data_name}) epoch {epoch}, total loss: {total_loss}.')
def centroids_cal(self, dataloader): #在embedding模式下生成mem,建议在train里的if opt.load 和 model.train()之间添加model.centroids_cal(train_dataloader) centroids = torch.zeros(50030, self.feature_nums).to(opt.device) # print('Calculating centroids.') self.eval() with torch.set_grad_enabled(False): for i, data in enumerate(dataloader): utils.progress_bar(i, len(dataloader), 'Calculating centroids...') inputs, labels = data['input'], data['label'] inputs = inputs.to(opt.device) direct_features = self.direct_feature(inputs) for i in range(len(labels)): label = labels[i] centroids[label] += direct_features[i] # Average summed features with class count centroids /= torch.tensor(self.class_count(train_dataset)).float().unsqueeze(1).to(opt.device) #class count为每一类的样本数,需要单独写。 self.mem = centroids
def tta_inference(forward_func, img, nw, nh, patch_w=256, patch_h=256, padding_w=0, padding_h=0, progress_idx=None): tta = OverlapTTA(img, nw, nh, patch_w, patch_h, padding_w, padding_h) with torch.no_grad(): for j, x in enumerate(tta): # 获取每个patch输入 if progress_idx is not None: idx, tot = progress_idx progress_bar(idx * len(tta) + j, tot * len(tta), 'TTA... ') generated = forward_func(x) # torch.cuda.empty_cache() tta.collect(generated[0], j) # 收集inference结果 output = tta.combine() return output
'label'] # ['label'], data['image'] # img_var = Variable(img, requires_grad=False).to(device=opt.device) label_var = Variable(label, requires_grad=False).to(device=opt.device) ############################## # Update parameters ############################## update = model.update(img_var, label_var) recovered = update.get('recovered') pre_msg = 'Epoch:%d' % epoch msg = f'lr:{round(scheduler.get_lr()[0], 6) : .6f} (loss) {str(model.avg_meters)} ETA: {utils.format_time(remaining)}' utils.progress_bar(iteration, len(train_dataloader), pre_msg, msg) # print(pre_msg, msg) if global_step % 1000 == 0: write_meters_loss(writer, 'train', model.avg_meters, global_step) logger.info( f'Train epoch: {epoch}, lr: {round(scheduler.get_lr()[0], 6) : .6f}, (loss) ' + str(model.avg_meters)) if epoch % opt.save_freq == 0 or epoch == opt.epochs: # 最后一个epoch要保存一下 model.save(epoch) #################### # Validation
for iteration, sample in enumerate(train_dataloader): global_step += 1 # 计算剩余时间 rate = (global_step - start_step) / (time.time() - start) remaining = (total_steps - global_step) / rate # 更新模型参数 update_return = model.update(sample) # 获取当前学习率 lr = model.get_lr() lr = lr if lr is not None else opt.lr # 显示进度条 msg = f'lr:{round(lr, 6) : .6f} (loss) {str(model.avg_meters)} ETA: {utils.format_time(remaining)}' utils.progress_bar(iteration, len(train_dataloader), 'Epoch:%d' % epoch, msg) # 训练时每1000个step记录一下summary if global_step % 1000 == 0: write_meters_loss(writer, 'train', model.avg_meters, global_step) model.write_train_summary(update_return) # 每个epoch结束后的显示信息 logger.info(f'Train epoch: {epoch}, lr: {round(lr, 6) : .6f}, (loss) ' + str(model.avg_meters)) if epoch % opt.save_freq == 0 or epoch == opt.epochs: # 最后一个epoch要保存一下 model.save(epoch) # 训练中验证 if epoch % opt.eval_freq == 0:
def eval_mAP(self, dataloader, epoch, writer, logger, data_name='val'): # eval_yolo(self.detector, dataloader, epoch, writer, logger, dataname=data_name) pred_bboxes = [] pred_labels = [] pred_scores = [] gt_bboxes = [] gt_labels = [] gt_difficults = [] with torch.no_grad(): for i, sample in enumerate(dataloader): utils.progress_bar(i, len(dataloader), 'Eva... ') image = sample['image'].to(opt.device) gt_bbox = sample['bboxes'] labels = sample['labels'] paths = sample['path'] batch_bboxes, batch_labels, batch_scores = self.forward(image) pred_bboxes.extend(batch_bboxes) pred_labels.extend(batch_labels) pred_scores.extend(batch_scores) for b in range(len(gt_bbox)): gt_bboxes.append(gt_bbox[b].detach().cpu().numpy()) gt_labels.append(labels[b].int().detach().cpu().numpy()) gt_difficults.append(np.array([False] * len(gt_bbox[b]))) if opt.vis: # 可视化预测结果 img = tensor2im(image).copy() # for x1, y1, x2, y2 in gt_bbox[0]: # cv2.rectangle(img, (x1,y1), (x2,y2), (0, 255, 0), 2) # 绿色的是gt num = len(batch_scores[0]) visualize_boxes(image=img, boxes=batch_bboxes[0], labels=batch_labels[0].astype(np.int32), probs=batch_scores[0], class_labels=opt.class_names) write_image(writer, f'{data_name}/{i}', 'image', img, epoch, 'HWC') result = [] for iou_thresh in [0.5, 0.55, 0.6, 0.65, 0.7, 0.75]: AP = eval_detection_voc(pred_bboxes, pred_labels, pred_scores, gt_bboxes, gt_labels, gt_difficults=None, iou_thresh=iou_thresh, use_07_metric=False) APs = AP['ap'] mAP = AP['map'] result.append(mAP) logger.info( f'Eva({data_name}) epoch {epoch}, IoU: {iou_thresh}, APs: {str(APs[:opt.num_classes])}, mAP: {mAP}' ) write_loss(writer, f'val/{data_name}', 'mAP', mAP, epoch) logger.info( f'Eva({data_name}) epoch {epoch}, mean of (AP50-AP75): {sum(result)/len(result)}' )
}) opt.width = width opt.height = height voc_dataset = VOCTrainValDataset(voc_root, class_names, split=train_split, format=img_format, transforms=preview_transform) output_file = f'instances_{train_split[:-4]}.json' for i, sample in enumerate(voc_dataset): utils.progress_bar(i, len(voc_dataset), 'Drawing...') image = sample['image'] bboxes = sample['bboxes'].cpu().numpy() labels = sample['labels'].cpu().numpy() image_path = sample['path'] h, w, _ = image.shape global_image_id += 1 coco_dataset['images'].append({ 'file_name': os.path.basename(image_path), 'id': global_image_id, 'width': int(w), 'height': int(h)
# denominator = np.reciprocal(std, dtype=np.float32) img = img.astype(np.float32) # img -= mean # img *= denominator img *= std img += mean return img CanChinese = False for i, sample in enumerate(previewed): # if i > 30: # break utils.progress_bar(i, len(previewed), 'Handling...') if opt.debug: ipdb.set_trace() image = sample['input'][0].detach().cpu().numpy().transpose([1, 2, 0]) # image = (image.copy() image = (denormalize(image, max_pixel_value=1.0) * 255).astype( np.uint8).copy() label = sample['label'][0].item() if CanChinese: name = names[str(label)] image = cv2ImgAddText(image, name, 7, 3, (255, 0, 0), textSize=24) else: cv2.putText(image, 'label: ' + str(label), (10, 30), 0, 1, (255, 0, 0),
opt.which_epoch = model.load(opt.load) model.eval() with open('submission.csv', 'w') as f: # 如果在windows下打开csv出现空行的情况,加一个newline=''参数 csv_writer = csv.writer(f) csv_writer.writerow(['id', 'predicted']) # 写一行 for i, data in enumerate(dataloader): input, path = data['input'], data['path'] if 'label' in data: label = data['label'] utils.progress_bar(i, len(dataloader), 'Testing... ') # ct_num += 1 with torch.no_grad(): img_var = Variable(input, requires_grad=False).to(device=opt.device) predicted = model(img_var) _, predicted = torch.max(predicted, 1) # ct_num += label.size(0) # correct += (predicted == label_var).sum().item() # ipdb.set_trace() for idx in range(len(path)): # batch filename = os.path.basename(path[idx]) line = [filename, predicted[idx].item()] csv_writer.writerow(line) # 写一行
if not opt.load: raise Exception( 'Checkpoint must be specified at test phase, try --load <checkpoint_dir>' ) Model = get_model(opt.model) model = Model(opt) model = model.to(device=opt.device) model.eval() load_epoch = model.load(opt.load) result_dir = os.path.join(opt.result_dir, opt.tag, str(load_epoch)) utils.try_make_dir(result_dir) for i, data in enumerate(dl.test_dataloader): utils.progress_bar(i, len(dl.test_dataloader), 'Test... ') img, paths = data['input'], data['path'] img = img.to(device=opt.device) """ Test Codes """ filename = utils.get_file_name(paths[0]) res = model.inference(img, progress_idx=(i, len(dl.test_dataloader))) # 保存结果 save_path = os.path.join(result_dir, filename + '.png') Image.fromarray(res).save(save_path)
def __init__(self, voc_root, class_names, split='train.txt', format='jpg', transforms=None, max_size=None, use_cache=False, use_difficult=False): utils.color_print(f'Use dataset: {voc_root}, split: {split[:-4]}', 3) im_list = os.path.join(voc_root, f'ImageSets/Main/{split}') image_root = os.path.join(voc_root, 'JPEGImages') self.image_paths = [] self.bboxes = [] self.labels = [] self.difficults = [] counter = defaultdict(int) tot_bbox = 0 difficult_bbox = 0 """ 如果有缓存的pickle文件,就直接从pickle文件读取bboxes """ os.makedirs('.cache', exist_ok=True) cache_file = os.path.join( '.cache', f'{os.path.basename(voc_root)}_{split[:-4]}.pkl') if use_cache and os.path.isfile(cache_file): with open(cache_file, 'rb') as f: data = pickle.load(f, encoding='bytes') utils.color_print(f'Use cached annoations.', 3) self.image_paths, self.bboxes, self.labels, self.difficults, \ counter, tot_bbox, difficult_bbox = data else: # 没有缓存文件 with open(im_list, 'r') as f: lines = f.readlines() for i, line in enumerate(lines): utils.progress_bar(i, len(lines), 'Load Anno...') image_id = line.rstrip('\n') abspath = os.path.abspath( os.path.join(image_root, f'{image_id}.{format}')) self.image_paths.append(abspath) with open( os.path.join(voc_root, f'Annotations/{image_id}.xml'), 'r') as anno: tree = ET.parse(anno) # 解析xml标注 root = tree.getroot() bboxes = [] labels = [] size = root.find('size') width = int(size.find('width').text) height = int(size.find('height').text) for obj in root.iter('object'): # 多个元素 # difficult = obj.find('difficult').text class_name = obj.find('name').text difficult = obj.find('difficult').text if difficult != '0' and not use_difficult: difficult_bbox += 1 continue # 忽略困难样本 if class_name not in class_names: continue # class_names中没有的类别是忽略还是报错 raise Exception( f'"{class_name}" not in class names({class_names}).' ) class_id = class_names.index(class_name) bbox = obj.find('bndbox') x1 = limit(int(bbox.find('xmin').text), 0, width) y1 = limit(int(bbox.find('ymin').text), 0, height) x2 = limit(int(bbox.find('xmax').text), 0, width) y2 = limit(int(bbox.find('ymax').text), 0, height) if x2 - x1 <= 2 or y2 - y1 <= 2: # 面积很小的标注 continue counter[class_name] += 1 tot_bbox += 1 bboxes.append([x1, y1, x2, y2]) labels.append(class_id) self.bboxes.append(bboxes) self.labels.append(labels) """ 存放到缓存文件 """ data = [self.image_paths, self.bboxes, self.labels, self.difficults, \ counter, tot_bbox, difficult_bbox] with open(cache_file, 'wb') as f: pickle.dump(data, f) for name in class_names: utils.color_print( f'{name}: {counter[name]} ({counter[name]/tot_bbox*100:.2f}%)', 5) utils.color_print(f'Total bboxes: {tot_bbox}', 4) if difficult_bbox: utils.color_print(f'{difficult_bbox} difficult bboxes ignored.', 1) self.format = format assert transforms is not None, '"transforms" is required' self.transforms = transforms self.max_size = max_size