TATECHATLAS
◎ 简体中文
人工智能

AI 精确率和召回率在小数据集上的评估

了解如何在 AI 模型的小型问题数据集上有效评估精确率和召回率。本指南使用 scikit-learn 涵盖了概念、计算方法和实际注意事项。

本文内容

要评估 AI 模型在小型问题数据集上的精确率和召回率,您需要定义您的真实情况(正确答案)以及模型的预测。然后,使用 scikit-learn 等库来计算这些指标。精确率衡量模型所有预测为正例的样本中,实际为正例的比例,回答了“在 AI 预测为相关的所有项目中,有多少实际上是相关的?”这个问题。召回率衡量所有实际为正例的样本中,被模型正确识别为正例的比例,回答了“在所有实际上相关的项目中,AI 找到了多少?”这个问题。对于小型数据集,手动标注真实情况至关重要,并且理解 scikit-learn 中不同平均方法的含义对于准确解释结果非常重要。

理解精确率和召回率

精确率(Precision)和召回率(Recall)是评估分类模型性能的基本指标,尤其是在信息检索和 AI 问答系统中。精确率量化了正例预测的准确性,关注的是真正例(True Positives, TP)与所有预测为正例的总数(TP + 假正例 False Positives, FP)的比例。它回答了这个问题:“在 AI 预测为相关的所有项目中,有多少实际上是相关的?”高精确率意味着模型擅长不将不相关的项目标记为相关。另一方面,召回率衡量模型找到所有相关项目(真正例)的能力。它计算为真正例(TP)与所有实际为正例的总数(TP + 假反例 False Negatives, FN)的比例。召回率回答了:“在所有实际上相关的项目中,AI 找到了多少?”高召回率表明模型能够识别出大部分相关项目。

计算精确率和召回率

要计算精确率和召回率,您首先需要一组真实标签(正确答案)以及您的 AI 模型对给定问题集所做的预测。对于二元分类任务(例如,相关/不相关),精确率计算公式为 TP / (TP + FP),召回率计算公式为 TP / (TP + FN)。scikit-learn 库提供了方便的函数 precision_score 和 recall_score 来直接计算这些指标。这些函数接受真实标签 (y_true) 和预测标签 (y_pred) 作为输入。对于小型数据集,确保 y_true 的准确性至关重要,因为任何错误都会直接影响计算出的指标。

from sklearn.metrics import precision_score, recall_score

# 示例真实情况和预测
y_true = [0, 1, 2, 0, 1, 2]  # 实际相关性(例如,0:不相关,1:相关,2:高度相关)
y_pred = [0, 2, 1, 0, 0, 1]  # AI 预测的相关性

# 对于二元分类,您可能需要定义“正例”类别,例如类别 1
# 类别 1 的精确率
precision = precision_score(y_true, y_pred, pos_label=1, average='binary')
# 类别 1 的召回率
recall = recall_score(y_true, y_pred, pos_label=1, average='binary')

print(f"Precision (class 1): {precision:.2f}")
print(f"Recall (class 1): {recall:.2f}")

处理多类别和多标签场景

在处理 AI 问答时,问题可能并非严格的二元分类。您可能对单个问题有多个相关性级别或多个正确答案。Scikit-learn 的 precision_score 和 recall_score 函数可以处理多类别和多标签目标。这里的 average 参数至关重要。选项包括 'micro'(全局计算)、'macro'(每个类别的未加权平均值)、'weighted'(按支持度加权的平均值)、'samples'(每个实例的平均值,用于多标签)或 None(返回每个类别的分数)。对于小型数据集,使用 average=None 通常很有见地,因为它显示了每个特定类别或标签的性能,从而可以详细了解 AI 在哪些方面表现出色或挣扎。

from sklearn.metrics import precision_score, recall_score
import numpy as np

y_true_multi = [0, 1, 2, 0, 1, 2]
y_pred_multi = [0, 2, 1, 0, 0, 1]

# 计算每个类别的精确率和召回率
precision_scores = precision_score(y_true_multi, y_pred_multi, average=None)
recall_scores = recall_score(y_true_multi, y_pred_multi, average=None)

print(f"Precision per class: {precision_scores}")
print(f"Recall per class: {recall_scores}")

# 加权平均示例
weighted_precision = precision_score(y_true_multi, y_pred_multi, average='weighted')
weighted_recall = recall_score(y_true_multi, y_pred_multi, average='weighted')

print(f"Weighted Precision: {weighted_precision:.2f}")
print(f"Weighted Recall: {weighted_recall:.2f}")

零除法的角色

在精确率或召回率计算中出现分母为零(例如,没有做出正例预测,或者不存在实际正例)的情况下,可能会发生除零错误。Scikit-learn 的指标函数使用 zero_division 参数来处理这种情况。默认值为 'warn',它返回 0 并发出警告。您可以显式将其设置为 0.0 以返回 0 而不发出警告,设置为 1.0 以返回 1(如果您认为对于一个没有实际实例的类别,模型不预测任何内容是完美的精确率/召回率),或设置为 np.nan 以从平均值中排除此类情况。对于小型数据集,理解这些边缘情况以及 zero_division 如何影响您的指标对于准确解释至关重要。

from sklearn.metrics import precision_score, recall_score
import numpy as np

y_true_zero = [0, 0, 0]
y_pred_zero = [0, 0, 0]

