Python中的相等错误率
Posted
技术标签:
【中文标题】Python中的相等错误率【英文标题】:Equal Error Rate in Python 【发布时间】:2015-04-05 01:25:12 【问题描述】:谁能告诉我如何从 Python 中的 ROC 曲线计算等错误率(EER)?在 scikit-learn 中有计算 roc 曲线和 auc 的方法,但找不到计算 EER 的方法。
from sklearn.metrics import roc_curve, auc
回答:
我想我自己实现了。
ROC EER 的概念是直线连接之间的交点
(1,0) 和 (0,1) 以及 roc 曲线。这是它相交的唯一点。对于 a=1 和 b=1 的直线,方程为 x+y =1 (x/a +y/b =1.0)
。因此,交点将是真阳性率(tpr)和假阳性率(fpr)的值,它满足以下等式:
x + y - 1.0 = 0.0
因此将方法实现为:
def compute_roc_EER(fpr, tpr):
roc_EER = []
cords = zip(fpr, tpr)
for item in cords:
item_fpr, item_tpr = item
if item_tpr + item_fpr == 1.0:
roc_EER.append((item_fpr, item_tpr))
assert(len(roc_EER) == 1.0)
return np.array(roc_EER)
所以这里的一个值是错误率,另一个值是准确度。
也许有人可以帮我验证一下。
【问题讨论】:
您的解释是正确的 - 您正在寻找 TPR+FPR == 1 的位置。但是,您的代码并不可靠,因为我们不能保证坐标列表实际上包括正好位于 EER 线上的点。换句话说,您很可能有时会收到len(roc_EER)==0
。您需要在两点(EER 线的每一侧)之间进行插值,以更稳健地执行此操作。或者为简单起见,如果您需要选择一种经过测试的配置,您可以选择与 EER 线距离最短的设置。
【参考方案1】:
对于通过 Google 搜索到达这里的任何其他人。正如格哈德指出的那样,弗兰的答案是不正确的。正确的代码是:
import numpy as np
from sklearn.metrics import roc_curve
fpr, tpr, threshold = roc_curve(y, y_pred, pos_label=1)
fnr = 1 - tpr
eer_threshold = threshold[np.nanargmin(np.absolute((fnr - fpr)))]
请注意,这将为您提供 EER 发生的阈值,而不是 EER。 EER 定义为 FPR = 1 - PTR = FNR。因此,要获得 EER(实际错误率),您可以使用以下内容:
EER = fpr[np.nanargmin(np.absolute((fnr - fpr)))]
作为健全性检查,该值应接近
EER = fnr[np.nanargmin(np.absolute((fnr - fpr)))]
因为这是一个近似值。
【讨论】:
对于阅读此答案的任何人:而不是fpr(np.nanargmin(np.absolute((fnr - fpr))))
它应该是 fpr[np.nanargmin(np.absolute((fnr - fpr)))]
因为 fpr
是一个 numpy 数组【参考方案2】:
抄表How to compute Equal Error Rate (EER) on ROC 长江:
from scipy.optimize import brentq
from scipy.interpolate import interp1d
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y, y_score, pos_label=1)
eer = brentq(lambda x : 1. - x - interp1d(fpr, tpr)(x), 0., 1.)
thresh = interp1d(fpr, thresholds)(eer)
这给了我正确的 EER 值。还要记住,在文档中写到 y
是 在 0, 1 或 -1, 1 范围内的真正二进制标签。如果标签不是二元的,则应明确给出 pos_label 并且 y_score
是 目标分数,可以是正类的概率估计、置信度值或决策的非阈值度量(由某些分类器上的“decision_function”)。
【讨论】:
【参考方案3】:相等的错误率 (EER) 是您的错误定位率 (fpr) == 错误否定率 (fnr) [越小越好]
使用您从 roc sklearn 计算中获得的 fpr、tpr 和阈值,您可以使用此函数来获得 EER:
def compute_eer(fpr,tpr,thresholds):
""" Returns equal error rate (EER) and the corresponding threshold. """
fnr = 1-tpr
abs_diffs = np.abs(fpr - fnr)
min_index = np.argmin(abs_diffs)
eer = np.mean((fpr[min_index], fnr[min_index]))
return eer, thresholds[min_index]
【讨论】:
【参考方案4】:在他们在 Github 上的官方代码中有一个相当新的论文 AutoSpeech 的参考代码。我想这是可靠的之一。
https://github.com/VITA-Group/AutoSpeech/blob/master/utils.py#L84
def compute_eer(distances, labels):
# Calculate evaluation metrics
fprs, tprs, _ = roc_curve(labels, distances)
eer = fprs[np.nanargmin(np.absolute((1 - tprs) - fprs))]
return eer
另一种选择是使用 VoxCeleb1 非官方基线,这是从官方 VoxCeleb1 页面链接的:
https://github.com/clovaai/voxceleb_trainer/blob/master/tuneThreshold.py#L13
但链接中的tuneThresholdfromScore
函数不是一个简单的函数,那么AutoSpeech可能会更好。
【讨论】:
【参考方案5】:EER 定义为 FPR = 1 - PTR = FNR。 这是错误的。
由于 FPR= 1-TNR(真阴性率),因此不等于 FNR。
【讨论】:
【参考方案6】:要估计相等错误率EER
,您需要在ROC
内寻找使TPR
值等于FPR
值的点,即TPR-FPR=0
。换句话说,你寻找 abs(TPR-FPR
)
-
首先您需要估计
ROC
曲线:
fpr, tpr, threshold = roc_curve(y, y_pred, pos_label=1)
-
要在 python 中计算
EER
,只需要一行代码:
EER = threshold(np.argmin(abs(tpr-fpr)))
【讨论】:
错了。相等的错误率=误报率-误报率。非真阳性率 - 假阳性率!以上是关于Python中的相等错误率的主要内容,如果未能解决你的问题,请参考以下文章
Python中的is和==的区别,is判断值是否相等,id判断地址是否一致