2018-12-06 16:22:35 zwqjoy 阅读数 8545
  • Kubernetes 实战系列

    Kubernetes(KS8) 实战系列教程,该课程将对Kubernetes的Node、Pod、Replication Controller、Service等基本核心概念进行讲解,这些组件共同构成了Kubernetes的系统框架和计算模型。通过对它们进行灵活的组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。

    9532 人正在学习 去看看 CSDN讲师

目录

 

背景介绍

一 ROC曲线和AUC值

二 KS曲线

三 GINI系数

四 Lift , Gain

五 模型稳定度指标PSI

 


参考另一篇:[机器学习] 性能评估指标(精确率、召回率、ROC、AUC) 

背景介绍

在模型建立之后,必须对模型的效果进行评估,因为数据挖掘是一个探索的过程,评估-优化是一个永恒的过程。在分类模型评估中,最常用的两种评估标准就是KS值和GINI, AUC值.可能有人会问了,为什么不直接看正确率呢?你可以这么想,如果一批样本中,正样本占到90%,负样本只占10%,那么我即使模型什么也不做,把样本全部判定为正,也能有90%的正确率咯?所以,用AUC值够保证你在样本不均衡的情况下也能准确评估模型的好坏,而KS值不仅能告诉你准确与否,还能告诉你模型对好坏客户是否有足够的区分度。

 

这里先整体给大家一个直观的介绍。

概括:

Confusion Matrix -> Lift,Gain,ROC。

ROC -> AUC,KS -> GINI。

 

在介绍之前,我们先重新明确一下这些图表的名称,中文、英文、简称,全部来熟悉一下:

记住这个之后,我们来理解一下他们之间的关系。

拟人化概括

其实,这些图之间的关系不是很复杂。我尝试着用一个小故事概括一下人物之间的关系。

故事是这样的:

首先,混淆矩阵是个元老,年龄最大也资历最老。创建了两个帮派,一个夫妻帮,一个阶级帮。

之后,夫妻帮里面是夫妻两个,一个Lift曲线,一个Gain曲线,两个人不分高低,共用一个横轴。

再次,阶级帮里面就比较混乱。

           1. 帮主是ROC曲线。

           2. 副帮主是KS曲线,AUC面积

           3. AUC养了一个小弟,叫GINI系数

 

下图是曲线与指标的综合对比图

 

一 ROC曲线和AUC值

在逻辑回归、随机森林、GBDT、XGBoost这些模型中,模型训练完成之后,每个样本都会获得对应的两个概率值,一个是样本为正样本的概率,一个是样本为负样本的概率。把每个样本为正样本的概率取出来,进行排序,然后选定一个阈值,将大于这个阈值的样本判定为正样本,小于阈值的样本判定为负样本,然后可以得到两个值,一个是真正率,一个是假正率。

真正率即判定为正样本且实际为正样本的样本数/所有的正样本数,假正率为判定为正样本实际为负样本的样本数/所有的负样本数。每选定一个阈值,就能得到一对真正率和假正率,由于判定为正样本的概率值区间为[0,1],那么阈值必然在这个区间内选择,因此在此区间内不停地选择不同的阈值,重复这个过程,就能得到一系列的真正率和假正率,以这两个序列作为横纵坐标,即可得到ROC曲线了。而ROC曲线下方的面积,即为AUC值。

对于AUC值,也许有一个更直观的理解,那就是,在按照正样本概率值对所有样本排序后,任意选取一对正负样本,正样本排在负样本之前的概率值,即为AUC值。也就是说,当所有的正样本在排序后都能排在负样本之前时,就证明所有的样本都被正确分类了,此时的AUC值也会为1。那么AUC值也就很好算了,如果有N个负样本,其中正样本有M个,那么可取的所有带正样本的样本对数对于排在第一位的正样本来说,有M+N-1个,但其中包含M-1对(正,正)的样本,而对于后面所有的正样本而言,能够取到的正样本概率大于负样本对数肯定小于其位置-1。


二 KS曲线

KS曲线其实数据来源和本质和ROC曲线是一致的,只是ROC曲线是把真正率和假正率当作横纵轴,而K-S曲线是把真正率和假正率都当作是纵轴,横轴则由选定的阈值来充当。

KS(Kolmogorov-Smirnov):KS用于模型风险区分能力进行评估,指标衡量的是好坏样本累计分部之间的差值。好坏样本累计差异越大,KS指标越大,那么模型的风险区分能力越强。

KS的计算步骤如下:
1. 计算每个评分区间的好坏账户数。
2. 计算每个评分区间的累计好账户数占总好账户数比率(good%)和累计坏账户数占总坏账户数比率(bad%)。
3. 计算每个评分区间累计坏账户占比与累计好账户占比差的绝对值(累计good%-累计bad%),然后对这些绝对值取最大值即得此评分卡的KS值。

 

下面这一段解释得更详细的KS和AUC的区别是参考的这篇博客:

