6

我是数组编程的新手,发现很难解释 sklearn.metrics label_ranking_average_precision_score 函数。需要您的帮助来理解它的计算方式,并感谢任何学习 Numpy 数组编程的技巧。

一般来说,我知道精度是
((True Positive) / (True Positive + False Positive))

我之所以问这个问题是因为我偶然发现了 Kaggle Competition for Audio Tagging 并看到了这篇文章,说当响应中有多个正确标签时,他们正在使用 LWRAP 函数来计算分数。我开始阅读以了解该分数是如何计算的,但发现很难解释。我的两个困难是
1)从文档中解释 Math 函数,我不确定如何在分数计算中使用排名
2)从代码中解释 Numpy 数组操作
我正在阅读的函数来自Google Collab 文档,然后我尝试阅读文档在sklearn但无法正确理解。

一个样本计算的代码是

# Core calculation of label precisions for one test sample.

def _one_sample_positive_class_precisions(scores, truth):
  """Calculate precisions for each true class for a single sample.

  Args:
    scores: np.array of (num_classes,) giving the individual classifier scores.
    truth: np.array of (num_classes,) bools indicating which classes are true.

  Returns:
    pos_class_indices: np.array of indices of the true classes for this sample.
    pos_class_precisions: np.array of precisions corresponding to each of those
      classes.
  """
  num_classes = scores.shape[0]
  pos_class_indices = np.flatnonzero(truth > 0)
  # Only calculate precisions if there are some true classes.
  if not len(pos_class_indices):
    return pos_class_indices, np.zeros(0)
  # Retrieval list of classes for this sample. 
  retrieved_classes = np.argsort(scores)[::-1]
  # class_rankings[top_scoring_class_index] == 0 etc.
  class_rankings = np.zeros(num_classes, dtype=np.int)
  class_rankings[retrieved_classes] = range(num_classes)
  # Which of these is a true label?
  retrieved_class_true = np.zeros(num_classes, dtype=np.bool)
  retrieved_class_true[class_rankings[pos_class_indices]] = True
  # Num hits for every truncated retrieval list.
  retrieved_cumulative_hits = np.cumsum(retrieved_class_true)
  # Precision of retrieval list truncated at each hit, in order of pos_labels.
  precision_at_hits = (
      retrieved_cumulative_hits[class_rankings[pos_class_indices]] / 
      (1 + class_rankings[pos_class_indices].astype(np.float)))
  return pos_class_indices, precision_at_hits
4

1 回答 1

26

为了更好地理解分数是如何计算的,让我们举一个简单的例子。假设我们正在标记可能包含猫、狗和/或鸟类的图像。类数组看起来像 [Cat, Dog, Bird]。因此,如果我们的图像中只包含一只猫,那么真值数组将具有 [1, 0, 0] 的形式。

我们为模型提供这个只包含一只猫的图像,它输出 [.9, .2, .3]。首先,我们对模型预测的标签进行排名。猫获得第一名,鸟获得第二名,狗获得第三名。现在我们计算从第一名开始到达真正感兴趣的类别(Cat)需要多少标签。该模型将 Cat 排在第一位,因此只需取值 1。接下来,我们计算有多少其他真正的标签,直到我们到达正确的标签 (Cat)。起初这可能看起来令人困惑,但对于稍后的多标签示例来说,这将是必要的。对于这种情况,Cat 标签是正确的,我们不需要进一步移动,所以它的值也为 1。Score 的计算方法是取第二个值除以第一个值。在这种情况下,分数是 1/1 = 1。

那么如果模型出现故障会发生什么?让我们将相同的 Cat 图像放入不同的模型中。它输出 [.6, .8, .1]。将标签从头到尾排列。狗获得第一名,猫获得第二名,鸟获得第三名。找出从第 1 位开始到达正确的兴趣类别(又是 Cat)需要多少个标签。对于这个场景,它需要两个标签,所以第一个值是 2。接下来,计算一路上有多少正确的标签。只有 1,所以第二个值为 1。对于这种情况,Score 为 1/2 = 0.50。

好的,这些都是简单的例子。对于接下来的两个,我不会那么冗长,但应用与上面相同的逻辑。主要区别在于每个正确的标签都需要单独计算。

正确排列两个标签:图像包含猫和鸟 [1, 0, 1]。模型输出 [.8, .2, .9]。排名是鸟,猫,狗。对于 Cat 标签,第一个值为 2(需要两个标签才能到达),第二个值为 2(沿途有两个正确的标签,Bird 和 Cat)。Score = 2/2 = 1。对于 Bird 标签,第一个值为 1,第二个值为 1。Score = 1/1 = 1。

错误地排列两个标签:图像包含猫和狗 [1, 1, 0]。模型输出 [.1, .2, .8]。排名是鸟,狗,猫。对于 Cat 标签,第一个值为 3,第二个值为 2。得分 = 2/3 = 0.66。对于 Dog 标签,第一个值为 2,第二个值为 1。得分 = 1/2 = 0.50。

好的,那么我们如何获得每个班级的最终分数?最简单的方法是取平均值。让我们使用前面的两个例子来计算它。对于 Cat,我们的得分为 1 和 0.66。最终猫分数 = (1+0.66)/2 = 0.83。对于狗,我们只有 0.50 的分数,所以最终的狗分数 = 0.50。对于 Bird,我们的分数仅为 1.0,因此 Final Bird Score = 1。这个指标非常适合分析班级表现。

我们如何将这些班级分数压缩成一个最终分数?我们可以平均所有最终班级的分数,但这会稀释普通班级的分数并提高频率较低的班级。相反,我们可以简单地使用加权平均!使用这两个示例图像,我们有 2 只猫、1 只狗和 1 只鸟。最终得分 =(2 只猫/4 个标签)*0.83 +(1 只狗/4 个标签)*0.50 +(1 只鸟/4 个标签)*1.0 = 0.79。方便的是,这最终与平均所有个人分数相同,因此我们甚至不需要存储班级权重。回想一下,我们对第一张图像的猫和鸟的个人得分分别为 1 和 1,然后对第二张图像的猫和狗的得分分别为 0.66 和 0.50。(1 + 1 + 0.66 + 0.50)/4 = 0.79。

希望这能让您更好地理解计算。我将把代码留给另一张海报,因为我已经无人机了足够长的时间。也许如果没有人很快回答那部分,我可以添加一篇文章。

于 2019-07-02T16:59:16.430 回答