二分类模型 AUC 评价法


二分类模型 AUC 评价法

对于二分类模型,其实既可以构建分类器,也可以构建回归(比如同一个二分类问题既可以用 SVC 又可以 SVR,python 的 sklearn 中 SVC 和 SVR 是分开的,R 的 e1701 中都在 svm 中,仅当 y 变量是 factor 类型时构建 SVC,否则构建 SVR)。

二分类模型的评价指标很多,这里仅叙述 AUC 这个指标。分类问题中,正类预测 score 大于负类预测 score 的概率即是 C 指数(Mann–Whitney U 检验的 C 统计量),也称 AUC,推导可以参考:AUC 与 Mann–Whitney U test 以及 wikipedia/Mann_Whitney_U_test。AUC 的具体原理此处不再叙述,可以参考相关资料,比如这两个还行:ROC 和 AUC 介绍以及如何计算 AUC机器学习之分类性能度量指标,以及这两个也有些不错的思考:AUC 原理介绍及求解方法总结

其实,ROC 的另一种呈现可以是直方图(或密度图)形式,即横坐标是 score,直方图(密度图)的颜色是真实类别,比如下面这种:

img

若构建 regression,可以直接将 predict 的值和真实值直接扔进 auc 函数里去计算,就是让程序去逐个找 predict 的 cutoff 值就可以构建 ROC 了。

但是如果是 classifier,因为直接 predict 的值是 0 或 1,无法计算 auc,此时需要借助于 “预测概率”,sklearn 中常调用 predict_proba 函数来获取。另外,Logistics 回归,python 的 predict 也是 0 或 1,也需要调用 predict_proba 函数来获取相应 “预测概率”。还有个 decision_function,其意义是当这个值大于 0 时,相应的样本预测为正例。R 中不会有这些问题,R 都是简单易用的。

AUC 的计算举例:

test_auc = metrics.roc_auc_score(y_test,y_test_pre)

ROC 的计算举例:

fpr, tpr, thresholds = metrics.roc_curve(y_test,y_test_pre)
plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % test_auc)

Classifier 的其他相关评价指标

准确度 accuracy:可以用 classifier.score 计算 accuracy。理解为正确率,就是分类正确的占总数的比例,即 (TP+TN)/Total。

二分类问题中,当其中某一类数量远小于另一类时,如果追求准确度,那么只需要将分类结果全指定为数量多的那类即可。所以这种情况下仅用 accuracy 评价是不够的。

精确度 precision:又叫 “查准率”、用 P 表示。这是针对其中一类而言。比如我建模的目的是找出正例,那么 precision 就是真正的正例 / 找出来的所有,即 TP/(TP+FP)。

召回率 recall:又叫 “查全率”、“灵敏度”、“真阳性率 TPR”,用 R 表示。也是针对其中一类而言。比如建模的目的是找出正例,那么 recall 就是真正的正例 / 所有的正例,即 TP/(TP+FN)。另,假阴性率 FNR(漏诊率)=FN/(TP+FN),FNR=1-R。

真阴性率 TNR:又叫 “特异度”,TNR=TN/(TN+FP)。假阳性率 FPR:又叫 “误诊率”。TNR+FPR=1。(还记得 ROC 的横坐标吗)

总而言之,准确率就是找得对,召回率就是找得全。

关于灵敏度和特异度的关系:如果说灵敏度为正例的召回率,那么特异度就是反例的召回率。当正例和反例同样重要时,灵敏度和特异度的重要性也一样。所以,在无偏的分类模型中(各类的重要性相同),由灵敏度和特异度组合的指标(如 AUC)是十分重要的指标。注意,当模型是为了找出特殊人群(比如找出高危人群)时,识别特殊人群的灵敏度,要比特异度更重要。

你问问一个模型,这堆东西是不是某个类的时候,准确率就是 它说是,这东西就确实是的概率吧,召回率就是, 它说是,但它漏说了(1 - 召回率)这么多

F1 值:是精确值和召回率的调和均值,即 2/F1=1/precision+1/recall。Fβ是更一般的形式,对 precision 和 recall 加权。而 F1 是其特殊情况,认为 precision 和 recall 同等重要。推广的话还有 macro-P、macro-R、macro-F1 及 micro-P、micro-R、micro-F1 等。