https://blog.csdn.net/sinat_30316741/article/details/80018932

由于KS值能找出模型中差异最大的一个分段,因此适合用于cut_off,像评分卡这种就很适合用ks值来评估。但是ks值只能反映出哪个分段是区分最大的,而不能总体反映出所有分段的效果,因果AUC值更能胜任。
ROC值一般在0.5-1.0之间。值越大表示模型判断准确性越高,即越接近1越好。ROC=0.5表示模型的预测能力与随机结果没有差别。
KS值表示了模型将+和-区分开来的能力。值越大,模型的预测准确性越好。一般,KS>0.2即可认为模型有比较好的预测准确性。
KS值一般是很难达到0.6的,在0.2~0.6之间都不错。一般如果是如果负样本对业务影响极大,那么区分度肯定就很重要,此时K-S比AUC更合适用作模型评估,如果没什么特别的影响,那么用AUC就很好了。

区分度指标(KS)是度量具体模型下正常样本和违约样本分布的最大差距,首先按照样本的信用分数或预测违约率从小到大进行排序,然后计算每一个分数或违约率下好坏样本的累计占比。正常和违约样本的累计占比差值的最大值即为区分度指标(KS)

 

风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)
 

实际上是就是你建立好模型后,按照评分从大到小排列后:检验你所谓的好客户和坏客户两类客户分布的差异性,即模型区分度。分布根据好坏两个客户评分的累积密度分布曲线,画出来的:比如好坏客户共100个,按照评分排序后前百分之十的客户即10个,其中好的客户有8个,坏的客户有2个(总体样本中好客户80个,坏客户20个),那么前10%的客户的累积密度为:好客户10%,坏客户10%。同理前20%的客户中其中好的客户有15个,坏的客户有5个那么前20%的客户的累积密度为:好客户18.75%,坏客户25%
以此类推可以得出前30%,40%。。。。100%的累积密度。以10%,20%,30%。。。100%为横坐标,以两类客户累积密度为纵坐标,即可画出KS曲线图。

 

三 GINI系数

 

·GINI系数:也是用于模型风险区分能力进行评估。
GINI统计值衡量坏账户数在好账户数上的的累积分布与随机分布曲线之间的面积,好账户与坏账户分布之间的差异越大,GINI指标越高,表明模型的风险区分能力越强。

GINI系数的计算步骤如下:
1. 计算每个评分区间的好坏账户数。
2. 计算每个评分区间的累计好账户数占总好账户数比率(累计good%)和累计坏账户数占总坏账户数比率(累计bad%)。
3. 按照累计好账户占比和累计坏账户占比得出下图所示曲线ADC。
4. 计算出图中阴影部分面积,阴影面积占直角三角形ABC面积的百分比,即为GINI系数。

 

四 Lift , Gain

前三个指标应用场景更多一些


Lift图衡量的是,与不利用模型相比,模型的预测能力“变好”了多少,lift(提升指数)越大,模型的运行效果越好。
Gain图是描述整体精准度的指标。
计算公式如下:
                                       
                                                       
                  
作图步骤:
1. 根据学习器的预测结果(注意,是正例的概率值,非0/1变量)对样本进行排序(从大到小)-----这就是截断点依次选取的顺序
2. 按顺序选取截断点,并计算Lift和Gain ---也可以只选取n个截断点,分别在1/n,2/n,3/n等位置
例图:

   
 

 

 

五 模型稳定度指标PSI

群体稳定性指标PSI(Population Stability Index)是衡量模型的预测值与实际值偏差大小的指标。

PSI = sum((实际占比-预期占比)* ln(实际占比/预期占比))

举例:

比如训练一个logistic回归模型,预测时候会有个概率输出p。
测试集上的输出设定为p1吧,将它从小到大排序后10等分,如0-0.1,0.1-0.2,......。
现在用这个模型去对新的样本进行预测,预测结果叫p2,按p1的区间也划分为10等分。
实际占比就是p2上在各区间的用户占比,预期占比就是p1上各区间的用户占比。
意义就是如果模型跟稳定,那么p1和p2上各区间的用户应该是相近的,占比不会变动很大,也就是预测出来的概率不会差距很大。

一般认为PSI小于0.1时候模型稳定性很高,0.1-0.25一般,大于0.25模型稳定性差,建议重做。

PS:除了按概率值大小等距十等分外,还可以对概率排序后按数量十等分,两种方法计算得到的psi可能有所区别但数值相差不大。

 

 

参考:

  1. https://blog.csdn.net/Orange_Spotty_Cat/article/details/82425113
  2. https://blog.csdn.net/shy19890510/article/details/79501582
2017-10-24 21:24:51 yaoqsm 阅读数 15718
  • Kubernetes 实战系列

    Kubernetes(KS8) 实战系列教程,该课程将对Kubernetes的Node、Pod、Replication Controller、Service等基本核心概念进行讲解,这些组件共同构成了Kubernetes的系统框架和计算模型。通过对它们进行灵活的组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。

    9532 人正在学习 去看看 CSDN讲师