# 零除法示例,默认 'warn'
print("--- Zero Division Handling ---")
precision_warn = precision_score(y_true_zero, y_pred_zero, average=None, zero_division='warn')
recall_warn = recall_score(y_true_zero, y_pred_zero, average=None, zero_division='warn')
print(f"Precision (warn): {precision_warn}")
print(f"Recall (warn): {recall_warn}")

# zero_division=1 示例
precision_one = precision_score(y_true_zero, y_pred_zero, average=None, zero_division=1)
recall_one = recall_score(y_true_zero, y_pred_zero, average=None, zero_division=1)
print(f"Precision (zero_division=1): {precision_one}")
print(f"Recall (zero_division=1): {recall_one}")

# zero_division=np.nan 示例
precision_nan = precision_score(y_true_zero, y_pred_zero, average=None, zero_division=np.nan)
recall_nan = recall_score(y_true_zero, y_pred_zero, average=None, zero_division=np.nan)
print(f"Precision (zero_division=np.nan): {precision_nan}")
print(f"Recall (zero_division=np.nan): {recall_nan}")

在小型数据集上解释结果

在小型数据集上评估 AI 性能需要仔细解释。高精确率可能仅仅因为模型做出的正例预测非常少,并且碰巧是正确的。同样,如果数据集中实际的正例非常少,而模型正确地识别了它们,也可能出现高召回率。关键是要同时考虑这两个指标。一种常见的方法是查看精确率-召回率曲线,尽管对于非常小的数据集,这可能不那么有信息量。对于问答系统,小型数据集可能意味着手动验证每个预测。如果数据集太小而无法代表整体情况,计算出的精确率和召回率可能无法很好地推广到更大、未见过的数据。如果可行,请考虑扩充数据集或使用交叉验证等技术。

精确率与召回率的权衡

精确率和召回率之间通常存在权衡。提高一个有时会降低另一个。例如,一个非常保守、仅在极度自信时才预测答案为相关的模型,可能具有高精确率但低召回率(它会错过许多相关的答案)。相反,一个试图找到所有可能的相关答案、即使置信度较低的模型,可能具有高召回率但低精确率(它包含了许多不相关的答案)。最佳平衡取决于具体应用。对于问答 AI,是提供仅正确的答案(高精确率)更重要,还是确保找到所有可能的正确答案(高召回率),即使包含一些不相关的答案?这个决定将指导您如何优先考虑这些指标。

AI 问答的实际考量

当将精确率和召回率应用于 AI 问答时,尤其是在小型数据集上,请考虑“正例”的性质。它是一个正确的答案,还是一组可接受的答案?如果使用向量搜索(如 Azure AI Search 文档中所述),相关性由向量相似度决定。然后,精确率和召回率衡量相似性搜索检索预期文档的程度。对于混合搜索(结合了向量搜索和关键字搜索),评估整体性能需要考虑这两个方面。小型数据集可能需要更多的手动标注,并仔细定义在语义或概念相似性方面什么是“真正例”,而不仅仅是精确的关键字匹配。

使用 precision_recall_fscore_support

Scikit-learn 提供了一个实用函数 precision_recall_fscore_support,它计算每个类别的精确率、召回率、F1 分数以及真正例的数量(支持度)。当您希望全面了解模型在所有类别上的性能时,尤其是在多类别场景中,此函数特别有用。对于小型数据集,查看每个类别的“支持度”信息非常有用,它可以突出显示哪些类别示例很少,这可能解释了这些特定类别的低召回率或精确率。此函数简化了一次获取多个关键指标的过程。

from sklearn.metrics import precision_recall_fscore_support

y_true_multi = [0, 1, 2, 0, 1, 2]
y_pred_multi = [0, 2, 1, 0, 0, 1]

precision, recall, fscore, support = precision_recall_fscore_support(y_true_multi, y_pred_multi, average=None)

print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1-Score: {fscore}")
print(f"Support: {support}")

小型数据集的局限性

在小型数据集上评估精确率和召回率的主要局限性在于缺乏统计显著性。在小样本上计算出的指标可能无法准确反映模型在更大、更多样化数据集上的性能。模型可能在小型、精心策划的问题集上表现得异常出色,这仅仅是由于偶然性或对特定示例的过拟合。反之,如果小型数据集恰好包含具有挑战性的边缘案例,模型可能显得性能不佳。很难从非常小的数据集中推广发现。此外,“真实情况”本身的定义可能具有主观性,尤其是在问答等细微的 AI 任务中,并且标注小型数据集可能无法捕捉到所有可能的答案或解释的全部范围。

检查清单

  • 确保 y_true(真实情况)已为小型数据集准确标注。
  • 验证 y_pred(模型预测)是否与 y_true 标签正确对应。
  • 理解 average 参数对多类别/多标签结果的影响。
  • 考虑 zero_division 参数在边缘情况下的行为。
  • 同时分析精确率和召回率,而不是孤立地分析。
  • 注意,来自小型数据集的结果可能无法很好地推广。

当这些指标应用于能代表 AI 将遇到的真实世界数据的代表性数据集时,它们最为可靠。对于非常小的数据集,由于统计限制和潜在的过拟合,计算出的精确率和召回率可能无法准确反映真实性能。应谨慎解释结果,并尽可能努力扩展数据集或使用交叉验证。

参考来源

  1. scikit-learn: precision_score ↗
  2. scikit-learn: recall_score ↗
  3. Microsoft Learn: relevance in vector search ↗
返回顶部 ↑