持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
ROC曲线
在二元分类器中还有一个经常使用的工具,叫受试者工作特征(receiver operating characteristic,简称ROC)曲线,他与之前的提到的精度/召回率(PR)曲线非常相似,不过是绘制的是真正类率(召回率)和假正率(FPR)。
现在我们让我们配上图1-1,重新认识几个指标:
图1-1 混淆矩阵
真正类率(True Positive Rate,TPR),真阳性率、Recall(查全率、召回率)、Sensitivity(感受性)- ,是把正类预测正确的数,与所有的正类总数的比率
图1-2 TPR
假正类率(False Positive Rate,FPR),假阳性率- ,是把负类预测错误的数,与所有的负类总数的比率
图1-3 FPR
真负类率(True Negative Rate,TNR),特异度(Specificity)- ,是把负类预测正确的数,与所有的负类总数的比率
因此ROC也可以是灵敏度(召回率)和(1-特异度)的关系。接下来让我们绘制一下ROC曲线,我们需要用到roc_curve()函数,计算出我们需要的多种阈值下的TPR和FPR:
from sklearn.metrics import roc_curve
# 获得我们需要的fpr, tpr
# y_scores 来自上一篇文章,如果不清楚的读者可以自行查看《分类(一)》
fpr, tpr, threshold = roc_curve(y_train_5, y_scores)
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, "r", linewidth=2, label=label)
plt.plot([0,1],[0,1],'k--')
plt.grid(True)
plt.xlabel("假正类")
plt.ylabel("真正率")
plot_roc_curve(fpr, tpr)
plt.show()
图1-4 ROC曲线
OK,是不是又发现了有新的问题:召回率(TPR)越高,分类器产生的假正类(FPR)越高。黑色虚线是一个村随机分类器的ROC曲线,而我们要做的就是要远离这条线(当然方向是要向左上角,等下我会解释)
那我们画出ROC后,我们还可以干什么?那就是测量去线下的面积(area under the curve,AUC)。一个很完美的分类器他的ROC AUC会等于1,而纯随机分类器等于0.5。所以这就是为什么我们需要的ROC是要远离黑色虚线,且最好是向左上角。
我们看到ROC曲线和PR曲线还是蛮相似的,那么我们应该如何选择哪条曲线呢。刚好本例给了我们线索,我们发现本例的ROC曲线还是很不错的,但是PR曲线却不是那么完美。这是有一个经验法则可以帮助我们选择:当正类非常少或者你更关注假正类而不是假负类时应该选择PR曲线,反之则是ROC。本例因为非5的数量远远大于5的数量,所以PR曲线可以让我们明白我们需要改进。
Scikit-Learn也提供了计算AUC的函数:
from sklearn.metrics import roc_auc_score
roc_auc_score(y_train_5, y_scores) # 输出 0.9604938554008616
我们知道SGDClassifier似乎还不够好,那我们换一个分类器,比如使用RandomForestClassifier分类器看看。但是由于它们之间的工作方式的不同,RandomForestClassifier分类器没有decicion_function(),但是他又dict_proba()方法,我们可以用这个方法返回某个实例属于某个类别的概率(比如这个图片,有80%为5)。
from sklearn.ensemble import RandomForestClassifier
forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,method="predict_proba")
y_score_forest = y_probas_forest[:,1]
fpr_forest, tpr_forest, threshold_forest = roc_curve(y_train_5, y_score_forest)
plot_roc_curve(fpr_forest, tpr_forest,label="随机森林")
plt.plot(fpr, tpr,"b:",label="SGD" )
plt.legend(loc="lower right", fontsize=16)
plt.show()
图1-4 SGD和随机森林ROC曲线
看上去似乎还不错,我们可以继续计算auc,精度和召回率:
roc_auc_score(y_train_5, y_score_forest)# 输出 0.9983436731328145
y_train_pred_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3)
print(precision_score(y_train_5, y_train_pred_forest))
print(recall_score(y_train_5, y_train_pred_forest))
# 输出
0.9905083315756169
0.8662608374838591
看来随机森林真的很不错,auc有0.998,精度有99.1%,召回率有86.6%。OK,我们已经掌握了二元分类器,并且选择合适的评估方式。