生成精确召回曲线的置信区间

Phi*_*hil 2 python statistics r machine-learning confidence-interval

我有来自训练模型的预测,我可以很容易地为数据生成精确召回曲线,因此,还有精确召回曲线 (AUPRC) 下的区域。但是,我还尝试为数据生成 95% 的置信区间,我很难找到适合的数据。我已经在 sklearn 中查找了 Python 的 sklearn 和 R 的 pROC 包(它确实有一些用于 PR 的用途,但不是 AUPRC),但除了一些非常高水平的学术论文之外,我没有找到任何超出我头脑的东西。

有谁知道一个好的库,或者可以帮我找到计算 AUPRC 95% 置信区间的代码?

感谢任何可以提供帮助的人!

Mar*_*rat 6

我还没有看到现有的库这样做,所以我假设您需要自己实现它。不用担心,这并不难。

我看到了三种可能的方法:

  1. 精确置信区间:将 FN/FP 解释为从概率精度或召回率的二项式分布中采样。使用二项式 CDF 来估计精确的区间。这是最乏味的,但即使使用较小的样本也能工作。
  2. 使用正态近似值:与之前基本相同,但使用正态分位数而不是二项式。如果有 100 多个数据点,将产生与 (1) 几乎相同的结果
  3. 对 1000 个随机保留集重复分类,使用经验精度和召回分布作为置信区间。这是最容易实现的,但需要更多的计算。

UPD:关于实施的一些提示:

  • 精度为 TP/(TP+FP),即正面预测的真实概率为正
  • Recall 是 TP/(TP+FN),即对真实的正面预测的正面预测的概率。

由于我们下面的文本将涉及多个概率,因此我将这两个称为 PR(用于 Precision 或 Recall)

获得两者的置信区间的任务完全相同。我们基本上是在尝试估计伯努利变量的p(就像抛硬币时正面朝上的概率)。在这两种情况下,一系列翻转中的积极结果的数量是相同的 (TP)。唯一的区别是尝试次数(分母,我将在后面将其称为n)。

因此,我们需要将 PR 的值与观察到的结果的概率相关联。我们想要找到一些 PR 值的区间,使得观察到的结果的概率高于某个alpha。使用伯努利分布,我们可以根据正翻转 PR ( p )的机会估计观察到的结果 ( P ) 的概率:

P = (n! / (tp! * (n-tp)!)) * (p ** tp) * ((1-p) ** (n-tp))
Run Code Online (Sandbox Code Playgroud)

p进行累积和求逆是上面的选项 1。正如我所提到的,这很乏味(但并非不可能。

方法 2 是使用中心极限定理,它基本上说随机变量的总和严格遵循正态分布。鉴于伯努利分布的方差为p * (1-p),并且 sum 的方差与n成反比,我们可以找到 sum 的标准差。现在,概率为 1-alpha,p 应该在范围内p_hat +/- z_score * standard_deviation_of_sum

最后,实现:

# we'll need this for z-score
from scipy.stats import norm

def ci(tp, n, alpha=0.05):
    """ Estimates confidence interval for Bernoulli p
    Args:
      tp: number of positive outcomes, TP in this case
      n: number of attemps, TP+FP for Precision, TP+FN for Recall
      alpha: confidence level
    Returns:
      Tuple[float, float]: lower and upper bounds of the confidence interval
    """
    p_hat = float(tp) / n
    z_score = norm.isf(alpha * 0.5)  # two sides, so alpha/2 on each side
    variance_of_sum = p_hat * (1-p_hat) / n
    std = variance_of_sum ** 0.5
    return p_hat - z_score * std, p_hat + z_score * std
Run Code Online (Sandbox Code Playgroud)

UPD2:计算 AUC CI

sklearn.metrics.auc需要两个向量xy值。在这里,精确率和召回率可以互换使用。即,x是估计精度值的向量,y是召回的上限/下限,反之亦然 -x是估计的召回值,y是精度的上限或下限。

没有sklearn,大致可以这样近似:

# assuming data is a list of (upper_precision, precision, lower precision, upper_recall, recall, lower_recall)

auc = 0
sort(data, key=lambda x: x[1])  # sort by precision
last_point = (0, 0)  # last values of x,y
for up, p, lp, ur, r, lr in data:
    # whatever was used to sort should come first
    new_point = (p, ur)  # or (r, up) for upper bound; (p, lr), (r, lp) for lower bound
    dx = new_point[0] - last_point[0]
    y = last_point[1]
    auc += dx * last_point[1] + dx * (new_point[1] - last_point[1]) * 0.5        
Run Code Online (Sandbox Code Playgroud)