先上图


ROC曲线是评判一个模型好坏的标准,有两个值要知道,FPR(假正率)和TPR(真正率),ROC曲线就是以这两个值为坐标轴画的。比如逻辑回归得到的结果是概率,那么就要取阈值来划分正负,这时候,每划一个阈值,就会产生一组FPR和TPR的值,然后把这组值画成坐标轴上的一个点,这样,当选取多组阈值后,就形成了ROC曲线(每次选取一个不同的阈值,我们就可以得到一组FPR和TPR,即ROC曲线上的一点),AUC值就是ROC曲线下方的面积。图中画出的AUC=0.810就是这个模型能得出的最好的AUC值,其对应的阈值也是最好的划分。但是最好的阈值是不能通过这个图知道的,要通过KS曲线得出。

KS曲线的纵轴是表示TPR和FPR的值,就是这两个值可以同时在一个纵轴上体现,横轴就是阈值,,然后在两条曲线分隔最开的地方,对应的就是最好的阈值,也是该模型最好的AUC值,就比如是上图的AUC=0.810,下图中,一条曲线是FPR,一条是TPR




2018-03-19 16:43:28 cymy001 阅读数 5751
  • Kubernetes 实战系列

    Kubernetes(KS8) 实战系列教程,该课程将对Kubernetes的Node、Pod、Replication Controller、Service等基本核心概念进行讲解,这些组件共同构成了Kubernetes的系统框架和计算模型。通过对它们进行灵活的组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。

    9532 人正在学习 去看看 CSDN讲师

ROC曲线与AUC

ROC曲线下方的面积是AUC,AUC表示对于随机选择的正类别样本确实为正类别,以及随机选择的负类别样本为正类别,分类器更确信前者的概率。
分类问题的模型评估理论参考:
http://blog.csdn.net/cymy001/article/details/79366754
Python机器学习库sklearn分类问题的模型评估API参考:
http://blog.csdn.net/cymy001/article/details/79425233

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize

# Import some data to play with
iris = datasets.load_iris()
X = iris.data   #(150,4)的二维numpy数组<class 'numpy.ndarray'> 
y = iris.target   #(150,)的一维numpy数组标签<class 'numpy.ndarray'>

# Binarize the output
#对类别标签也进行了二值化处理[0 1 2]==>[[1 0 0],[0 1 0],[0 0 1]]
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   #样本数150,特征数4
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]   
#np.c_将多个对象连接到第二个数轴上,增加了800维的特征噪声
#np.random.randn(维度大小参数)从标准正态分布中返回一个或多个样本值
#这里利用随机种子进行改造np.random.RamdonState(0).randn
#np.random.rand(维度大小参数)随机样本位于[0, 1)中

# 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)   #数据集切分

sklearn库API——decision_function(ROC阈值)

%matplotlib inline
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp

# 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)   
#decision_function对于SVC返回每个样本距离决策边界的距离
#decision_function对于LR返回预测样本的置信度分数——该样本与超平面的有符号距离

# 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])   
    #y_test样例真实标签,y_score学习器预测的样例的概率 
    roc_auc[i] = auc(fpr[i], tpr[i])   
    #计算ROC曲线下方的面积,fpr假正例率数组(横坐标),tpr真正例率数组(纵坐标) 

#Plot of a ROC curve for a specific class
plt.rcParams['figure.figsize']=(8,5)
plt.figure()
plt.plot(fpr[2], tpr[2], color='darkorange', label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', 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")

这里写图片描述

Compute micro-average ROC curve and ROC area先计算每一类混淆矩阵,各类混淆矩阵作和除3,再算tpr和fpr
import numpy as np
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())   #ravel函数将矩阵展开成向量
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])
Compute macro-average ROC curve and ROC area先计算出每一类的tpr和fpr,再除3
import numpy as np
# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))   #np.concatenate将“特征维度相同数组”纵向拼接

# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)   #np.zeros_like创建一个和参数all_fpr数组维度相同的全0数组
for i in range(n_classes):
    mean_tpr += interp(all_fpr, fpr[i], tpr[i])   
    #interp一维线性插值,fpr和tpr是插值结点横纵坐标,all_fpr是已知中间节点横坐标(得到插值曲线后,求其纵坐标)
#https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html#numpy.interp

# 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"])
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn.metrics import roc_curve, auc

# Plot all ROC curves
plt.rcParams['figure.figsize']=(8,5)
plt.figure()
plt.plot(fpr["micro"], tpr["micro"], label='micro-average ROC curve (area = {0:0.2f})' ''.format(roc_auc["micro"]),
         color='deeppink', linestyle=':')

plt.plot(fpr["macro"], tpr["macro"], label='macro-average ROC curve (area = {0:0.2f})' ''.format(roc_auc["macro"]),
         color='navy', linestyle=':')

colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])   #python3里的无穷循环器
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, label='ROC curve of class {0} (area = {1:0.2f})' ''.format(i, roc_auc[i]))

plt.plot([0, 1], [0, 1], 'k--')
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")

这里写图片描述

带交叉验证的ROC曲线

准备数据

import numpy as np
from scipy import interp
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 StratifiedKFold

# Data IO and generation

# Import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target
X, y = X[y != 2], y[y != 2]    #去掉一类,下述交叉验证绘制ROC曲线只考虑二分类问题
n_samples, n_features = X.shape

# Add noisy features
random_state = np.random.RandomState(0)
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]

交叉验证计算auc,画图

# Classification and ROC analysis

# Run classifier with cross-validation and plot ROC curves
cv = StratifiedKFold(n_splits=6)
classifier = svm.SVC(kernel='linear', probability=True, random_state=random_state)

tprs = []
aucs = []
mean_fpr = np.linspace(0, 1, 100)

i = 0
for train, test in cv.split(X, y):
    # train和test是交叉验证分组索引
    probas_ = classifier.fit(X[train], y[train]).predict_proba(X[test])   #predict_proba作用类似decision_function
    # Compute ROC curve and area the curve
    fpr, tpr, thresholds = roc_curve(y[test], probas_[:, 1])
    tprs.append(interp(mean_fpr, fpr, tpr))   #根据每一折的fpr和tpr进行插值,得插值曲线后,对相同的mean_fpr求其对应插值曲线上的纵坐标
    #interp一维线性插值,fpr和tpr是插值结点横纵坐标,mean_fpr是已知中间节点横坐标(得到插值曲线后,求其纵坐标)
    #https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html#numpy.interp
    tprs[-1][0] = 0.0   #tprs有6个元素,每个元素是一个长度为100的array
    roc_auc = auc(fpr, tpr)
    aucs.append(roc_auc)   #aucs有6个auc的值,是交叉验证每一折的auc
    plt.plot(fpr, tpr, alpha=0.3, label='ROC fold %d (AUC = %0.2f)' % (i, roc_auc))

    i += 1
plt.plot([0, 1], [0, 1], linestyle='--', color='r', label='Luck', alpha=.8)

mean_tpr = np.mean(tprs, axis=0)   #将每一折交叉验证计算的tpr求和取平均(每个位置对应相同的fpr)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
std_auc = np.std(aucs)
plt.plot(mean_fpr, mean_tpr, color='b', label=r'Mean ROC (AUC = %0.2f $\pm$ %0.2f)' % (mean_auc, std_auc), alpha=.8)

std_tpr = np.std(tprs, axis=0)
tprs_upper = np.minimum(mean_tpr + std_tpr, 1)
tprs_lower = np.maximum(mean_tpr - std_tpr, 0)
plt.fill_between(mean_fpr, tprs_lower, tprs_upper, color='grey', alpha=.2, label=r'$\pm$ 1 std. dev.')

plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")

这里写图片描述

K-S曲线与KS值

K-S曲线是正样本洛伦兹曲线与负样本洛伦兹曲线的差值曲线,用来度量阳性与阴性分类区分程度的。K-S曲线的最高点(最大值)定义为KS值,KS值越大,模型的区分度越好。
以Logistic Regression为例,说明K-S曲线的做法:
(1)把Logistic Regression模型对样本的输出概率(predict_proba)从大到小排序rankthreshold
(2)计算阈值取每个概率时对应的TPR和FPR值
(3)以(rankthresholdTPR)画正样本曲线,以(rankthresholdFPR)画负样本曲线,就构成K-S曲线
(4)K-S曲线上的KS值,即max(TPRFPR),即两条曲线间的最大间隔距离。
这里写图片描述

TPRFPR最大时,即Δ(TPRFPR)=0,也就是ROC曲线上最优阈值满足的条件ΔTPR=ΔFPR。通过,K-S曲线可以直观地找出模型中差异最大的一个分段,但K-S曲线不能反映出所有分段的效果。

2019-06-20 12:04:09 weixin_31866177 阅读数 912
  • Kubernetes 实战系列

    Kubernetes(KS8) 实战系列教程,该课程将对Kubernetes的Node、Pod、Replication Controller、Service等基本核心概念进行讲解,这些组件共同构成了Kubernetes的系统框架和计算模型。通过对它们进行灵活的组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。

    9532 人正在学习 去看看 CSDN讲师

KS检验-风控角度

分类模型评判指标 - KS曲线与KS值

从统计角度,我们知道KS是分析两组数据分布是否相同的检验指标在金融领域中,我们的y值和预测得到的违约概率刚好是两个分布未知的两个分布。好的信用风控模型一般从准确性、稳定性和可解释性来评估模型。

