eval_utils.py 5.1 KB
Newer Older
1
import pickle
Shaoshuai Shi's avatar
Shaoshuai Shi committed
2
3
import time

4
5
import numpy as np
import torch
Shaoshuai Shi's avatar
Shaoshuai Shi committed
6
7
import tqdm

8
from pcdet.models import load_data_to_gpu
Shaoshuai Shi's avatar
Shaoshuai Shi committed
9
from pcdet.utils import common_utils
10
11
12
13


def statistics_info(cfg, ret_dict, metric, disp_dict):
    for cur_thresh in cfg.MODEL.POST_PROCESSING.RECALL_THRESH_LIST:
14
15
16
        metric['recall_roi_%s' % str(cur_thresh)] += ret_dict.get('roi_%s' % str(cur_thresh), 0)
        metric['recall_rcnn_%s' % str(cur_thresh)] += ret_dict.get('rcnn_%s' % str(cur_thresh), 0)
    metric['gt_num'] += ret_dict.get('gt', 0)
17
18
19
20
21
    min_thresh = cfg.MODEL.POST_PROCESSING.RECALL_THRESH_LIST[0]
    disp_dict['recall_%s' % str(min_thresh)] = \
        '(%d, %d) / %d' % (metric['recall_roi_%s' % str(min_thresh)], metric['recall_rcnn_%s' % str(min_thresh)], metric['gt_num'])


22
def eval_one_epoch(cfg, args, model, dataloader, epoch_id, logger, dist_test=False, result_dir=None):
23
24
    result_dir.mkdir(parents=True, exist_ok=True)

Shaoshuai Shi's avatar
Shaoshuai Shi committed
25
    final_output_dir = result_dir / 'final_result' / 'data'
26
    if args.save_to_file:
27
28
29
30
31
32
33
34
35
36
37
38
39
        final_output_dir.mkdir(parents=True, exist_ok=True)

    metric = {
        'gt_num': 0,
    }
    for cur_thresh in cfg.MODEL.POST_PROCESSING.RECALL_THRESH_LIST:
        metric['recall_roi_%s' % str(cur_thresh)] = 0
        metric['recall_rcnn_%s' % str(cur_thresh)] = 0

    dataset = dataloader.dataset
    class_names = dataset.class_names
    det_annos = []

40
41
42
43
    if getattr(args, 'infer_time', False):
        start_iter = int(len(dataloader) * 0.1)
        infer_time_meter = common_utils.AverageMeter()

44
45
    logger.info('*************** EPOCH %s EVALUATION *****************' % epoch_id)
    if dist_test:
Gus-Guo's avatar
Gus-Guo committed
46
47
48
49
50
51
52
        num_gpus = torch.cuda.device_count()
        local_rank = cfg.LOCAL_RANK % num_gpus
        model = torch.nn.parallel.DistributedDataParallel(
                model,
                device_ids=[local_rank],
                broadcast_buffers=False
        )
53
54
55
56
57
58
    model.eval()

    if cfg.LOCAL_RANK == 0:
        progress_bar = tqdm.tqdm(total=len(dataloader), leave=True, desc='eval', dynamic_ncols=True)
    start_time = time.time()
    for i, batch_dict in enumerate(dataloader):
59
        load_data_to_gpu(batch_dict)
60
61
62
63

        if getattr(args, 'infer_time', False):
            start_time = time.time()

64
65
        with torch.no_grad():
            pred_dicts, ret_dict = model(batch_dict)
66

67
68
        disp_dict = {}

69
70
71
72
73
74
        if getattr(args, 'infer_time', False):
            inference_time = time.time() - start_time
            infer_time_meter.update(inference_time * 1000)
            # use ms to measure inference time
            disp_dict['infer_time'] = f'{infer_time_meter.val:.2f}({infer_time_meter.avg:.2f})'

75
76
77
        statistics_info(cfg, ret_dict, metric, disp_dict)
        annos = dataset.generate_prediction_dicts(
            batch_dict, pred_dicts, class_names,
78
            output_path=final_output_dir if args.save_to_file else None
79
80
81
82
83
84
85
86
87
88
89
        )
        det_annos += annos
        if cfg.LOCAL_RANK == 0:
            progress_bar.set_postfix(disp_dict)
            progress_bar.update()

    if cfg.LOCAL_RANK == 0:
        progress_bar.close()

    if dist_test:
        rank, world_size = common_utils.get_dist_info()
Gus-Guo's avatar
Gus-Guo committed
90
91
        det_annos = common_utils.merge_results_dist(det_annos, len(dataset), tmpdir=result_dir / 'tmpdir')
        metric = common_utils.merge_results_dist([metric], world_size, tmpdir=result_dir / 'tmpdir')
92
93
94
95
96
97
98
99
100
101

    logger.info('*************** Performance of EPOCH %s *****************' % epoch_id)
    sec_per_example = (time.time() - start_time) / len(dataloader.dataset)
    logger.info('Generate label finished(sec_per_example: %.4f second).' % sec_per_example)

    if cfg.LOCAL_RANK != 0:
        return {}

    ret_dict = {}
    if dist_test:
Gus-Guo's avatar
Gus-Guo committed
102
103
104
105
        for key, val in metric[0].items():
            for k in range(1, world_size):
                metric[0][key] += metric[k][key]
        metric = metric[0]
106
107
108
109
110
111
112

    gt_num_cnt = metric['gt_num']
    for cur_thresh in cfg.MODEL.POST_PROCESSING.RECALL_THRESH_LIST:
        cur_roi_recall = metric['recall_roi_%s' % str(cur_thresh)] / max(gt_num_cnt, 1)
        cur_rcnn_recall = metric['recall_rcnn_%s' % str(cur_thresh)] / max(gt_num_cnt, 1)
        logger.info('recall_roi_%s: %f' % (cur_thresh, cur_roi_recall))
        logger.info('recall_rcnn_%s: %f' % (cur_thresh, cur_rcnn_recall))
113
114
        ret_dict['recall/roi_%s' % str(cur_thresh)] = cur_roi_recall
        ret_dict['recall/rcnn_%s' % str(cur_thresh)] = cur_rcnn_recall
115
116
117
118
119
120
121
122
123
124
125
126

    total_pred_objects = 0
    for anno in det_annos:
        total_pred_objects += anno['name'].__len__()
    logger.info('Average predicted number of objects(%d samples): %.3f'
                % (len(det_annos), total_pred_objects / max(1, len(det_annos))))

    with open(result_dir / 'result.pkl', 'wb') as f:
        pickle.dump(det_annos, f)

    result_str, result_dict = dataset.evaluation(
        det_annos, class_names,
Shaoshuai Shi's avatar
Shaoshuai Shi committed
127
128
        eval_metric=cfg.MODEL.POST_PROCESSING.EVAL_METRIC,
        output_path=final_output_dir
129
130
131
132
133
    )

    logger.info(result_str)
    ret_dict.update(result_dict)

souravraha's avatar
souravraha committed
134
    logger.info('Result is saved to %s' % result_dir)
135
136
137
138
139
140
    logger.info('****************Evaluation done.*****************')
    return ret_dict


if __name__ == '__main__':
    pass