class AccuracyAndF1(Metric): """ Encapsulates Accuracy, Precision, Recall and F1 metric logic. """ def __init__(self, topk=(1, ), pos_label=1, name='acc_and_f1', *args, **kwargs): super(AccuracyAndF1, self).__init__(*args, **kwargs) self.topk = topk self.pos_label = pos_label self._name = name self.acc = Accuracy(self.topk, *args, **kwargs) self.precision = Precision(*args, **kwargs) self.recall = Recall(*args, **kwargs) self.reset() def compute(self, pred, label, *args): self.label = label self.preds_pos = paddle.nn.functional.softmax(pred)[:, self.pos_label] return self.acc.compute(pred, label) def update(self, correct, *args): self.acc.update(correct) self.precision.update(self.preds_pos, self.label) self.recall.update(self.preds_pos, self.label) def accumulate(self): acc = self.acc.accumulate() precision = self.precision.accumulate() recall = self.recall.accumulate() if precision == 0.0 or recall == 0.0: f1 = 0.0 else: # 1/f1 = 1/2 * (1/precision + 1/recall) f1 = (2 * precision * recall) / (precision + recall) return ( acc, precision, recall, f1, (acc + f1) / 2, ) def reset(self): self.acc.reset() self.precision.reset() self.recall.reset() self.label = None self.preds_pos = None def name(self): """ Return name of metric instance. """ return self._name
class AccuracyAndF1(Metric): """ This class encapsulates Accuracy, Precision, Recall and F1 metric logic, and `accumulate` function returns accuracy, precision, recall and f1. The overview of all metrics could be seen at the document of `paddle.metric <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api/paddle/metric/Overview_cn.html>`_ for details. Args: topk (int or tuple(int), optional): Number of top elements to look at for computing accuracy. Defaults to (1,). pos_label (int, optional): The positive label for calculating precision and recall. Defaults to 1. name (str, optional): String name of the metric instance. Defaults to 'acc_and_f1'. Example: .. code-block:: import paddle from paddlenlp.metrics import AccuracyAndF1 x = paddle.to_tensor([[0.1, 0.9], [0.5, 0.5], [0.6, 0.4], [0.7, 0.3]]) y = paddle.to_tensor([[1], [0], [1], [1]]) m = AccuracyAndF1() correct = m.compute(x, y) m.update(correct) res = m.accumulate() print(res) # (0.5, 0.5, 0.3333333333333333, 0.4, 0.45) """ def __init__(self, topk=(1, ), pos_label=1, name='acc_and_f1', *args, **kwargs): super(AccuracyAndF1, self).__init__(*args, **kwargs) self.topk = topk self.pos_label = pos_label self._name = name self.acc = Accuracy(self.topk, *args, **kwargs) self.precision = Precision(*args, **kwargs) self.recall = Recall(*args, **kwargs) self.reset() def compute(self, pred, label, *args): """ Accepts network's output and the labels, and calculates the top-k (maximum value in topk) indices for accuracy. Args: pred (Tensor): Predicted tensor, and its dtype is float32 or float64, and has a shape of [batch_size, num_classes]. label (Tensor): The ground truth tensor, and its dtype is is int64, and has a shape of [batch_size, 1] or [batch_size, num_classes] in one hot representation. Returns: Tensor: Correct mask, each element indicates whether the prediction equals to the label. Its' a tensor with a data type of float32 and has a shape of [batch_size, topk]. """ self.label = label self.preds_pos = paddle.nn.functional.softmax(pred)[:, self.pos_label] return self.acc.compute(pred, label) def update(self, correct, *args): """ Updates the metrics states (accuracy, precision and recall), in order to calculate accumulated accuracy, precision and recall of all instances. Args: correct (Tensor): Correct mask for calculating accuracy, and it's a tensor with shape [batch_size, topk] and has a dtype of float32. """ self.acc.update(correct) self.precision.update(self.preds_pos, self.label) self.recall.update(self.preds_pos, self.label) def accumulate(self): """ Calculates and returns the accumulated metric. Returns: tuple: The accumulated metric. A tuple of shape (acc, precision, recall, f1, average_of_acc_and_f1) With the fileds: - acc (numpy.float64): The accumulated accuracy. - precision (numpy.float64): The accumulated precision. - recall (numpy.float64): The accumulated recall. - f1 (numpy.float64): The accumulated f1. - average_of_acc_and_f1 (numpy.float64): The average of accumulated accuracy and f1. """ acc = self.acc.accumulate() precision = self.precision.accumulate() recall = self.recall.accumulate() if precision == 0.0 or recall == 0.0: f1 = 0.0 else: # 1/f1 = 1/2 * (1/precision + 1/recall) f1 = (2 * precision * recall) / (precision + recall) return ( acc, precision, recall, f1, (acc + f1) / 2, ) def reset(self): """ Resets all metric states. """ self.acc.reset() self.precision.reset() self.recall.reset() self.label = None self.preds_pos = None def name(self): """ Returns name of the metric instance. Returns: str: The name of the metric instance. """ return self._name