一、模型评估常用的评估方法:
1、准确率(Accuracy)
模型的准确率(Accuracy)是指模型在测试集上预测正确的样本数占总样本数的比例。通常用公式表示为:
准确率 = 预测正确的样本数 / 总样本数
在二分类问题中,如果将真正例定义为模型正确预测的正例数,真反例定义为模型正确预测的负例数,假正例定义为模型将负例错误地预测为正例的样本数,假反例定义为模型将正例错误地预测为负例的样本数,那么准确率可以进一步细分为:
准确率 = (真正例 + 真反例) / (真正例 + 真反例 + 假正例 + 假反例)
准确率是评估模型性能的基本指标之一。对于多分类问题,也可以使用类似的公式计算每个类别的准确率或者计算宏平均准确率和微平均准确率等不同的指标。
需要注意的是,有时候仅仅使用准确率不能完全反映模型的性能。例如,在极度不平衡的数据集中,模型可能会使得准确率过高,但同时漏掉了重要异常情况或较少出现的类别。因此,在实际应用中,我们可能需要结合其他指标来评估模型性能,如召回率、精确率、F1 分数等。
示例:
假设我们有一个二分类问题,数据集中有200个样本。其中,100个样本属于正类别(标记为1),另外100个样本属于负类别(标记为0)。
现在,我们使用一个分类模型对这个数据集进行训练,并在测试集上进行预测。在测试集上,模型正确地预测了60个正类别样本和70个负类别样本,但同时也出现了15个负类别样本被错误地预测为正类别,以及10个正类别样本被错误地预测为负类别。
我们可以将这些结果整理成一个混淆矩阵,如下所示:
预测正类别 | 预测负类别 | |
---|---|---|
实际正类别 | 60 | 10 |
实际负类别 | 15 | 70 |
根据混淆矩阵,我们可以计算出模型的准确率。总样本数为200,其中有130个样本被正确地预测(60个正类别样本和70个负类别样本),因此准确率为:
准确率 = 130 / 200 = 0.65 = 65%(即模型在测试集上的准确率为65%)
通过混淆矩阵和准确率,我们可以得到一些关于模型性能的观察:
- 模型在正类别样本上的准确率为60%(60/100),即只有60%的正类别样本被正确地预测。
- 模型在负类别样本上的准确率为70%(70/100),即有70%的负类别样本被正确地预测。
- 模型将15个负类别样本错误地预测为正类别,这可能导致误判或错误的决策。
- 模型将10个正类别样本错误地预测为负类别,这也可能导致错误的判断。
综上所述,准确率可以作为评估模型性能的一个指标,但它并不能提供关于不同类别的详细信息。因此,在实际应用中,通常需要结合其他评估指标来全面了解模型的表现。
2、精确率(Precision)
模型评估的精确率(Precision)是指在所有预测为正例的样本中,真正例的比例。从公式上来看,精确率可以表示为:
精确率 = 真正例 / (真正例 + 假正例)
其中,真正例表示模型正确地预测为正例的样本数,假正例表示模型错误地将负例预测为正例的样本数。
精确率通常被用来评估分类器的准确性,特别是在有不平衡类别数据集的情况下。对于某些应用场景,例如医疗诊断等,在保证高精度的前提下,可能更注重找到真正例,而不是错判负例为正例,因为这可能会导致严重后果。
示例:
假设我们有一个二分类问题,数据集中有100个样本。其中,60个样本属于正类别(标记为1),另外40个样本属于负类别(标记为0)。
在测试集上,我们使用一个分类模型进行预测,其中预测结果为正类别的样本有30个,其中有20个属于真正例,10个属于假正例。那么,模型的精确率可以计算为:
精确率 = 20 / (20 + 10) = 0.67 = 67%
这意味着,模型在所有预测为正例的样本中,有67%是真正例。
需要注意的是,精确率通常对于不平衡类别数据集更具有意义。如果数据集中正类别样本比负类别样本多得多,那么分类器可能会将所有样本预测为正类别,这会导致非常高的准确率,但是精确率则会很低。因此,在实际应用中,我们可能需要结合其他指标来评估模型性能,如召回率、F1 分数等。
3、召回率(Recall)
模型评估的召回率(Recall)是指在所有实际为正例的样本中,被正确预测为正例的比例。从公式上来看,召回率可以表示为:
召回率 = 真正例 / (真正例 + 假反例)
其中,真正例表示模型正确地预测为正例的样本数,假反例表示模型错误地将正例预测为负例的样本数。
召回率主要用于评估分类器对正例的识别能力,即分类器能够正确检测到多少真实的正例。
示例:
假设我们有一个二分类问题,数据集中有100个样本。其中,60个样本属于正类别(标记为1),另外40个样本属于负类别(标记为0)。
在测试集上,我们的分类模型对正类别样本进行了预测,其中预测结果为正类别的样本有30个,其中有20个属于真正例,10个属于假反例(即将正例错误预测为负例)。那么,模型的召回率可以计算为:
召回率 = 20 / (20 + 0) = 1.00 = 100%
这意味着,模型在所有实际为正例的样本中,能够将所有正例都正确地预测出来。
需要注意的是,召回率对于一些特定的应用场景非常重要,尤其是在关注发现所有正例时。例如,在医疗诊断中,如果一个分类器用于检测罕见疾病,那么高召回率意味着它能够尽可能地发现更多的真实病例。
然而,召回率相对于精确率来说是一个更加保守的指标,即在保证发现尽可能多的真实正例的同时,可能会导致更多的误报。因此,在实际应用中,我们需要综合考虑精确率、召回率以及其他评估指标,找到适合具体应用场景的平衡点。
4、P-R曲线
PR曲线(Precision-Recall Curve)是用于评估二分类模型性能的一种常用方法,通常用于处理样本不平衡的情况
-
横轴为召回率(Recall),表示实际为正例的样本中被正确预测为正例的比例。计算方法为:Recall = TP / (TP + FN),其中TP表示真正例(True Positive),FN表示假反例(False Negative)。
-
纵轴为精确率(Precision),表示预测为正例的样本中真正例的比例。计算方法为:Precision = TP / (TP + FP),其中TP表示真正例(True Positive),FP表示假正例(False Positive)。
-
PR曲线通过绘制不同分类阈值下的精确率和召回率来展示模型在不同情况下的性能。阈值决定了模型将样本划分为正例还是负例的界限,不同阈值可以得到不同的精确率和召回率。
-
PR曲线上每个点对应于一个特定的分类阈值,点的位置表示该阈值下的精确率和召回率。曲线上的每个点都代表着模型在不同阈值下的性能,点越靠近右上角,说明模型的性能越好。
-
PR曲线的面积(Area Under Curve,AUC-PR)是一个综合评估分类器性能的指标。AUC-PR的取值范围在[0, 1]之间,数值越大表示分类器性能越好。
4.1应用场景
PR 曲线适用于正负样本不平衡的情况,尤其是当正样本数量远小于负样本数量时,PR曲线能够更好地反映模型对正样本的预测性能。它可以用来评估信息检索系统、文本分类系统等的性能,帮助我们了解分类器实际的效果和作用,也能够以此进行模型的改进和优化。
4.2 P-R曲线计算方法
在PR曲线中,横轴表示召回率,纵轴表示精度,曲线上每一点的坐标表示在该召回率下的精度值。
PR 曲线的绘制方法通俗来说就是:先设定一个较高的阈值θ,然后计算数据集的精确率和召回率,然后递减地降低阈值 θ,并分别记录各自阈值对应下的精确率和召回率。每个阈值 θ 对应于一个 (Precision,Recall)点,把这些 点 连起来就是 PR 曲线。
Q:这里的阈值 θ 是什么?怎么设定?
A:阈值 θ 是用来将模型的预测概率转换为二元分类结果的一个参数。
- 当模型预测一个样本属于正类的概率大于等于阈值 θ 时,我们将该样本分类为正类(正样本);
- 否则,我们将该样本分类为负类(负样本)。
4.3 PR 曲线 API
在 sklearn
库中,我们可以使用 precision_recall_curve
函数来计算精确率和召回率,然后使用 matplotlib
库来绘制 PR 曲线。
sklearn.metrics.precision_recall_curve(y_true,
probas_pred,
pos_label=None,
sample_weight=None)
作用:precision_recall_curve 是 sklearn.metrics 模块中的一个函数,它用于计算二分类模型的精确率和召回率。
参数说明:
y_true: 真实标签,形状为 (n_samples,) 的一维数组。
probas_pred: 预测概率,形状为 (n_samples,) 的一维数组。
pos_label: 可选参数,指定正类标签。默认值为 1。
sample_weight: 可选参数,样本权重。默认值为 None。
返回值:
precision: 精确率,形状为 (n_thresholds + 1,) 的一维数组。
recall: 召回率,形状为 (n_thresholds + 1,) 的一维数组。
thresholds: 阈值,形状为 (n_thresholds,) 的一维数组。
示例:
from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
# 生成数据集
X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.1, 0.9], random_state=1)
# 训练模型
model = LogisticRegression()
model.fit(X, y)
# 预测概率
yhat = model.predict_proba(X)
probs = yhat[:, 1] # 提取模型预测每个样本属于正类的概率
# 计算精确率和召回率
precision, recall, _ = precision_recall_curve(y, probs)
# 绘制 PR 曲线
plt.plot(recall, precision, marker='.')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.show()
Q:这段代码中,为什么要 probs = yhat[:, 1]?
A:在这段代码中,probs = yhat[:, 1] 这一行的作用是提取模型预测每个样本属于正类的概率。
LogisticRegression 模型的 predict_proba 方法返回一个形状为 (n_samples, n_classes) 的数组,其中第 i 行第 j 列的元素表示第 i 个样本属于第 j 类的概率。在二分类问题中,n_classes=2,因此 predict_proba 方法返回一个形状为 (n_samples, 2) 的数组。
在这段代码中,我们假设正类的标签为 1,负类的标签为 0。因此,yhat[:, 0] 表示模型预测每个样本属于负类的概率,而 yhat[:, 1] 表示模型预测每个样本属于正类的概率。所以,我们使用 probs = yhat[:, 1] 来提取模型预测每个样本属于正类的概率。
我们也可以同时将阈值 θ 画出来:
from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
# 生成数据集
X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.1, 0.9], random_state=1)
# 训练模型
model = LogisticRegression()
model.fit(X, y)
# 预测概率
yhat = model.predict_proba(X)
probs = yhat[:, 1]
# 计算精确率和召回率
precision, recall, thresholds = precision_recall_curve(y, probs)
# 绘制 PR 曲线和阈值曲线
fig, ax1 = plt.subplots(dpi=300)
ax1.plot(recall, precision, marker='.')
ax1.set_xlabel('Recall')
ax1.set_ylabel('Precision', color='b')
ax2 = ax1.twinx()
ax2.plot(recall[:-1], thresholds, 'r')
ax2.set_ylabel('Threshold', color='r')
plt.show()
需要注意的是:在上面的代码中,我们使用 recall[:-1] 是因为 precision_recall_curve 函数返回的阈值数组的长度比精确率和召回率数组的长度少 1。
precision_recall_curve 函数返回的阈值数组表示在不同阈值下,模型将样本分类为正类的概率。这些阈值是根据模型预测概率的分布情况确定的。由于阈值数组中不包括最大阈值(即 1),所以阈值数组的长度比精确率和召回率数组的长度少 1。
为了在同一个图中绘制 PR 曲线和阈值曲线,我们需要保证两条曲线的横坐标具有相同的长度。因此,我们使用 recall[:-1] 来去掉召回率数组中的最后一个元素,使得召回率数组的长度与阈值数组相同。
4.4 如何观察 PR 曲线
PR 曲线越靠近右上角,模型的性能就越好(AUC 曲线是越靠近左上角模型性能越好)。
通常,我们可以通过以下几种方法来根据 PR 曲线判断几个模型的效果是好还是坏:
- 如果一条曲线完全“包住”另一条曲线,则前者性能优于另一条曲线。
- 如果两条曲线发生了交叉,则可以使用平衡点(Break-Even Point)作为衡量指标。平衡点是查准率等于查全率时的取值,值越大代表效果越优。
- 另一种常用的方法是使用 F-1 度量,F-1 分数越高越好。
5、ROC曲线和AUC评估指标
ROC曲线和AUC(Area Under Curve)是用于评估分类模型性能的重要指标。
-
ROC曲线:ROC曲线以不同的分类阈值为基础,绘制出分类器的真阳性率(TPR)与假阳性率(FPR)之间的关系曲线。ROC曲线的横轴是FPR,纵轴是TPR。通过改变分类阈值,可以得到一组不同的TPR和FPR值。ROC曲线的形状反映了分类器在不同分类阈值下的性能表现。通常情况下,我们希望ROC曲线向左上方凸起,因为这意味着分类器在保持较低FPR的同时,能够获得较高的TPR。
-
AUC值:AUC是ROC曲线下面积的度量,取值范围在0到1之间。AUC值反映了分类器将正例排在负例前面的能力。AUC值越大,表示分类器的性能越好,能够更准确地区分正例和负例。当AUC值等于0.5时,表示分类器的性能等同于随机猜测,小于0.5则表示分类器性能较差。一般来说,AUC值大于0.8被认为是一个较好的分类器性能。
ROC曲线和AUC值提供了一种可视化和量化的方式来评估分类模型的性能,尤其在处理不平衡数据集或需要权衡不同分类阈值下模型表现时非常有用。它们可以帮助我们选择合适的分类阈值、比较不同模型之间的性能,并对模型进行优化和改进。
5.1ROC曲线解释
一个二分类问题,可以将实例分成正类(postive)或者负类(negative)。但是实际中分类时,会出现四种情况
- 1.某一个实例是正类,并且预测结果也为正类,此为真正类(True Positive, TP)
- 2.某一个实例是正类,被预测为负类,此为假负类(False Negative, FN)
- 3.某一个实例是负类,被预测为正类,此为假正类(False Positive, FP)
- 4.某一个实例为负类,并且预测结果也为负类,此为真负类(True Negative, TN)
ROC曲线的纵坐标是真正率(TPR)
用通俗的语言解释就是预测的正例中,实际上也为正的在所有正例中的占比,这个比例自然是越大越好。
ROC曲线的横坐标是假正率(FPR)
用通俗的语言解释就是预测的正例中,实际上为负的在所有负例中的占比。这个比例是越小越好。
很明显,这两个指标是互斥的,无法同时达到最优效果。
5.2如何画ROC曲线
假设已经得出一系列样本被划分为正类的概率,然后按照大小排序,下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率。
接下来,我们从高到低,依次将“Score”值作为阈值threshold,当测试样本属于正样本的概率大于或等于这个threshold时,我们认为它为正样本,否则为负样本。举例来说,对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。每次选取一个不同的threshold,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。这样一来,我们一共得到了20组FPR和TPR的值,将它们画在ROC曲线的结果如下图:
python代码实现:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc
# 随机生成样本的真实标签和预测概率
y_true = np.array([0, 0, 1, 1, 1, 0])
y_scores = np.array([0.2, 0.3, 0.7, 0.4, 0.8, 0.6])
# 计算FPR, TPR和阈值
fpr, tpr, thresholds = roc_curve(y_true, y_scores)
# 计算AUC值
roc_auc = auc(fpr, tpr)
# 绘制ROC曲线
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()
在上述代码中,我们使用numpy
库生成了样本的真实标签y_true
和模型的预测概率y_scores
。然后,使用sklearn.metrics
模块中的roc_curve
函数计算出ROC曲线的FPR、TPR和阈值。接着,使用auc
函数计算AUC值。最后,使用matplotlib.pyplot
库绘制了ROC曲线,并添加了相应的标题、坐标轴标签和图例。
5.3AUC值含义
AUC值指的是ROC曲线下的面积。AUC常常被用来作为模型排序好坏的指标,原因在于AUC可以看做随机从正负样本中选取一对正负样本,其中正样本的得分大于负样本的概率。所以,AUC常用在排序场景的模型评估,比如搜索和推荐等场景。
5.4AUC的计算方法
在有M个正样本,N个负样本的数据集里。一共有MN对样本(一对样本即,一个正样本与一个负样本)。统计这MN对样本里,正样本的预测概率大于负样本的预测概率的个数。
其中,
python代码:
from sklearn.metrics import roc_auc_score
auc = roc_auc_score(y_true, y_pred_prob)
举例:
上面的例子有4个样本,其中两个为正两个为负,则M*N=4,总共4个样本对。
(D,B), (D,A), (C,B), (C,A)
其中,I(D,B)=I(D,A)=I(C,A)=1, I(C,B)=0
最后AUC的值为(1+1+1+0)/4 = 0.75
5.5P-R曲线和ROC曲线对比
AUC曲线和PR曲线的共同点:
- 都可以用于评估分类模型的性能,并提供了一种可视化方式。
- 都可以用于比较不同模型之间的性能。
AUC曲线的优点:
- AUC值在不同分类阈值下的性能综合考虑了真阳性率(TPR)和假阳性率(FPR),对数据集中的不平衡样本分布具有较好的稳定性。
- 对于二分类问题,AUC值是一个很常见的评估指标,容易理解和解释。
- 对于大规模数据集,计算AUC相对较快。
AUC曲线的缺点:
- AUC无法体现模型在具体的分类阈值下的性能表现,只能提供一个综合的评估结果。
- 当数据集存在严重的类别不平衡时,AUC可能会失真,因为大多数情况下的分类阈值选择都会导致较低的FPR。
P-R曲线的优点:
- PR曲线以精确率(Precision)和召回率(Recall)为基础,直接反映了模型在不同分类阈值下的性能变化。
- PR曲线对于类别不平衡问题更为敏感,能够更好地评估模型在少数类别(正例)上的性能。
- PR曲线特别适用于当关注的是正例的预测准确性时,如医学诊断等领域。
P-R曲线的缺点:
- PR曲线对于不同模型的比较相对较困难,因为曲线下面积(AUC-PR)在不同数据集和分类阈值下具有较大的变化范围。
- PR曲线在处理大规模数据集时计算复杂度较高。