Download lib/core/function.py from dashgaming/slyte: direct link, hf CLI and curl.
- Browser
- Download file 13 kB
-
https://huggingface.co/dashgaming/slyte/resolve/main/lib/core/function.py
- Command line
-
hf download hf://dashgaming/slyte/lib/core/function.py
-
curl -L -o function.py https://huggingface.co/dashgaming/slyte/resolve/main/lib/core/function.py
13 kB
| # ------------------------------------------------------------------------------ | |
| # Copyright (c) Microsoft | |
| # Licensed under the MIT License. | |
| # Written by Bin Xiao (Bin.Xiao@microsoft.com) | |
| # ------------------------------------------------------------------------------ | |
| from __future__ import absolute_import | |
| from __future__ import division | |
| from __future__ import print_function | |
| import time | |
| import logging | |
| import os | |
| import numpy as np | |
| import torch | |
| import torch.nn.functional as F | |
| from core.evaluate import accuracy | |
| from core.inference import get_final_preds | |
| from utils.transforms import flip_back, transform_preds | |
| from utils.vis import save_debug_images | |
| logger = logging.getLogger(__name__) | |
| def train(config, train_loader, train_dataset, model, criterion, optimizer, epoch, | |
| output_dir, tb_log_dir, writer_dict): | |
| batch_time = AverageMeter() | |
| data_time = AverageMeter() | |
| losses = AverageMeter() | |
| acc = AverageMeter() | |
| # switch to train mode | |
| model.train() | |
| end = time.time() | |
| for i, (input, target, target_weight, meta) in enumerate(train_loader): | |
| # measure data loading time | |
| data_time.update(time.time() - end) | |
| target = target.cuda(non_blocking=True).float() | |
| target_weight = target_weight.cuda(non_blocking=True).float() | |
| cat_ids = meta['category_id'] | |
| c = meta['center'].numpy() | |
| s = meta['scale'].numpy() | |
| score = meta['score'].numpy() | |
| channel_mask = torch.zeros_like(target_weight).float() | |
| for j, cat_id in enumerate(cat_ids): | |
| rg = train_dataset.gt_class_keypoints_dict[int(cat_id)] | |
| index = torch.tensor([list(range(rg[0], rg[1]))], device=channel_mask.device, dtype=channel_mask.dtype).transpose(1,0).long() | |
| channel_mask[j].scatter_(0, index, 1) | |
| # compute output | |
| output = model(input) | |
| if config.MODEL.TARGET_TYPE == 'gaussian': | |
| # block irrelevant channels in output | |
| output = output * channel_mask.unsqueeze(3) | |
| preds, maxvals = get_final_preds(config, output.detach().cpu().numpy(), c, s) | |
| elif config.MODEL.TARGET_TYPE == 'coordinate': | |
| heatmap, output = output | |
| # block irrelevant channels in output | |
| output = output * channel_mask | |
| preds_local, maxvals = get_final_preds(config, output.detach().cpu().numpy(), c, s, heatmap.detach().cpu().numpy()) | |
| # Transform back from heatmap coordinate to image coordinate | |
| preds = preds_local.copy() | |
| for i in range(preds_local.shape[0]): | |
| preds[i] = transform_preds( | |
| preds_local[i], c[i], s[i], | |
| [config.MODEL.HEATMAP_SIZE[0], config.MODEL.HEATMAP_SIZE[1]] | |
| ) | |
| else: | |
| raise NotImplementedError('{} is not implemented'.format(config.MODEL.TARGET_TYPE)) | |
| loss = criterion(output, target, target_weight) | |
| # compute gradient and do update step | |
| optimizer.zero_grad() | |
| loss.backward() | |
| optimizer.step() | |
| losses.update(loss.item(), input.size(0)) | |
| _, avg_acc, cnt, pred = accuracy(output.detach().cpu().numpy(), | |
| target.detach().cpu().numpy(), | |
| train_dataset.target_type) | |
| acc.update(avg_acc, cnt) | |
| # measure elapsed time | |
| batch_time.update(time.time() - end) | |
| end = time.time() | |
| if i % config.PRINT_FREQ == 0: | |
| msg = 'Epoch: [{0}][{1}/{2}]\t' \ | |
| 'Time {batch_time.val:.3f}s ({batch_time.avg:.3f}s)\t' \ | |
| 'Speed {speed:.1f} samples/s\t' \ | |
| 'Data {data_time.val:.3f}s ({data_time.avg:.3f}s)\t' \ | |
| 'Loss {loss.val:.6f} ({loss.avg:.6f})\t' \ | |
| 'acc {acc.val:.3f} ({acc.avg:.3f})'.format( | |
| epoch, i, len(train_loader), batch_time=batch_time, | |
| speed=input.size(0)/batch_time.val, | |
| data_time=data_time, loss=losses, acc=acc) | |
| logger.info(msg) | |
| writer = writer_dict['writer'] | |
| global_steps = writer_dict['train_global_steps'] | |
| writer.add_scalar('train_loss', losses.val, global_steps) | |
| writer.add_scalar('train_acc', acc.val, global_steps) | |
| writer_dict['train_global_steps'] = global_steps + 1 | |
| prefix = '{}_{}'.format(os.path.join(output_dir, 'train'), i) | |
| save_debug_images(config, input, meta, target, preds_local, output, prefix) | |
| def validate(config, val_loader, val_dataset, model, criterion, output_dir, | |
| tb_log_dir, writer_dict=None): | |
| batch_time = AverageMeter() | |
| losses = AverageMeter() | |
| acc = AverageMeter() | |
| # switch to evaluate mode | |
| model.eval() | |
| num_samples = len(val_dataset) | |
| all_preds = np.zeros( | |
| (num_samples, config.MODEL.NUM_JOINTS, 3), | |
| dtype=np.float32 | |
| ) | |
| all_boxes = np.zeros((num_samples, 7)) | |
| image_path = [] | |
| filenames = [] | |
| imgnums = [] | |
| idx = 0 | |
| with torch.no_grad(): | |
| end = time.time() | |
| for i, (input, target, target_weight, meta) in enumerate(val_loader): | |
| target = target.cuda(non_blocking=True).float() | |
| target_weight = target_weight.cuda(non_blocking=True).float() | |
| cat_ids = meta['category_id'] | |
| c = meta['center'].numpy() | |
| s = meta['scale'].numpy() | |
| score = meta['score'].numpy() | |
| channel_mask = torch.zeros_like(target_weight).float() | |
| for j, cat_id in enumerate(cat_ids): | |
| rg = val_dataset.gt_class_keypoints_dict[int(cat_id)] | |
| index = torch.tensor([list(range(rg[0], rg[1]))], device=channel_mask.device, dtype=channel_mask.dtype).transpose(1,0).long() | |
| channel_mask[j].scatter_(0, index, 1) | |
| # compute output | |
| output = model(input) | |
| if config.MODEL.TARGET_TYPE == 'gaussian': | |
| if config.TEST.FLIP_TEST: | |
| # this part is ugly, because pytorch has not supported negative index | |
| # input_flipped = model(input[:, :, :, ::-1]) | |
| input_flipped = np.flip(input.cpu().numpy(), 3).copy() | |
| input_flipped = torch.from_numpy(input_flipped).cuda() | |
| outputs_flipped = model(input_flipped) | |
| if isinstance(outputs_flipped, list): | |
| output_flipped = outputs_flipped[-1] | |
| else: | |
| output_flipped = outputs_flipped | |
| output_flipped = output_flipped.cpu().numpy() | |
| category_id_list = meta['category_id'].cpu().numpy().copy() | |
| for j, category_id in enumerate(category_id_list): | |
| output_flipped[j, :, :, :] = flip_back(output_flipped[j, None], | |
| val_dataset.flip_pairs[category_id-1], | |
| config.MODEL.HEATMAP_SIZE[0]) | |
| output_flipped = torch.from_numpy(output_flipped.copy()).cuda() | |
| # feature is not aligned, shift flipped heatmap for higher accuracy | |
| if config.TEST.SHIFT_HEATMAP: | |
| output_flipped[:, :, :, 1:] = \ | |
| output_flipped.clone()[:, :, :, 0:-1] | |
| output = (output + output_flipped) * 0.5 | |
| # block irrelevant channels in output | |
| output = output * channel_mask.unsqueeze(3) | |
| preds_local, maxvals = get_final_preds(config, output.detach().cpu().numpy(), c, s) | |
| # Transform back from heatmap coordinate to image coordinate | |
| preds = preds_local.copy() | |
| for i in range(preds_local.shape[0]): | |
| preds[i] = transform_preds( | |
| preds_local[i], c[i], s[i], | |
| [config.MODEL.HEATMAP_SIZE[0], config.MODEL.HEATMAP_SIZE[1]] | |
| ) | |
| else: | |
| raise NotImplementedError('{} is not implemented'.format(config.MODEL.TARGET_TYPE)) | |
| loss = criterion(output, target, target_weight) | |
| num_images = input.size(0) | |
| # measure accuracy and record loss | |
| losses.update(loss.item(), num_images) | |
| _, avg_acc, cnt, pred = accuracy(output.detach().cpu().numpy(), | |
| target.detach().cpu().numpy(), | |
| val_dataset.target_type) | |
| acc.update(avg_acc, cnt) | |
| # measure elapsed time | |
| batch_time.update(time.time() - end) | |
| end = time.time() | |
| all_preds[idx:idx + num_images, :, 0:2] = preds[:, :, 0:2] | |
| all_preds[idx:idx + num_images, :, 2:3] = maxvals | |
| # double check this all_boxes parts | |
| all_boxes[idx:idx + num_images, 0:2] = c[:, 0:2] | |
| all_boxes[idx:idx + num_images, 2:4] = s[:, 0:2] | |
| all_boxes[idx:idx + num_images, 4] = np.prod(s*200, 1) | |
| all_boxes[idx:idx + num_images, 5] = score | |
| all_boxes[idx:idx + num_images, 6] = meta['category_id'].cpu().numpy().astype(int) | |
| image_path.extend(meta['image']) | |
| idx += num_images | |
| if i % config.PRINT_FREQ == 0: | |
| msg = 'Test: [{0}/{1}]\t' \ | |
| 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' \ | |
| 'Loss {loss.val:.5f} ({loss.avg:.5f})\t' \ | |
| 'acc {acc.val:.3f} ({acc.avg:.3f})'.format( | |
| i, len(val_loader), batch_time=batch_time, | |
| loss=losses, acc=acc) | |
| logger.info(msg) | |
| prefix = '{}_{}'.format( | |
| os.path.join(output_dir, 'val'), i | |
| ) | |
| save_debug_images(config, input, meta, target, preds_local, output, prefix) | |
| name_values, perf_indicator = val_dataset.evaluate( | |
| config, all_preds, output_dir, all_boxes, image_path, | |
| filenames, imgnums | |
| ) | |
| model_name = config.MODEL.NAME | |
| if isinstance(name_values, list): | |
| for name_value in name_values: | |
| _print_name_value(name_value, model_name) | |
| else: | |
| _print_name_value(name_values, model_name) | |
| if writer_dict: | |
| writer = writer_dict['writer'] | |
| global_steps = writer_dict['valid_global_steps'] | |
| writer.add_scalar( | |
| 'valid_loss', | |
| losses.avg, | |
| global_steps | |
| ) | |
| writer.add_scalar( | |
| 'valid_acc', | |
| acc.avg, | |
| global_steps | |
| ) | |
| # if isinstance(name_values, list): | |
| # for name_value in name_values: | |
| # writer.add_scalars( | |
| # 'valid', | |
| # dict(name_value), | |
| # global_steps | |
| # ) | |
| # else: | |
| # writer.add_scalars( | |
| # 'valid', | |
| # dict(name_values), | |
| # global_steps | |
| # ) | |
| writer.add_scalar( | |
| 'valid_AP', | |
| perf_indicator, | |
| global_steps | |
| ) | |
| writer_dict['valid_global_steps'] = global_steps + 1 | |
| return perf_indicator | |
| # markdown format output | |
| def _print_name_value(name_value, full_arch_name): | |
| names = name_value.keys() | |
| values = name_value.values() | |
| num_values = len(name_value) | |
| logger.info( | |
| '| Arch ' + | |
| ' '.join(['| {}'.format(name) for name in names]) + | |
| ' |' | |
| ) | |
| logger.info('|---' * (num_values+1) + '|') | |
| if len(full_arch_name) > 15: | |
| full_arch_name = full_arch_name[:8] + '...' | |
| logger.info( | |
| '| ' + full_arch_name + ' ' + | |
| ' '.join(['| {:.4f}'.format(value) for value in values]) + | |
| ' |' | |
| ) | |
| class AverageMeter(object): | |
| """Computes and stores the average and current value""" | |
| def __init__(self): | |
| self.reset() | |
| def reset(self): | |
| self.val = 0 | |
| self.avg = 0 | |
| self.sum = 0 | |
| self.count = 0 | |
| def update(self, val, n=1): | |
| self.val = val | |
| self.sum += val * n | |
| self.count += n | |
| self.avg = self.sum / self.count if self.count != 0 else 0 | |