为精确召回曲线生成置信区间
Generating confidence interval for precision recall curve
我有来自经过训练的模型的预测,我可以很容易地为数据生成精确召回曲线,因此也可以生成精确召回曲线下的面积 (AUPRC)。但是,我还试图为数据生成 95% 的置信区间,我很难找到相关数据。我已经在 sklearn 中寻找 python 和 R 的 pROC 包(它确实有一些用于 PR,只是没有 AUPRC),但我没有找到一些相当高水平的学术论文之外的任何东西,这些论文走得很远在我头顶上方。
有没有人知道一个好的图书馆或者可以帮我找到代码来计算 AUPRC 的 95% 置信区间?
感谢任何能提供帮助的人!
我还没有看到现有的库这样做,所以我假设您需要自己实现它。别担心,没那么难。
我看到三种可能的方法:
- 精确置信区间:将 FN/FP 解释为从二项式分布中以概率 Precision 或 Recall 采样。使用二项式 CDF 来估计精确间隔。这个是最乏味的,但即使是较小的样本也能工作。
- 使用正态近似:与以前基本相同,但使用正态分位数而不是二项式。如果有 100+ 个数据点,将生成与 (1) 几乎相同的结果
- 对 1000 个随机保留集重复分类,使用经验精度和召回分布作为置信区间。这是最容易实现的,但需要更多的计算。
UPD: 一些实施提示:
- 精度为 TP/(TP+FP),即正预测的基本事实为正的概率
- 召回率是TP/(TP+FN),即对于ground truth positive的正预测的概率。
由于我们下面的文字将涉及多个概率,我将把这两个称为 PR(用于 Precision 或 Recall)
为两者获取置信区间的任务完全相同。我们基本上是在尝试估计伯努利变量的 p(就像抛硬币时正面朝上的概率)。在这两种情况下,一系列翻转中的正面结果数量是相同的 (TP)。唯一的区别是尝试次数(分母,我将在后面称为 n)。
因此,我们需要将 PR 的值与观察到的结果的概率相关联。
我们想要找到一些 PR 值区间,使得观察到的结果的概率高于某些 alpha。
使用伯努利分布,我们可以估计观察到的结果的概率 (P),这取决于正翻转 PR (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
需要两个向量,x
和 y
值。这里的精度和召回率可以互换使用。即,x
是估计精度值的向量,y
是 upper/lower 召回范围,反之亦然 - 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
我有来自经过训练的模型的预测,我可以很容易地为数据生成精确召回曲线,因此也可以生成精确召回曲线下的面积 (AUPRC)。但是,我还试图为数据生成 95% 的置信区间,我很难找到相关数据。我已经在 sklearn 中寻找 python 和 R 的 pROC 包(它确实有一些用于 PR,只是没有 AUPRC),但我没有找到一些相当高水平的学术论文之外的任何东西,这些论文走得很远在我头顶上方。
有没有人知道一个好的图书馆或者可以帮我找到代码来计算 AUPRC 的 95% 置信区间?
感谢任何能提供帮助的人!
我还没有看到现有的库这样做,所以我假设您需要自己实现它。别担心,没那么难。
我看到三种可能的方法:
- 精确置信区间:将 FN/FP 解释为从二项式分布中以概率 Precision 或 Recall 采样。使用二项式 CDF 来估计精确间隔。这个是最乏味的,但即使是较小的样本也能工作。
- 使用正态近似:与以前基本相同,但使用正态分位数而不是二项式。如果有 100+ 个数据点,将生成与 (1) 几乎相同的结果
- 对 1000 个随机保留集重复分类,使用经验精度和召回分布作为置信区间。这是最容易实现的,但需要更多的计算。
UPD: 一些实施提示:
- 精度为 TP/(TP+FP),即正预测的基本事实为正的概率
- 召回率是TP/(TP+FN),即对于ground truth positive的正预测的概率。
由于我们下面的文字将涉及多个概率,我将把这两个称为 PR(用于 Precision 或 Recall)
为两者获取置信区间的任务完全相同。我们基本上是在尝试估计伯努利变量的 p(就像抛硬币时正面朝上的概率)。在这两种情况下,一系列翻转中的正面结果数量是相同的 (TP)。唯一的区别是尝试次数(分母,我将在后面称为 n)。
因此,我们需要将 PR 的值与观察到的结果的概率相关联。 我们想要找到一些 PR 值区间,使得观察到的结果的概率高于某些 alpha。 使用伯努利分布,我们可以估计观察到的结果的概率 (P),这取决于正翻转 PR (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
需要两个向量,x
和 y
值。这里的精度和召回率可以互换使用。即,x
是估计精度值的向量,y
是 upper/lower 召回范围,反之亦然 - 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