AUC(Area Under Curve)被定义为ROC曲线下的面积。我们往往使用AUC值作为模型的评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。
其中,ROC曲线全称为受试者工作特征曲线 (receiver operating characteristic curve),它是根据一系列不同的二分类方式(分界值或决定阈),以真阳性率(敏感性)为纵坐标,假阳性率(1-特异性)为横坐标绘制的曲线。
AUC就是衡量学习器优劣的一种性能指标。从定义可知,AUC可通过对ROC曲线下各部分的面积求和而得。
ROC曲线的意义
(1)主要作用
1.ROC曲线能很容易的查出任意阈值对学习器的泛化性能影响。
2.有助于选择最佳的阈值。ROC曲线越靠近左上角,模型的准确性就越高。最靠近左上角的ROC曲线上的点是分类错误最少的最好阈值,其假正例和假反例总数最少。
3.可以对不同的学习器比较性能。将各个学习器的ROC曲线绘制到同一坐标中,直观地鉴别优劣,靠近左上角的ROC曲所代表的学习器准确性最高。
(2)优点
- 该方法简单、直观、通过图示可观察分析学习器的准确性,并可用肉眼作出判断。ROC曲线将真正例率和假正例率以图示方法结合在一起,可准确反映某种学习器真正例率和假正例率的关系,是检测准确性的综合代表。
- ROC曲线不固定阈值,允许中间状态的存在,利于使用者结合专业知识,权衡漏诊与误诊的影响,选择一个更加的阈值作为诊断参考值。
AUC
如果两条ROC曲线没有相交,我们可以根据哪条曲线最靠近左上角哪条曲线代表的学习器性能就最好。但是,实际任务中,情况很复杂,如果两条ROC曲线发生了交叉,则很难一般性地断言谁优谁劣。在很多实际应用中,我们往往希望把学习器性能分出个高低来。在此引入AUC面积。
在进行学习器的比较时,若一个学习器的ROC曲线被另一个学习器的曲线完全“包住”,则可断言后者的性能优于前者;若两个学习器的ROC曲线发生交叉,则难以一般性的断言两者孰优孰劣。此时如果一定要进行比较,则比较合理的判断依据是比较ROC曲线下的面积,即AUC(Area Under ROC Curve)。
AUC面积的意义
AUC是衡量二分类模型优劣的一种评价指标,表示预测的正例排在负例前面的概率。
有效性不同的模型的 ROC 曲线图示
from xgboost.sklearn import XGBClassifier
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.ensemble import BaggingClassifier, AdaBoostClassifier, GradientBoostingClassifier,RandomForestClassifier
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3)
def plot_roc():
clf_bagging = BaggingClassifier()
clf_ada = AdaBoostClassifier()
clf_gbdt = GradientBoostingClassifier()
clf_rf = RandomForestClassifier()
clf_xgb = XGBClassifier()
clfs = [clf_bagging, clf_ada, clf_gbdt, clf_rf,clf_xgb]
names = ['Bagging', 'AdaBoost', 'GBDT', 'RandomForest','XGBC']
prbs_1 = []
for clf in clfs:
clf.fit(X_train, Y_train)
pre = clf.predict(X_test)
y_prb_1 = clf.predict_proba(X_test)[:, 1]
prbs_1.append(y_prb_1)
for index, value in enumerate(prbs_1):
fpr, tpr, thresholds = roc_curve(Y_test, value)
roc_auc = auc(fpr, tpr)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(fpr, tpr, label='{0}_AUC = {1:.5f}'.format(names[index], roc_auc))
plt.title('ROC曲线')
plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.ylabel('命中率')
plt.xlabel('误判率')
plt.show()
plot_roc()
K-S曲线
KS曲线是用来衡量分类型模型准确度的工具。KS曲线与ROC曲线非常的类似。其指标的计算方法与混淆矩阵、ROC基本一致。它只是用另一种方式呈现分类模型的准确性。KS值是KS图中两条线之间最大的距离,其能反映出分类器的划分能力。
一句话概括版本:
KS曲线是两条线,其横轴是阈值,纵轴是TPR与FPR。两条曲线之间之间相距最远的地方对应的阈值,就是最能划分模型的阈值。
KS值是MAX(TPR - FPR),即两曲线相距最远的距离。
KS(Kolmogorov-Smirnov)评价指标,通过衡量好坏样本累计分布之间的差值,来评估模型的风险区分能力。
KS、AUC、PR曲线对比:
1)ks和AUC一样,都是利用TPR、FPR两个指标来评价模型的整体训练效果。
2)不同之处在于,ks取的是TPR和FPR差值的最大值,能够找到一个最优的阈值;AUC只评价了模型的整体训练效果,并没有指出如何划分类别让预估的效果达到最好,就是没有找到好的切分阈值。
3)与PR曲线相比,AUC和KS受样本不均衡的影响较小,而PR受其影响较大。(详看P-R曲线及与ROC曲线区别)
KS的曲线图走势大概如下:
ks值<0.2,一般认为模型没有区分能力。
ks值[0.2,0.3],模型具有一定区分能力,勉强可以接受
ks值[0.3,0.5],模型具有较强的区分能力。
ks值大于0.75,往往表示模型有异常。
二、直观理解KS
1)如何直观的理解ks呢?
参考上述ks曲线图,可以这样理解,随着阈值从大逐渐的变小,TPR的提升速度高于FPR的提升速度,直到一个临界阈值threshold,之后TPR提升速度低于FPR,这个临界threshold便是最佳阈值。在前期TPR越快提升,模型效果越好;反之,FPR越快提升,模型效果就越差。
P-R曲线及与ROC曲线区别
P-R曲线刻画查准率和查全率之间的关系,查准率指的是在所有预测为正例的数据中,真正例所占的比例,查全率是指预测为真正例的数据占所有正例数据的比例。
即:查准率P=TP/(TP + FP) 查全率=TP/(TP+FN)
查准率和查全率是一对矛盾的度量,一般来说,查准率高时,查全率往往偏低,查全率高时,查准率往往偏低,例如,若希望将好瓜尽可能多选出来,则可通过增加选瓜的数量来实现,如果希望将所有的西瓜都选上,那么所有的好瓜必然都被选上了,但这样查准率就会较低;若希望选出的瓜中好瓜比例尽可能高,则可只挑选最有把握的瓜,但这样就难免会漏掉不少好瓜,使得查全率较低。
在很多情况下,我们可以根据学习器的预测结果对样例进行排序,排在前面的是学习器认为最可能是正例的样本,排在后面的是学习器认为最不可能是正例的样本,按此顺序逐个把样本作为正例进行预测,则每次可计算当前的查全率和查准率,以查准率为y轴,以查全率为x轴,可以画出下面的P-R曲线。
如果一个学习器的P-R曲线被另一个学习器的P-R曲线完全包住,则可断言后者的性能优于前者,例如上面的A和B优于学习器C,但是A和B的性能无法直接判断,但我们往往仍希望把学习器A和学习器B进行一个比较,我们可以根据曲线下方的面积大小来进行比较,但更常用的是平衡点或者是F1值。平衡点(BEP)是查准率=查全率时的取值,如果这个值较大,则说明学习器的性能较好。而F1 = 2 * P * R /( P + R ),同样,F1值越大,我们可以认为该学习器的性能较好。
联合建模(BJ)P-R曲线
参数:
y_true:array, shape = [n_samples]:真实标签。如果标签不是{-1,1}或{0,1},那么pos_label应该显式给出。
probas_pred:array, shape = [n_samples] :正类的预测概率或决策函数
pos_label:int or str, default=None:正类标签。当pos_label=None时,如果y_true为{- 1,1}或{0,1},则pos_label设置为1,否则将报错。
返回值:
precision:array, shape = [n_thresholds + 1]:精度,最后一个元素是1。
recall:array, shape = [n_thresholds + 1]:召回率,最后一个是0
thresholds:array, shape = [n_thresholds <= len(np.unique(probas_pred))]:用于计算精度和召回率的决策函数的阈值
例子:
import numpy as np
from sklearn.metrics import precision_recall_curve
y_true = np.array([0, 0, 1, 1])
y_scores = np.array([0.1, 0.4, 0.35, 0.8])
precision, recall, thresholds = precision_recall_curve(y_true, y_scores)
如何选择呢?
- 在很多实际问题中,正负样本数量往往很不均衡。比如,计算广告领域经常涉及转化率模型,正样本的数量往往是负样本数量的1/1000,甚至1/10000。若选择不同的测试集,P-R曲线的变化就会非常大,而ROC曲线则能够更加稳定地反映模型本身的好坏。所以,ROC曲线的适用场景更多,被广泛用于排序、推荐、广告等领域。
- 但需要注意的是,选择P-R曲线还是ROC曲线是因实际问题而异的,如果研究者希望更多地看到模型在特定数据集上的表现,P-R曲线则能够更直观地反映其性能。
- PR曲线比ROC曲线更加关注正样本,而ROC则兼顾了两者。
- AUC越大,反映出正样本的预测结果更加靠前。(推荐的样本更能符合用户的喜好)
- 当正负样本比例失调时,比如正样本1个,负样本100个,则ROC曲线变化不大,此时用PR曲线更加能反映出分类器性能的好坏。这个时候指的是两个分类器,因为只有一个正样本,所以在画auc的时候变化可能不太大;但是在画PR曲线的时候,因为要召回这一个正样本,看哪个分类器同时召回了更少的负样本,差的分类器就会召回更多的负样本,这样precision必然大幅下降,这样分类器性能对比就出来了。
学习曲线
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
# 用sklearn的learning_curve得到training_score和cv_score,使用matplotlib画出learning curve
def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, n_jobs=1,
train_sizes=np.linspace(.05, 1., 20), verbose=0):
"""
画出data在某模型上的learning curve.
参数解释
----------
estimator : 你用的分类器。
title : 表格的标题。
X : 输入的feature,numpy类型
y : 输入的target vector
ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点
cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份)
n_jobs : 并行的的任务数(默认1)
"""
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)
train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)
plt.grid()
plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
train_scores_mean + train_scores_std, alpha=0.1,
color="r")
plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
test_scores_mean + test_scores_std, alpha=0.1, color="g")
plt.plot(train_sizes, train_scores_mean, 'o-', color="r",
label="Training score")
plt.plot(train_sizes, test_scores_mean, 'o-', color="g",
label="Cross-validation score")
plt.legend(loc="best")
return plt
plot_learning_curve(LR, u"学习曲线",x, y)