贴张图(来自:机器学习】分类性能度量指标 : ROC 曲线、AUC 值、正确率、召回率、敏感度、特异度

img

另外 wiki 上也有张图:

img

准确率和召回率是互相影响的,理想情况下肯定是做到两者都高,但是一般情况下准确率高、召回率就低,召回率低、准确率高,当然如果两者都低,那是什么地方出问题了

如果是做搜索,那就是保证召回的情况下提升准确率;如果做疾病监测、反垃圾,则是保准确率的条件下,提升召回。

所以,在两者都要求高的情况下,可以用 F1 来衡量。

P/R 和 ROC 是两个不同的评价指标和计算方式,一般情况下,检索用前者,分类、识别等用后者。

参考一篇还不错的博客:【机器学习】分类性能度量指标 : ROC 曲线、AUC 值、正确率、召回率、敏感度、特异度

一般认为,AUC<0.6 时区分度较差,0.6-0.75 时区分能力一般,>7.5 时区分能力较好。

两个模型的 AUC 是可以进行统计学差异检验的,采用 Z 检验,统计量 Z 近似服从正态分布。计算公式如下:

img

SE1 和 SE2 分别为 AUC1 和 AUC2 的标准误。

贴几段代码

# SVR与SVC的AUC/ROC计算
import numpy as np
from sklearn.svm import SVR,SVC
from sklearn.model_selection import train_test_split
from sklearn import metrics
 
x_train, x_test, y_train, y_test = train_test_split(X, Y,  train_size=0.7)
 
print("------------------------------ SVC ------------------------------------------")
clf = SVC(kernel='rbf', C=100, gamma=0.0001, probability=True)
clf.fit(x_train, y_train)
 
y_train_pre = clf.predict(x_train)
y_test_pre = clf.predict(x_test)
print("Accuracy: "+str(clf.score(x_train,y_train)))  
 
y_train_predict_proba = clf.predict_proba(x_train) #每一类的概率
false_positive_rate, recall, thresholds = roc_curve(y_train, y_train_predict_proba[:, 1])
train_auc=auc(false_positive_rate,recall)
print("train AUC: "+str(train_auc))
 
print("------------------------------------")
print("Accuracy: "+str(clf.score(x_test,y_test)))
 
y_test_predict_proba = clf.predict_proba(x_test) #每一类的概率
false_positive_rate, recall, thresholds = roc_curve(y_test, y_test_predict_proba[:, 1])
test_auc=auc(false_positive_rate,recall)
print("test AUC: "+str(test_auc))
 
plt.figure(0)
plt.title('ROC of SVM in test data')
plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % test_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('Fall-out')
plt.show()
 
print("--------------------------- SVR ------------------------------------------")
 
reg = SVR(kernel='rbf', C=100, gamma=0.0001)
reg.fit(x_train, y_train)
y_train_pre = reg.predict(x_train)
y_test_pre = reg.predict(x_test)
train_auc = metrics.roc_auc_score(y_train,y_train_pre)
print("train AUC: "+str(train_auc))
 
print("--------------------------------")
 
test_auc = metrics.roc_auc_score(y_test,y_test_pre)
print("test AUC: "+str(test_auc))
fpr, tpr, thresholds = metrics.roc_curve(y_test,y_test_pre)
 
plt.figure(1)
plt.title('ROC of SVR in test data')
plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % test_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('Fall-out')
plt.show()

Logistics 回归代码段

# Logistics regression
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve,auc
from sklearn.model_selection import train_test_split
 
# input X、y
 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) 
# clf = LogisticRegression(random_state=0, solver='lbfgs' ,multi_class='multinomial')
clf = LogisticRegression()
clf.fit(x_train, y_train)
 
# 一下几行仅用于展现那几个函数的作用,实际使用不应随便挑几个数据验证
logi_pre=clf.predict(X[:5, :])
logi_pro=clf.predict_proba(X[:5, :]) 
logi_accuracy=clf.score(x_test, y_test)
logi_deci=clf.decision_function(X[-5:,:])
print(y)
print("prediction of first 5 samples: ",end=" ")
print(logi_pre)
print("prediction probability of first 5 samples: ")
print(logi_pro)
print("decision_function of last 5 samples(大于0时,正类被预测): ",end=" ")
print(logi_deci)
print("prediction accuracy of test data: ",end=" ")
print(logi_accuracy)
 
predictions=clf.predict_proba(x_test)#每一类的概率
false_positive_rate, recall, thresholds = roc_curve(y_test, predictions[:, 1])
roc_auc=auc(false_positive_rate,recall)
plt.title('ROC of logistics in test data')
plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('Fall-out')
plt.show()

AUC/ROC 计算的 sklearn 官网举例

print(__doc__)
# ROC for model
 
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
 
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp
 
# Import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target
 
# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]
 
# Add noisy features to make the problem harder
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]
 
# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,
                                                    random_state=0)
 
# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,
                                 random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)
 
# 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"])
 
plt.figure()
lw = 2
plt.plot(fpr[2], tpr[2], color='darkorange',
         lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', lw=lw, 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 example')
plt.legend(loc="lower right")
plt.show()

题外话:SVM 参数设置的案例

import numpy as np
from sklearn.svm import SVR,SVC
import matplotlib.pyplot as plt
 
# #############################################################################
# Generate sample data
X = np.sort(16 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel()
 
# #############################################################################
# Add noise to targets
y[::5] += 3 * (0.5 - np.random.rand(16))
 
# Fit regression model
svr_rbf = SVC(kernel='rbf', C=1e3, gamma=0.1)
# svr_rbf = SVR(kernel='rbf', C=1e3, gamma=100) #可能过拟合
# svr_lin = SVR(kernel='linear', C=1e3)
# svr_poly = SVR(kernel='poly', C=1e3, degree=2)
y_rbf = svr_rbf.fit(X, y).predict(X)
 
# Look at the results
lw = 2
plt.scatter(X, y, color='darkorange', label='data')
plt.plot(X, y_rbf, color='navy', lw=lw, label='RBF model')
# plt.plot(X, y_lin, color='c', lw=lw, label='Linear model')
# plt.plot(X, y_poly, color='cornflowerblue', lw=lw, label='Polynomial model')
plt.xlabel('data')
plt.ylabel('target')
plt.title('Support Vector Regression')
plt.legend()
plt.show()


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM