我把自己的原码放在这里了,用Jupyter notebook编写的,包含该系列的所有代码,有需要的同学请自取!!
ROC曲线
ROC曲线全称:受试者工作特征曲线,用于绘制真正类率(即召回率)和假正类率(FPR)。FPR是被错误分成正类的负类实例比率。数值上等于1-真负类率(TNR)。TNR是被正确分类为负类的负类实例比率,也称为特异度。因此,ROC曲线绘制的是灵敏度(召回率)和(1-特异度)的关系。
绘制过程
要绘制ROC曲线,首先需要使用roc_curve()
函数计算多种阈值的TPR和FPR。
计算方式如下:
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
然后使用Matplotlib绘制FPR和TPR的曲线。
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, linewidth=2, label=label)
plt.plot([0, 1], [0, 1], 'k--') # 用于绘制虚线对角线
plt.axis([0, 1, 0, 1])
plt.xlabel('假正率', fontsize=16)
plt.ylabel('真正率(召回率)', fontsize=16)
plt.grid(True)
plt.figure(figsize=(8, 6))
plot_roc_curve(fpr, tpr)
fpr_90 = fpr[np.argmax(tpr >= recall_90_precision)]
plt.plot([fpr_90, fpr_90], [0., recall_90_precision], "r:")
plt.plot([0.0, fpr_90], [recall_90_precision, recall_90_precision], "r:")
plt.plot([fpr_90], [recall_90_precision], "ro")
save_fig("roc_curve_plot")
plt.show()
图像如下:

图中的红点就是我们选定的比率,即精度$90%$的比率。
通过ROC测量分类器性能
有一种比较分类器的方法是测量去线下的面积(AUC)。完美的分类器的ROC,其AUC等于1,而纯随机分类器的ROC其AUC=0.5.Scikit-Learn提供的AUC函数如下:
from sklearn.metrics import roc_auc_score
roc_auc_score(y_train_5, y_scores)
输出:
0.9604938554008616
精度/召回率(PR)曲线与ROC曲线的选择
经验法则:
- 正类非常少,或者分类目标更加关注假正类而不是假负类时,选择PR曲线(如儿童视频过滤)。反之选择ROC曲线。
通过ROC对比不同的而分类器
我们再训练一个随机森林,比较随机森林和SGC的ROC曲线和ROC AUC分数。
注:随机森林没有decision_function()
方法,但有dict_proba()
方法,用于返回一个数组,每行代表一个实例,每列代表一个类别,即:某个给定实例属于某个给定类别的概率。
另外,Scikit-Learn的分类器通常会有这两种方法的一种,或者两种都有
训练随机森林:
from sklearn.ensemble import RandomForestClassifier
forest_clf = RandomForestClassifier(n_estimators=100, random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,
method="predict_proba")
由于roc_curve()
需要标签和分数,但dict-proba()
函数不提供分数,而是提供类的概率,所以我们直接使用正类的概率作为分数值:
y_scores_forest = y_probas_forest[:, 1] # score = 正类概率
fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)
然后绘制ROC曲线:(两条曲线绘制在一块,作为对比)
recall_for_forest = tpr_forest[np.argmax(fpr_forest >= fpr_90)]
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, "b:", linewidth=2, label="SGD")
plot_roc_curve(fpr_forest, tpr_forest, "随机森林")
plt.plot([fpr_90, fpr_90], [0., recall_90_precision], "r:")
plt.plot([0.0, fpr_90], [recall_90_precision, recall_90_precision], "r:")
plt.plot([fpr_90], [recall_90_precision], "ro")
plt.plot([fpr_90, fpr_90], [0., recall_for_forest], "r:")
plt.plot([fpr_90], [recall_for_forest], "ro")
plt.grid(True)
plt.legend(loc="lower right", fontsize=16)
save_fig("roc_curve_comparison_plot")
plt.show()
图像如下:

由图可知,RF的ROC曲线比SGD更靠左上,所以具有更大的AUC,所以随机森林分类器优于SGD分类器。
输出RF的ROC AUC看一下:
roc_auc_score(y_train_5, y_scores_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
这两个指标都比SGD高上不少。
Comments | NOTHING