Shortcuts

Source code for mmcls.core.evaluation.multilabel_eval_metrics

# Copyright (c) OpenMMLab. All rights reserved.
import warnings

import numpy as np
import torch


[docs]def average_performance(pred, target, thr=None, k=None): """Calculate CP, CR, CF1, OP, OR, OF1, where C stands for per-class average, O stands for overall average, P stands for precision, R stands for recall and F1 stands for F1-score. Args: pred (torch.Tensor | np.ndarray): The model prediction with shape (N, C), where C is the number of classes. target (torch.Tensor | np.ndarray): The target of each prediction with shape (N, C), where C is the number of classes. 1 stands for positive examples, 0 stands for negative examples and -1 stands for difficult examples. thr (float): The confidence threshold. Defaults to None. k (int): Top-k performance. Note that if thr and k are both given, k will be ignored. Defaults to None. Returns: tuple: (CP, CR, CF1, OP, OR, OF1) """ if isinstance(pred, torch.Tensor) and isinstance(target, torch.Tensor): pred = pred.detach().cpu().numpy() target = target.detach().cpu().numpy() elif not (isinstance(pred, np.ndarray) and isinstance(target, np.ndarray)): raise TypeError('pred and target should both be torch.Tensor or' 'np.ndarray') if thr is None and k is None: thr = 0.5 warnings.warn('Neither thr nor k is given, set thr as 0.5 by ' 'default.') elif thr is not None and k is not None: warnings.warn('Both thr and k are given, use threshold in favor of ' 'top-k.') assert pred.shape == \ target.shape, 'pred and target should be in the same shape.' eps = np.finfo(np.float32).eps target[target == -1] = 0 if thr is not None: # a label is predicted positive if the confidence is no lower than thr pos_inds = pred >= thr else: # top-k labels will be predicted positive for any example sort_inds = np.argsort(-pred, axis=1) sort_inds_ = sort_inds[:, :k] inds = np.indices(sort_inds_.shape) pos_inds = np.zeros_like(pred) pos_inds[inds[0], sort_inds_] = 1 tp = (pos_inds * target) == 1 fp = (pos_inds * (1 - target)) == 1 fn = ((1 - pos_inds) * target) == 1 precision_class = tp.sum(axis=0) / np.maximum( tp.sum(axis=0) + fp.sum(axis=0), eps) recall_class = tp.sum(axis=0) / np.maximum( tp.sum(axis=0) + fn.sum(axis=0), eps) CP = precision_class.mean() * 100.0 CR = recall_class.mean() * 100.0 CF1 = 2 * CP * CR / np.maximum(CP + CR, eps) OP = tp.sum() / np.maximum(tp.sum() + fp.sum(), eps) * 100.0 OR = tp.sum() / np.maximum(tp.sum() + fn.sum(), eps) * 100.0 OF1 = 2 * OP * OR / np.maximum(OP + OR, eps) return CP, CR, CF1, OP, OR, OF1