一般来说。好人样本的分布同坏人样本的分布应该是有很大不同的,KS正好是有效性指标中的区分能力指标:KS用于模型风险区分能力进行评估,KS指标衡量的是好坏样本累计分布之间的差值。好坏样本累计差异越大,KS指标越大,那么模型的风险区分能力越强。

横轴:阈值or数据集百分比

纵轴:TPR(真正率)与FPR(假正率)

实现:

def compute_ks(data1,data2):
    df1 = DataFrame()
    df1['pred'] = data2
    df1['label'] = data1
    # 按照样本为正样本的概率值升序排序,也即坏样本的概率从高到低排序
    sorted_list = df1.sort_values(['pred'], ascending=[True])
    # print(sorted_list)
    """
      pred     label
17  0.055966    0.0
8   0.056266    0.0
14  0.063441    0.0
15  0.066217    0.0
0   0.070942    0.0
4   0.074102    0.0
3   0.087055    0.0
2   0.090387    0.0
18  0.092003    1.0
6   0.098286    0.0
16  0.105280    0.0
10  0.107256    0.0
12  0.123415    0.0
5   0.137829    0.0
7   0.139731    0.0
1   0.159905    0.0
13  0.180385    0.0
9   0.203199    0.0
11  0.217903    0.0
    """
    total_good = sorted_list['label'].sum() # label为1的样本有多少个,真实为1的样本
    # print(sorted_list['label'])
    # print(total_good)
    total_bad = sorted_list.shape[0] - total_good # label为0的样本有多少个,真实为0的样本

    max_ks = 0.0
    good_count = 0.0
    bad_count = 0.0
    for index, row in sorted_list.iterrows(): #按照标签和每行拆开
        # print(index)
        # print('-'*5)
        # print(row)
        """
        index: 17
        row:
            pred     0.055966
            label    0.000000
        """
        if row['label'] == 0:
            bad_count += 1
        else:
            good_count += 1
        val = abs(bad_count/total_bad - good_count/total_good)
        max_ks = max(max_ks, val)
    return max_ks



def cal_auc(labels, preds):
    """
    先排序,然后统计有多少正负样本对满足:正样本预测值>负样本预测值, 再除以总的正负样本对个数
    复杂度 O(NlogN), N为样本数
    """
    n_pos = sum(labels)
    n_neg = len(labels) - n_pos
    total_pair = n_pos * n_neg

    labels_preds = zip(labels, preds)
    labels_preds = sorted(labels_preds, key=lambda x: x[1])
    accumulated_neg = 0
    satisfied_pair = 0
    for i in range(len(labels_preds)):
        if labels_preds[i][0] == 1:
            satisfied_pair += accumulated_neg
        else:
            accumulated_neg += 1

    return satisfied_pair / float(total_pair)

def approximate_auc(labels, preds, n_bins=100):
    """
    近似方法,将预测值分桶(n_bins),对正负样本分别构建直方图,再统计满足条件的正负样本对
    复杂度 O(N)
    这种方法有什么缺点?怎么分桶?

    """
    n_pos = sum(labels)
    n_neg = len(labels) - n_pos
    total_pair = n_pos * n_neg

    pos_histogram = [0 for _ in range(n_bins)]
    neg_histogram = [0 for _ in range(n_bins)]
    bin_width = 1.0 / n_bins
    for i in range(len(labels)):
        nth_bin = int(preds[i] / bin_width)
        if labels[i] == 1:
            pos_histogram[nth_bin] += 1
        else:
            neg_histogram[nth_bin] += 1

    accumulated_neg = 0
    satisfied_pair = 0
    for i in range(n_bins):
        satisfied_pair += (pos_histogram[i] * accumulated_neg + pos_histogram[i] * neg_histogram[i] * 0.5)
        accumulated_neg += neg_histogram[i]

    return satisfied_pair / float(total_pair)

掉包侠的结果好像是错的,逃不掉自己写

# official
def calc_ks(y_true, y_prob, n_bins=10):
    percentile = np.linspace(0, 100, n_bins + 1).tolist()
    bins = [np.percentile(y_prob, i) for i in percentile]
    bins[0] = bins[0] - 0.01
    bins[-1] = bins[-1] + 0.01
    binids = np.digitize(y_prob, bins) - 1
    y_1 = sum(y_true == 1)
    y_0 = sum(y_true == 0)
    bin_true = np.bincount(binids, weights=y_true, minlength=len(bins))
    bin_total = np.bincount(binids, minlength=len(bins))
    bin_false = bin_total - bin_true
    true_pdf = bin_true / y_1
    false_pdf = bin_false / y_0
    true_cdf = np.cumsum(true_pdf)
    false_cdf = np.cumsum(false_pdf)
    ks_list = np.abs(true_cdf - false_cdf).tolist()
    ks = max(ks_list)
    return ks


