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

时间:2019-08-13 17:05:28

标签: python r machine-learning statistics confidence-interval

我从训练有素的模型得到预测,并且可以非常轻松地为数据生成精确调用曲线,因此也可以在精确调用曲线(AUPRC)下生成面积。但是,我也试图为数据生成95%的置信区间,但我很难为之寻找东西。我已经在sklearn中找到了针对R的python和pROC包(确实对PR有一些用法,而对AUPRC却没有用),但是在一些相当高级的学术论文之外,我什么都没找到。

有人知道一个好的图书馆吗,或者可以帮助我找到用于计算AUPRC 95%置信区间的代码?

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

1 个答案:

答案 0 :(得分:1)

我还没有看到现有的库在执行此操作,因此我认为您需要自己实现它。不用担心,这并不难。

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

  1. 精确的置信区间:将FN / FP解释为从二项式分布中采样的概率为Precision或Recall。使用二项式CDF估计确切间隔。这是最繁琐的,但即使是较小的样本也可以使用。
  2. 使用法线逼近:与以前基本相同,但使用法线分位数代替二项式。如果有100个以上的数据点,将产生与(1)几乎相同的结果
  3. 对1000个随机保留集进行重复分类,使用经验精度并针对置信区间进行召回分布。这是最容易实现的方法,但是将需要更多的计算。

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

  • 精确度是TP /(TP + FP),即对于阳性预测而言,地面真实性为正的概率
  • 召回率是TP /(TP + FN),即对地面事实为阳性的阳性预测的概率。

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

获得两者的置信区间的任务是完全相同的。我们基本上是在尝试估算Bernoulli变量的 p (就像掷硬币的机会一样)。在这两种情况下,一系列翻转中的积极结果数是相同的(TP)。唯一的区别是尝试次数(分母,我将进一步称为 n )。

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

P = (n! / (tp! * (n-tp)!)) * (p ** tp) * ((1-p) ** (n-tp))

p 进行累加并求反是上面的选项1。正如我提到的那样,这很繁琐(但并非不可能。

方法2使用Central Limit Theorem,该方法基本上表示随机变量的总和紧随正态分布。 假设伯努利分布的方差为p * (1-p),并且总和的方差与 n 成反比,我们可以找到总和的标准差。现在,以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

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