# scripts/train.py --workers 12 --checkpoint project22_no3dcgloss_smaldogsilvia_v0 --loss-weight-path barc_loss_weights_no3dcgloss.json --config barc_cfg_train.yaml start --model-file-hg hg_ksp_fromnewanipose_stanext_v0/checkpoint.pth.tar --model-file-3d barc_normflow_pret/checkpoint.pth.tar import torch import torch.backends.cudnn import torch.nn.parallel from tqdm import tqdm import os import json import pathlib import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../', 'src')) # from stacked_hourglass.loss import joints_mse_loss from stacked_hourglass.loss import joints_mse_loss_onKPloc from stacked_hourglass.utils.evaluation import accuracy, AverageMeter, final_preds, get_preds, get_preds_soft from stacked_hourglass.utils.transforms import fliplr, flip_back from stacked_hourglass.utils.visualization import save_input_image_with_keypoints def do_training_step(model, optimiser, input, target, meta, data_info, target_weight=None): assert model.training, 'model must be in training mode.' assert len(input) == len(target), 'input and target must contain the same number of examples.' with torch.enable_grad(): # Forward pass and loss calculation. output = model(input) # original: loss = sum(joints_mse_loss(o, target, target_weight) for o in output) # NEW: loss = sum(joints_mse_loss_onKPloc(o, target, meta, target_weight) for o in output) # Backward pass and parameter update. optimiser.zero_grad() loss.backward() optimiser.step() return output[-1], loss.item() def do_training_epoch(train_loader, model, device, data_info, optimiser, quiet=False, acc_joints=None): losses = AverageMeter() accuracies = AverageMeter() # Put the model in training mode. model.train() iterable = enumerate(train_loader) progress = None if not quiet: progress = tqdm(iterable, desc='Train', total=len(train_loader), ascii=True, leave=False) iterable = progress for i, (input, target, meta) in iterable: input, target = input.to(device), target.to(device, non_blocking=True) target_weight = meta['target_weight'].to(device, non_blocking=True) output, loss = do_training_step(model, optimiser, input, target, meta, data_info, target_weight) acc = accuracy(output, target, acc_joints) # measure accuracy and record loss losses.update(loss, input.size(0)) accuracies.update(acc[0], input.size(0)) # Show accuracy and loss as part of the progress bar. if progress is not None: progress.set_postfix_str('Loss: {loss:0.4f}, Acc: {acc:6.2f}'.format( loss=losses.avg, acc=100 * accuracies.avg )) return losses.avg, accuracies.avg def do_validation_step(model, input, target, meta, data_info, target_weight=None, flip=False): # assert not model.training, 'model must be in evaluation mode.' assert len(input) == len(target), 'input and target must contain the same number of examples.' # Forward pass and loss calculation. output = model(input) # original: loss = sum(joints_mse_loss(o, target, target_weight) for o in output) # NEW: loss = sum(joints_mse_loss_onKPloc(o, target, meta, target_weight) for o in output) # Get the heatmaps. if flip: # If `flip` is true, perform horizontally flipped inference as well. This should # result in more robust predictions at the expense of additional compute. flip_input = fliplr(input) flip_output = model(flip_input) flip_output = flip_output[-1].cpu() flip_output = flip_back(flip_output.detach(), data_info.hflip_indices) heatmaps = (output[-1].cpu() + flip_output) / 2 else: heatmaps = output[-1].cpu() return heatmaps, loss.item() def do_validation_epoch(val_loader, model, device, data_info, flip=False, quiet=False, acc_joints=None, save_imgs_path=None): losses = AverageMeter() accuracies = AverageMeter() predictions = [None] * len(val_loader.dataset) if save_imgs_path is not None: pathlib.Path(save_imgs_path).mkdir(parents=True, exist_ok=True) # Put the model in evaluation mode. model.eval() iterable = enumerate(val_loader) progress = None if not quiet: progress = tqdm(iterable, desc='Valid', total=len(val_loader), ascii=True, leave=False) iterable = progress for i, (input, target, meta) in iterable: # Copy data to the training device (eg GPU). input = input.to(device, non_blocking=True) target = target.to(device, non_blocking=True) target_weight = meta['target_weight'].to(device, non_blocking=True) # import pdb; pdb.set_trace() heatmaps, loss = do_validation_step(model, input, target, meta, data_info, target_weight, flip) # Calculate PCK from the predicted heatmaps. acc = accuracy(heatmaps, target.cpu(), acc_joints) # Calculate locations in original image space from the predicted heatmaps. preds = final_preds(heatmaps, meta['center'], meta['scale'], [64, 64]) # NEW for visualization: (and redundant, but for visualization) preds_unprocessed, preds_unprocessed_maxval = get_preds_soft(heatmaps, return_maxval=True) # preds_unprocessed, preds_unprocessed_norm, preds_unprocessed_maxval = get_preds_soft(heatmaps, return_maxval=True, norm_and_unnorm_coords=True) # import pdb; pdb.set_trace() ind = 0 for example_index, pose in zip(meta['index'], preds): predictions[example_index] = pose # NEW for visualization if save_imgs_path is not None: out_name = os.path.join(save_imgs_path, 'res_' + str( example_index.item()) + '.png') pred_unp = preds_unprocessed[ind, :, :] pred_unp_maxval = preds_unprocessed_maxval[ind, :, :] pred_unp_prep = torch.cat((pred_unp, pred_unp_maxval), 1) inp_img = input[ind, :, :, :] # the following line (with -1) should not be needed anymore after cvpr (after bugfix01 in data preparation 08.09.2022) # pred_unp_prep[:, :2] = pred_unp_prep[:, :2] - 1 # save_input_image_with_keypoints(inp_img, pred_unp_prep, out_path=out_name, threshold=0.1, print_scores=True) # here we have default ratio_in_out=4. # NEW: 08.09.2022 after bugfix01 # import pdb; pdb.set_trace() pred_unp_prep[:, :2] = pred_unp_prep[:, :2] * 4 if 'name' in meta.keys(): # we do this for the stanext set name = meta['name'][ind] out_path_keyp_img = os.path.join(os.path.dirname(out_name), name) out_path_json = os.path.join(os.path.dirname(out_name), name).replace('_vis', '_json').replace('.jpg', '.json') if not os.path.exists(os.path.dirname(out_path_json)): os.makedirs(os.path.dirname(out_path_json)) if not os.path.exists(os.path.dirname(out_path_keyp_img)): os.makedirs(os.path.dirname(out_path_keyp_img)) save_input_image_with_keypoints(inp_img, pred_unp_prep, out_path=out_path_keyp_img, ratio_in_out=1.0, threshold=0.1, print_scores=True) # threshold=0.3 out_name_json = out_path_json # os.path.join(save_imgs_path, 'res_' + str( example_index.item()) + '.json') res_dict = { 'pred_joints_256': list(pred_unp_prep.cpu().numpy().astype(float).reshape((-1))), 'center': list(meta['center'][ind, :].cpu().numpy().astype(float).reshape((-1))), 'scale': meta['scale'][ind].item()} with open(out_name_json, 'w') as outfile: json.dump(res_dict, outfile) else: save_input_image_with_keypoints(inp_img, pred_unp_prep, out_path=out_name, ratio_in_out=1.0, threshold=0.1, print_scores=True) # threshold=0.3 '''# animalpose_hg8_v0 (did forget to subtract 1 in dataset) pred_unp_prep[:, :2] = pred_unp_prep[:, :2] * 4 ############ Why is this necessary??? pred_unp_prep[:, :2] = pred_unp_prep[:, :2] - 1 save_input_image_with_keypoints(inp_img, pred_unp_prep, out_path=out_name, ratio_in_out=1.0, threshold=0.1, print_scores=True) # threshold=0.3 out_name_json = os.path.join(save_imgs_path, 'res_' + str( example_index.item()) + '.json') res_dict = { 'pred_joints_256': list(pred_unp_prep.cpu().numpy().astype(float).reshape((-1))), 'center': list(meta['center'][ind, :].cpu().numpy().astype(float).reshape((-1))), 'scale': meta['scale'][ind].item()} with open(out_name_json, 'w') as outfile: json.dump(res_dict, outfile)''' ind += 1 # Record accuracy and loss for this batch. losses.update(loss, input.size(0)) accuracies.update(acc[0].item(), input.size(0)) # Show accuracy and loss as part of the progress bar. if progress is not None: progress.set_postfix_str('Loss: {loss:0.4f}, Acc: {acc:6.2f}'.format( loss=losses.avg, acc=100 * accuracies.avg )) predictions = torch.stack(predictions, dim=0) return losses.avg, accuracies.avg, predictions