# 在网上看其他人实现的方案,但是感觉是错的,和我们的问题可能有出入,
# 等之后再研究吧
from scipy.stats import ks_2samp
get_ks = lambda y_pred,y_true: ks_2samp(y_pred[y_true==1], y_pred[y_true!=1]).statistic
get_ks(x,y)
# mine
ks = ks_2samp(y, y_pred)
print("ks:",ks.statistic)

首先我们有一份样本数据,包含两个指标,1.label(0,1) 2.信用分(假定是0到5)

label指标属于原始数据,有过逾期的用户为0, bad clients; 信用一直良好的为1,good clients信用分为预测指标,模型输出数据(0到5)。

作为一个常识,我们应该知道信用分的分布应该符合正态分布,也就是说接近5的人和接近0的人应该是极少极少的,大部分都在2到4之间。

信用分是0到5,那现在想知道,如果我们要贷款给用户,那把钱贷给信用分为多少的人呢?
在选择这个值的时候,我们需要考虑是希望能把钱贷给尽可能多的好人和尽可能少的坏人。如果我们选择信用分大于4的人,也许确实能过滤掉大部分坏人,但好人也被过滤掉了,用户也就少了。
这个时候我们就需要ks值了。

下面解释ks值:

f(bad) 预测为负,真实为负除以所有真实负样本数。假正例率:

  • FPRate的意义是所有真实类别为0的样本中,预测类别为1的比例。(好人为1)

f(good) 预测为负,真实为正除以所有真实正样本数。真正例率:

  • TPRate的意义是所有真实类别为1的样本中,预测类别为1的比例。(坏人为0)

这里的负指的是bad clients,也就是逾期用户。而我们的目标就是希望找到一个值,区分bad和good用户,使f(bad)尽可能大,f(good)尽可能小。

可以画出如下类似的图:

横坐标代表信用分,纵坐标代表比率。 两条曲线分别是f(bad) 和 f(good)

极端情况下,我们假设信用分小于5的都是坏人,这样所有的人都是坏人了f(bad)=1了,但f(good)=1(也就是右上角的两个点),表明模型还是很不好的,把好人也当坏人了。 而ks值在这里恰好可以找到一个信用分点,满足上述的条件:f(bad)大,f(good)小。

如图所示,在横坐标2.5处,找到了我们的ks值0.4,在这个点我们找到了70%的真实坏人,而且只把30%的好人误认为是坏人了。 ks=70% - 30%; 相对于其它点来说已经是最好的了。

所以,ks值是越大越好的,再考虑极端情况,如果有模型能找到所有的坏人(也就是f(bad)=100%),并且没有误判任何一个好人f(good)=0,那么它的ks值就=1了,属于完美模型了。 当然,对于风控模型,因为信用分几乎都符合正态分布,是不可能出现这种情况的,也只能说越大越好。

def ks_2samp(data1, data2):
    """
    Computes the Kolmogorov-Smirnov statistic on 2 samples.
    This is a two-sided test for the null hypothesis that 2 independent samples
    are drawn from the same continuous distribution.

功能:计算ks值,输出对应分割点和累计分布函数曲线图
输入值:
data: 而为数组或dataframe,包括模型得分和真实的标签
score_col:一维数组或series,代表模型得分(一般为预测正类的概率)
class_col:一维数组或series,代表真实的标签((0,1)or(-1,1))
输出值:
ks:ks值
cdf_df:好坏人累积概率分布以及其差值gap

    Parameters
    ----------
    data1, data2 : sequence of 1-D ndarrays
        two arrays of sample observations assumed to be drawn from a continuous
        distribution, sample sizes can be different
    Returns
    -------
    statistic : float
        KS statistic
    pvalue : float
        two-tailed p-value
    Notes
    -----
    This tests whether 2 samples are drawn from the same distribution. Note
    that, like in the case of the one-sample K-S test, the distribution is
    assumed to be continuous.
    This is the two-sided test, one-sided tests are not implemented.
    The test uses the two-sided asymptotic Kolmogorov-Smirnov distribution.
    If the K-S statistic is small or the p-value is high, then we cannot
    reject the hypothesis that the distributions of the two samples
    are the same.
    Examples
    --------
    >>> from scipy import stats
    >>> np.random.seed(12345678)  #fix random seed to get the same result
    >>> n1 = 200  # size of first sample
    >>> n2 = 300  # size of second sample
    For a different distribution, we can reject the null hypothesis since the
    pvalue is below 1%:
    >>> rvs1 = stats.norm.rvs(size=n1, loc=0., scale=1)
    >>> rvs2 = stats.norm.rvs(size=n2, loc=0.5, scale=1.5)
    >>> stats.ks_2samp(rvs1, rvs2)
    (0.20833333333333337, 4.6674975515806989e-005)
    For a slightly different distribution, we cannot reject the null hypothesis
    at a 10% or lower alpha since the p-value at 0.144 is higher than 10%
    >>> rvs3 = stats.norm.rvs(size=n2, loc=0.01, scale=1.0)
    >>> stats.ks_2samp(rvs1, rvs3)
    (0.10333333333333333, 0.14498781825751686)
    For an identical distribution, we cannot reject the null hypothesis since
    the p-value is high, 41%:
    >>> rvs4 = stats.norm.rvs(size=n2, loc=0.0, scale=1.0)
    >>> stats.ks_2samp(rvs1, rvs4)
    (0.07999999999999996, 0.41126949729859719)
    """
    data1 = np.sort(data1)
    data2 = np.sort(data2)
    n1 = data1.shape[0]
    n2 = data2.shape[0]
    data_all = np.concatenate([data1, data2])
    cdf1 = np.searchsorted(data1, data_all, side='right') / (1.0*n1)
    cdf2 = np.searchsorted(data2, data_all, side='right') / (1.0*n2)
    d = np.max(np.absolute(cdf1 - cdf2))
    # Note: d absolute not signed distance
    en = np.sqrt(n1 * n2 / float(n1 + n2))
    try:
        prob = distributions.kstwobign.sf((en + 0.12 + 0.11 / en) * d)
    except:
        prob = 1.0

    return Ks_2sampResult(d, prob)

