机器学习之二分类模型评价指标
- 一、二分类模型衡量指标
-
- 1.1 混淆矩阵:Confusion matrix
-
- 1.2 精确度:Accuracy
-
- 1.3 准确率:Precision
-
- 1.4 召回率:Recall
-
- 1.5 F1-Score
-
- 1.6 PR曲线
-
- 1.7 ROC曲线
-
- 1.8 AUC值
-
- 1.9 KS值
-
一、二分类模型衡量指标
1.1 混淆矩阵:Confusion matrix
1.1.1 原理
- P(Positive) :代表1
- N(Negative) :代表0
- T(True) :代表预测正确
- F(False) :代表预测错误
1.1.2 实现
from sklearn.metrics import confusion_matrix
confusion_matrix(y_true,y_pred,labels=None,sample_weight = None)
'''
y_true:真实的label,一维数组,列名
y_pred:预测值的label,一维数组,行名
labels:默认不指定,此时y_true,y_pred去并集,做升序,做label
sample_weight:样本权重
返回结果:返回混淆矩阵
'''
import numpy as np
from sklearn.metrics import confusion_matrix
y_true = np.array([0,1,1,1,0,0,1,0,0,1])
y_pred = np.array([0,0,1,1,1,0,1,1,0,1])
confusion_matrix = confusion_matrix(y_true,y_pred)
confusion_matrix
array([[3, 2],
[1, 4]], dtype=int64)
1.2 精确度:Accuracy
1.2.1 原理
- 预测正确的结果占总样本的比例。
P r e c i s i o n = T P + T N T P + F P + T N + F N Precision=\frac{TP+TN}{TP+FP+TN+FN} Precision=TP+FP+TN+FNTP+TN
- 缺点:在样本不平衡时,不能很好的衡量结果。如正样本占90%,负样本占10%,样本是严重不平衡的。对于这种情况,我们只需要将全部样本预测为正样本即可得到90%的高准确率,但模型对负样本没有任何识别度。正因为如此,也就衍生了其他两种指标:准确率和召回率。
1.2.2 实现
from sklearn.metrics import accuracy_score
accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
'''
y_true:数据的真实label值
y_pred:数据的预测标签值
normalize:默认为True,返回正确预测的个数,若是为False,返回正确预测的比例
sample_weight:样本权重
返回结果:score为正确预测的个数或者比例,由normalize确定
'''
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score
y_true = [1,1,0,1,0]
y_pred = [1,1,1,0,0]
score = accuracy_score(y_true,y_pred)
print(score)
score1 = accuracy_score(y_true,y_pred,normalize = True)
print(score1)
1.3 准确率:Precision
1.3.1 原理
- 又叫查准率,含义是所有被预测为正的样本中实际为正的样本的比例。
P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP+FP} Precision=TP+FPTP
1.3.2 实现
from sklearn.metrics import classification_report
classification_report(y_true, y_pred, labels=None,
target_names=None, sample_weight=None, digits=2, output_dict=False)
'''
y_true:真实的label,一维数组,列名
y_pred:预测值的label,一维数组,行名
labels:默认不指定,此时y_true,y_pred去并集,做升序,做label
sample_weight:样本权重
target_names:行标签,顺序和label的要一致
digits,整型,小数的位数
out_dict:输出格式,默认False,如果为True,输出字典。
'''
import numpy as np
from sklearn.metrics import classification_report
y_true = np.array([0,1,1,0,1,2,1])
y_pred = np.array([0,1,0,0,1,2,1])
target_names = ['class0','class1','class2']
print(classification_report(y_true,y_pred,target_names = target_names))
precision recall f1-score support
class0 0.67 1.00 0.80 2
class1 1.00 0.75 0.86 4
class2 1.00 1.00 1.00 1
micro avg 0.86 0.86 0.86 7
macro avg 0.89 0.92 0.89 7
weighted avg 0.90 0.86 0.86 7
1.4 召回率:Recall
1.4.1 原理
- 又叫查全率,含义是实际为正的样本中被预测为正样本的比例。
R e c a l l = T P T P + F N Recall=\frac{TP}{TP+FN} Recall=TP+FNTP
- 召回率的应用场景:比如拿网贷违约率为例,相对好用户,我们更关心坏用户,不能错放过任何一个坏用户。因为如果我们过多的将坏用户当成好用户,这样后续可能发生的违约金额会远超过好用户偿还的借贷利息金额,造成严重偿失。召回率越高,代表实际坏用户被预测出来的概率越高,它的含义类似:宁可错杀一千,绝不放过一个。
1.4.2 实现
1.5 F1-Score
1.5.1 原理
- 找寻Precision和Recall之间的平衡,是一个综合的评价指标。
F 1 − S c o r e = 2 1 P r e c i s i o n 1 R e c a l l = 2 ∗ P r e c i s i o n ∗ R e c a l l P r e c i s i o n + R e c a l l F1-Score=\frac{2}{\frac{1}{Precision}\frac{1}{Recall}}=\frac{2*Precision*Recall}{Precision+Recall} F1−Score=Precision1Recall12=Precision+Recall2∗Precision∗Recall
1.5.2 实现
1.6 PR曲线
1.6.1 原理
- 当正负样本数差距不大时,ROC和PR曲线的趋势是差不多的,在正负样本分布不均匀的情况下,PRC比ROC能更有效地反应分类器的好坏。
- 横坐标是查全率Recall,纵坐标是查准率Precision。
- 当PR曲线越靠近右上方时,表明模型性能越好;
- 与ROC曲线类似,在对不同模型进行比较时,若一个模型的PR曲线被另一个模型的PR曲线完全包住则说明后者的性能优于前者.如上图中橘色线代表的模型要优于蓝色线代表的模型;
- 若模型的PR曲线发生了交叉,则无法直接判断哪个模型更好。在周志华老师的机器学习上中提到了可以用平衡点。它是查准率=查全率时的取值,如上图黑色线代表的模型的平衡点要大于橘色线模型代表的平衡点,表明前者优于后者,除此之外更为常用的是F1 score,也就是查准率和查全率的加权平均,F1 = (2查准率查全率)/(查准率+查全率)
- PR曲线绘制:设置一个从高到低的阈值,预测概率大于等于阈值的样本被预测为正类,小于阈值的样本被预测为负类。显然,设置n个阈值后,就可以得到n个混淆矩阵,从而得到n对Precision和Recall的值,便可绘制成PR曲线。
1.6.1 实现
from sklearn.metrics import precision_recall_curve
precision, recall, t =precision_recall_curve(y_test, y_score)
print(t)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.ylim([0.0, 1.0])
plt.xlim([0.0, 1.0])
plt.plot(recall, precision)
plt.title("Precision-Recall")
plt.show()
1.7 ROC曲线
1.7.1 原理
- TPR(True Positive Rate):真正例率,等于Recall。
T P R = T P T P + F N TPR=\frac{TP}{TP+FN} TPR=TP+FNTP
- FPR(False Positive Rate):假正例率
F P R = F P F P + T N FPR=\frac{FP}{FP+TN} FPR=FP+TNFP
- ROC:Receiver Operating Characteristic Curve,中文名字叫“受试者工作特征曲线”,ROC曲线以FPR为横坐标,TPR为纵坐标,样本数量越多,ROC曲线越平滑。
1.7.2 实现
from sklearn.metrics import roc_curve, auc
fpr,tpr,threshold = roc_curve(y_test, y_score)
roc_auc = auc(fpr,tpr)
plt.figure()
lw = 2
plt.figure(figsize=(10,10))
plt.plot(fpr, tpr,
lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], 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('ROC')
plt.legend(loc="best")
plt.show()
1.8 AUC值
1.8.1 原理
- AUC值是ROC曲线下方的面积,越接近于1,模型效果越好。
- 比较有意思的是,如果我们连接对角线,它的面积正好是0.5。对角线的实际含义是:随机判断正负样本,正负样本比率应该都是50%,表示随机效果。即最差的随机判断都有0.5,所以一般AUC的值是介于0.5到1之间的。
- UC的一般判断标准:
0.5 - 0.7:效果较低,但用于预测股票已经很不错了
0.7 - 0.85:效果一般
0.85 - 0.95:效果很好
0.95 - 1:效果非常好,但一般不太可能
1.8.2 实现
from sklearn.metrics import roc_curve, auc
fpr,tpr,threshold = roc_curve(y_test, y_score)
roc_auc = auc(fpr,tpr)
print(roc_auc)
0.8133333333333334
1.9 KS值
1.9.1 原理
- KS值是风控领域常用语评估模型区分度的指标。
K S = m a x ( T P R − F P R ) KS=max(TPR-FPR) KS=max(TPR−FPR)
- KS值用来评估模型的区分能力,KS值越大,模型的区分能力越强。
1.9.2 实现
from sklearn.metrics import roc_curve, auc
fpr,tpr,threshold = roc_curve(y_test, y_score)
ks=max(tpr-fpr)
print(ks)
y_true,y_pred = y_train,pred_train
df = pd.DataFrame({"y":y_true,"pred":y_pred})
good_cumlis = []
bad_cumlis = []
good_total = np.sum(df['y']==0)
bad_total = np.sum(df['y']==1)
for i in cutlist:
tmpdf = df.loc[df['pred']<=i,:]
a = np.sum(tmpdf['y']==0)
b = np.sum(tmpdf['y']==1)
good_cumlis.append(a/good_total)
bad_cumlis.append(b/bad_total)
df2 = pd.DataFrame({"cutoff":cutlist,
"good_cum":good_cumlis,
"bad_cum":bad_cumlis,
"delta(good_cum,bad_cum)":[a-b for a,b in zip(good_cumlis,bad_cumlis)]})
plt.figure(figsize=(6,5))
deltalis = df2['delta(good_cum,bad_cum)'].tolist()
plt.plot(cutlist,df2['good_cum'], label = 'good_cum')
plt.plot(cutlist,df2['bad_cum'], label = 'bad_cum')
plt.plot(cutlist,deltalis,label = 'delta')
plt.legend(loc = 'best')
x1=cutlist[deltalis.index(max(deltalis))]
y1=max(deltalis)
plt.scatter(x1,y1,color='red')
plt.xlabel("cutoff")
plt.ylabel("delta(good_cum,bad_cum)")
plt.show()
print("Delta最大值坐标:\ncutoff=%.4f\ndelta(good_cum,bad_cum)=ks=%.4f"%(x1,y1))
Delta最大值坐标:
cutoff=0.4174
delta(good_cum,bad_cum)=ks=0.5083
- KS计算参考:
1. https://zhuanlan.zhihu.com/p/365959002
2. https://blog.csdn.net/sinat_26917383/article/details/51725102