Python如何为Keras分类器生成ROC曲线的简单指南
阅读本指南后,您将了解如何通过ROC和AUC评估Keras分类器:
为二元分类分类器生成ROC图; 这样做应用交叉验证。
计算AUC并使用它来比较分类器的性能。
将ROC分析应用于多级分类。
ROC和AUC是什么?他们能做什么?
受试者工作特征曲线 (receiver operating characteristic curve,简称ROC曲线)是根据一系列不同的二分类方式(分界值或决定阈),以真阳性率(灵敏度)为纵坐标,假阳性率(1-特异度)为横坐标绘制的曲线。ROC曲线的评价方法与传统的评价方法不同,允许有中间状态,可以把试验结果划分为多个有序分类。我将向你展示如何通过one-vs-all方法将ROC绘制成多标签分类器。
AUC(Area Under Curve)被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。
ROC,二元分类器的AUC
首先,让我们使用Sklearn的make_classification()函数来生成一些训练/测试数据。
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=80000)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
X_train, X_train_lr, y_train, y_train_lr = train_test_split(X_train,
y_train,
test_size=0.5)
接下来,我们照例构建和训练Keras分类器模型。
from keras.models import Sequential
from keras.layers import Dense
def build_model():
model = Sequential()
model.add(Dense(20, input_dim=20, activation='relu'))
model.add(Dense(40, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
from keras.wrappers.scikit_learn import KerasClassifier
keras_model = build_model()
keras_model.fit(X_train, y_train, epochs=5, batch_size=100, verbose=1)
然后我们在保留的测试数据上调用model.predict来生成概率值。之后,使用概率和基础标签生成绘制ROC曲线所必需的两个数据阵列对:
fpr:每个可能阈值的假阳性率
tpr:对于每个可能的阈值,均为真正的阳性率
我们可以调用sklearn的roc_curve()函数来生成这两个。这是使它们发生的代码。
from sklearn.metrics import roc_curve
y_pred_keras = keras_model.predict(X_test).ravel()
fpr_keras, tpr_keras, thresholds_keras = roc_curve(y_test, y_pred_keras)
AUC值也可以像这样计算。
from sklearn.metrics import auc
auc_keras = auc(fpr_keras,tpr_keras)
让我们训练另一个二元分类器,并稍后在同一图表中将其与我们的Keras分类器进行比较。
from sklearn.ensemble import RandomForestClassifier
#基于随机森林的监督转化
rf = RandomForestClassifier(max_depth = 3,n_estimators = 10)
rf.fit(X_train,y_train)
y_pred_rf = rf.predict_proba(X_test)[:,1 ]
fpr_rf,tpr_rf,thresholds_rf = roc_curve(y_test,y_pred_rf)
auc_rf = auc(fpr_rf,tpr_rf)
现在,让我们绘制两个分类器的ROC。
plt.figure(1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_keras, tpr_keras, label='Keras (area = {:.3f})'.format(auc_keras))
plt.plot(fpr_rf, tpr_rf, label='RF (area = {:.3f})'.format(auc_rf))
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve')
plt.legend(loc='best')
plt.show()
# Zoom in view of the upper left corner.
plt.figure(2)
plt.xlim(0, 0.2)
plt.ylim(0.8, 1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_keras, tpr_keras, label='Keras (area = {:.3f})'.format(auc_keras))
plt.plot(fpr_rf, tpr_rf, label='RF (area = {:.3f})'.format(auc_rf))
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve (zoomed in at top left)')
plt.legend(loc='best')
plt.show()
结果如下:
正如你所看到的,考虑到AUC度量,Keras分类器优于其他分类器。
ROC,用于分类分类器的AUC
ROC曲线延伸到三个或更多类的问题,即所谓的one-vs-all”方法。
例如,如果我们有三个类,我们将创建三条ROC曲线,
对于每个类,我们把它作为正类,并将其余的类作为负类。
Class 1 vs classes 2&3
Class 2 vs classes 1&3
Class 3 vs classes 1&2
让我们开始创建一些带3类输出的训练/测试数据。
from sklearn.datasets import make_classification
from sklearn.preprocessing import label_binarize
# 3 classes to classify
n_classes = 3
X, y = make_classification(n_samples=80000, n_features=20, n_informative=3, n_redundant=0, n_classes=n_classes,
n_clusters_per_class=2)
# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
然后,我们像以前一样构建和训练一个分类Keras分类器。
from keras.models import Sequential
from keras.layers import Dense
def build_model():
model = Sequential()
model.add(Dense(20, input_dim=20, activation='relu'))
model.add(Dense(40, activation='relu'))
model.add(Dense(3, activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
keras_model2 = build_model()
keras_model2.fit(X_train, y_train, epochs=10, batch_size=100, verbose=1)
在对模型进行训练之后,我们可以使用它来对测试输入进行预测,并为三个类中的每一个绘制ROC。
在此之前,让我们定义度量标准以评估所有类的总体表现。有两个略有不同的指标,micro and macro averaging。
在“macro averaging”中,我们根据k-class模型的单个真阳性、真阴性、假阳性和假阴性计算性能,例如精度:
在macro averaging中,我们平均每个类的性能:
这里是绘制这些ROC曲线和AUC值的代码。
import numpy as np
from scipy import interp
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn.metrics import roc_curve, auc
# Plot linewidth.
lw = 2
# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
roc_auc[i] = auc(fpr[i], tpr[i])
# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])
# Compute macro-average ROC curve and ROC area
# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))
# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
for i in range(n_classes):
mean_tpr += interp(all_fpr, fpr[i], tpr[i])
# Finally average it and compute AUC
mean_tpr /= n_classes
fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])
# Plot all ROC curves
plt.figure(1)
plt.plot(fpr["micro"], tpr["micro"],
label='micro-average ROC curve (area = {0:0.2f})'
''.format(roc_auc["micro"]),
color='deeppink', linestyle=':', linewidth=4)
plt.plot(fpr["macro"], tpr["macro"],
label='macro-average ROC curve (area = {0:0.2f})'
''.format(roc_auc["macro"]),
color='navy', linestyle=':', linewidth=4)
colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):
plt.plot(fpr[i], tpr[i], color=color, lw=lw,
label='ROC curve of class {0} (area = {1:0.2f})'
''.format(i, roc_auc[i]))
plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Some extension of Receiver operating characteristic to multi-class')
plt.legend(loc="lower right")
plt.show()
# Zoom in view of the upper left corner.
plt.figure(2)
plt.xlim(0, 0.2)
plt.ylim(0.8, 1)
plt.plot(fpr["micro"], tpr["micro"],
label='micro-average ROC curve (area = {0:0.2f})'
''.format(roc_auc["micro"]),
color='deeppink', linestyle=':', linewidth=4)
plt.plot(fpr["macro"], tpr["macro"],
label='macro-average ROC curve (area = {0:0.2f})'
''.format(roc_auc["macro"]),
color='navy', linestyle=':', linewidth=4)
colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):
plt.plot(fpr[i], tpr[i], color=color, lw=lw,
label='ROC curve of class {0} (area = {1:0.2f})'
''.format(i, roc_auc[i]))
plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Some extension of Receiver operating characteristic to multi-class')
plt.legend(loc="lower right")
plt.show()
这是结果,第二个图是图的左上角的放大视图。
总结
在本教程中,我们逐步了解了如何使用ROC曲线和AUC值评估二元和分类Keras分类器。
ROC曲线将测试集上的排序器或概率模型的质量可视化,而不必承诺分类阈值。我们还学会了如何计算AUC值来帮助我们访问分类器的性能。