在实际情况下,我们一般计算违约概率的ks值,这时是不存在NAN值的。所以以上三种方法计算ks值均可。但是当我们计算单变量的ks值时,有时数据质量不好,存在NAN值时,继续采用ks_calc_auc和ks_calc_2samp就会存在问题。

解决办法有两个 1. 提前去除数据中的NAN值 2. 直接采用ks_calc_cross计算。 


参考:

houhaichao830

4.4.2分类模型评判指标(四) - ROC,AUC,GINI,KS,Lift,Gain,MSE总结

python绘制 

auc和ks是强相关的指标

互联网金融:Vintage的应用

astype转成一样的浮点数才可以进行减法操作!!!要dtype查看,之前这里报错辽~?

2018-10-03 17:47:08 aa_JamesJones 阅读数 1491
  • Kubernetes 实战系列

    Kubernetes(KS8) 实战系列教程,该课程将对Kubernetes的Node、Pod、Replication Controller、Service等基本核心概念进行讲解,这些组件共同构成了Kubernetes的系统框架和计算模型。通过对它们进行灵活的组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。

    9532 人正在学习 去看看 CSDN讲师

1. 混淆矩阵---确定截断点后,评价学习器性能

TP(实际为正预测为正),FP(实际为负但预测为正),FN(实际为正但预测为负),TN(实际为负预测为负)

通过混淆矩阵我们可以给出各指标的值:

查全率(召回率,Recall):样本中的正例有多少被预测准确了,衡量的是查全率,预测对的正例数占真正的正例数的比率:

查全率 = TP / (TP+FN)

查准率(精准率,Precision):针对预测结果而言,预测为正的样本有多少是真正的正样本,衡量的是查准率,预测正确的正例数占预测为正例总量的比率:

查准率 = TP / (TP+FP)

准确率(Accuracy):反映分类器对整个样本的判定能力,能将正的判定为正,负的判定为负的能力,计算公式:

Accuracy=(TP+TN) / (TP+FP+FN+TN)

阴性预测值:可以理解为负样本的查准率,阴性预测值被预测准确的比例,计算公式:

NPV=正确预测到的负例数/实际负例总数=TN / (TN+FN)

如果为多分类,也可以通过混淆矩阵得到上述指标的具体值。

查准率和查全率通常是一对矛盾的度量,通常一个高,另外一个就低。通常只有在一些简单任务中,才可能使查准率和查全率都很高。两个指标都很重要,我们应该根据实际情况综合考虑这两个指标。会有一个查准率=查全率的“平衡点”(BEP),过了这个点,查全率将增加,查准率将降低。

查准率-查全率曲线,即P-R曲线

在进行比较时,若一个P-R曲线完全”包住“另一个P-R曲线--->第一个学习器效果更好,比如上图中的学习器A的性能优于学习器C。如果两个学习器的P-R曲线发生了交叉,比如A和B,这时一个合理的判据是比较P-R曲线下面积的大小。

2. F1-score---查准率和查全率的加权调和平均数

(1)当认为查准率和查全率一样重要时,权重相同时:

(2)当查准率和查全率的重要性不同时,即权重不同时:

通常,对于不同的问题,查准率和查全率的侧重不同。比如,对于商品推荐系统,为了减少对用户的干扰,查准率更重要;逃犯系统中,查全率更重要。因此,F1-score的一般形式:

1. β=1,查全率的权重=查准率的权重,就是F1

2. β>1,查全率的权重>查准率的权重

3. β<1,查全率的权重<查准率的权重

除了F1分数之外,F0.5分数和F2分数在统计学中也得到了大量应用。其中,F2分数中,查全率的权重高于查准率,而F0.5分数中,查准率的权重高于查全率。另外,F1分数又分为宏F1(macro-F1)和微F1(micro-F1)。

