如何解读:Label Ranking Average Precision Score

How to interpret: Label Ranking Average Precision Score

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

一般来说,我知道精度是
((真阳性)/(真阳性 + 假阳性))

我问这个的原因是我偶然发现了 Kaggle Competition for Audio Tagging 并发现了这个 post 说他们正在使用 LWRAP 函数来计算分数,当有不止一个正确的时候响应中的标签。我开始阅读以了解这个分数是如何计算的,但发现很难解释。我的两个困难是
1) 从文档中解释 Math 函数,我不确定在分数计算中如何使用排名
2) 从代码中解读Numpy数组操作
我正在阅读的功能来自 Google Collab document then I tried reading the documentation at 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

为了更好地理解分数的计算方式,让我们举一个简单的例子。假设我们正在标记可能包含猫、狗、and/or 鸟的图像。 class 数组看起来像 [Cat, Dog, Bird]。因此,如果我们的图像中只包含一只猫,则真值数组的形式为 [1, 0, 0].

我们给模型提供这张只包含一只猫的图像,它输出 [.9, .2, .3]。首先,我们对模型预测的标签进行排序。 Cat 获得第一名,Bird 获得第二名,Dog 获得第三名。现在我们计算从第一名开始需要多少标签才能获得真正的 class 兴趣(猫)。该模型将 Cat 排在第 1 位,因此只需取值为 1。接下来,我们计算在找到正确标签 (Cat) 之前还有多少其他真实标签。乍一看这似乎令人困惑,但稍后的 multi-label 示例将需要它。对于这种情况,Cat 标签是正确的,我们不需要再移动,所以它的值也为 1。Score 的计算方法是取第二个值除以第一个值。在这种情况下,得分为 1/1 = 1。

那么,如果模型出现问题会怎样?让我们将相同的猫图像放在不同的模型中。它输出 [.6, .8, .1]。从头到尾排列标签。 Dog 获得第一名,Cat 获得第二名,Bird 获得第三名。从第一名开始,找出需要多少标签才能找到正确的 class 兴趣(又是 Cat)。对于这个场景,它需要两个标签,所以第一个值为 2。接下来,计算出一路上有多少个正确的标签。只有 1,所以第二个值为 1。对于这种情况,得分为 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。Score = 1/2 = 0.50.

好的,那么我们如何获得每个 class 的 最终分数?最简单的方法是取平均值。让我们用前面两个例子来计算一下。对于 Cat,我们的得分为 1 和 0.66。最终猫得分 = (1+0.66)/2 = 0.83。对于狗,我们的分数仅为 0.50,因此最终狗分数 = 0.50。对于 Bird,我们的得分仅为 1.0,因此最终 Bird 得分 = 1。此指标非常适合分析 class 性能。

我们如何将这些 class 分数压缩成 一个最终分数 ?我们可以对所有最终 class 分数进行平均,但这会稀释常见 classes 的分数并提高不太频繁的 classes。相反,我们可以简单地使用 weighted-average!使用这两个示例图像,我们有 2 只猫、1 只狗和 1 只鸟。最终得分 = (2 Cats/4 个标签)*0.83 + (1 Dog/4 个标签)*0.50 + (1 Bird/4 个标签)*1.0 = 0.79。方便的是,这最终与平均所有个人分数相同,因此我们甚至不需要存储 class 权重。回想一下,第一张图片的猫和鸟的得分分别为 1 和 1,第二张图片的猫和狗的得分分别为 0.66 和 0.50。 (1 + 1 + 0.66 + 0.50)/4 = 0.79.

希望这能让您更好地理解计算。我已经讲了足够长的时间,所以我会将代码留给另一位海报。也许如果没有人很快回答那部分,我可以添加一个 write-up.