3. ROC曲线, AUC---评价学习器性能,检验分类器对客户进行正确排序的能力

分类器产生的结果通常是一个概率值不是直接的0/1变量,通常数值越大,代表正例的可能性越大。

根据任务的不同也会采取不同的“截断点”,大于则为正例,小于则为反例。如重视查全率,则阈值可以设置低一些;而重视查准率,阈值可以设置高一些。

如果设定了截断点或明确了任务,那么我们根据混淆矩阵就可以知道分类器的效果好坏(计算出P、R和截断点或阈值进行比较)。

在未设定截断点(任务不明确)情况下,我们如何评价一个分类模型的效果的好坏或者比较不同分类模型效果呢?

我们可以观察这个学习器利用所有可能的截断点(就是所有样本的预测结果)对样本进行分类时的效果,注意要先对所有可能的截断点进行排序,方便对比观察。

ROC曲线描绘的是不同的截断点时,并以FPR和TPR为横纵坐标轴,描述随着截断点的变小,TPR随着FPR的变化。

纵轴:TPR=正例分对的概率 = TP/(TP+FN),其实就是查全率

横轴:FPR=负例分错的概率 = FP/(FP+TN),俗称假警报率

如果是随机分类(比如投掷硬币),没有进行任何学习器,FPR=TPR,即正例分对和负例分错概率相同,预测出来的正例负例和正例负例本身的分布是一致的,所以是一条45°的直线。因此,ROC曲线越向上远离这条45°直线,说明用了这个学习器在很小的代价(负例分错为正例,横轴)下达到了相对较大的查全率(TPR)

比如, 我们采用逻辑回归分类器,其给出针对每个实例为正类的概率,那么通过设定一个阈值如0.6,概率大于等于0.6的为正类,小于0.6的为负类。对应的就可以算出一组(FPR,TPR),在平面中得到对应坐标点。理想情况下,TPR应该接近1,FPR应该接近0。随着阈值的增加,TP和FP都减小,TPR和FPR也减小,ROC点向左下移动。阈值最大时,对应坐标点为(0,0),阈值最小时,对应坐标点(1,1)。
如下面这幅图,图中实线为ROC曲线,线上每个点对应一个阈值。

作图步骤:

1. 根据学习器的预测结果(注意,是正例的概率值,非0/1变量)对样本进行排序(从大到小)----- 这就是截断点(阈值threshold)依次选取的顺序

2. 按顺序选取截断点,并计算TPR和FPR(也可以只选取n个截断点)

3. 连接所有的点(TPR,FPR)即为ROC图

判断标准:

1. 一个ROC曲线完全”包住“另一个ROC曲线--->第一个学习器效果更好

2. 两个ROC曲线相交--->利用ROC曲线下的面积(AUC,area under ROC curve,是一个数值)进行比较

AUC:ROC曲线下的面积,由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。AUC作为数值可以直观的评价分类器的好坏,值越大越好。

AUC表示,随机抽取一个正样本和一个负样本,分类器正确给出正样本的score(预测样本是正例的概率)高于负样本的概率。在所有标注样本中,正样本共T个,负样本共F个,如果随机抽一个正样本和负样本,共有T*F个pair,其中如果有s个pair的正负样本pair满足于正样本的score高于负样本(权重为1),v个pair正负样本score相同(权重为0.5),则auc就等于(s+0.5v)/(T*F)。

既然已经这么多评价标准,为什么还要使用ROC和AUC呢?因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。

4. KS曲线,KS值---学习器将正例和反例分开的能力,确定最好的“截断点”

KS曲线和ROC曲线都用到了TPR,FPR。KS曲线是把TPR和FPR都作为纵坐标,而阈值作为横坐标。

作图步骤:

1. 根据学习器的预测结果(注意,是正例的概率值,非0/1变量)对样本进行排序(从大到小)-----这就是截断点依次选取的顺序

2. 按顺序选取截断点,并计算TPR和FPR(也可以只选取n个截断点)

3. 横轴为样本的占比百分比(最大100%),纵轴分别为TPR和FPR,可以得到KS曲线

4. TPR和FPR曲线分隔最开的位置就是最好的”截断点“,最大间隔距离就是KS值,通常>0.2即可认为模型有比较好的预测准确性

KS曲线的纵轴是表示TPR和FPR的值,就是这两个值分别通过两条曲线来体现,横轴就是阈值(把0-1之间等分N份,等分点为阈值),然后在两条曲线分隔最开的地方,对应的就是最好的阈值,也是该模型最大的KS值。KS值的取值范围是[0,1] ,KS值越大,表示模型能够将正、负客户区分开的程度越大。

参考:https://blog.csdn.net/shy19890510/article/details/79501582

https://blog.csdn.net/yaoqsm/article/details/78334920

http://alexkong.net/2013/06/introduction-to-auc-and-roc/

周志华《机器学习》

没有更多推荐了,返回首页