分享

KS曲线

 脑系科数据科学 2021-12-26

1.案例实战 - 股票客户流失预警模型

In [2]:

# 1.读取数据import pandas as pddf = pd.read_excel('股票客户流失.xlsx')# 2.划分特征变量和目标变量X = df.drop(columns='是否流失') y = df['是否流失']# 3.划分训练集和测试集from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)# 4.模型搭建from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression()model.fit(X_train, y_train)# 5.模型使用1 - 预测数据结果y_pred = model.predict(X_test)print(y_pred[0:100])  # 打印预测内容的前100个看看# 查看全部的预测准确度from sklearn.metrics import accuracy_scorescore = accuracy_score(y_pred, y_test)print(score)  # 打印整体的预测准确度# 6.模型使用2 - 预测概率y_pred_proba = model.predict_proba(X_test)  print(y_pred_proba[0:5])  # 打印前5个客户的分类概率
[0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0
 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1]
0.7977288857345636
[[0.82041491 0.17958509]
 [0.84029613 0.15970387]
 [0.79819342 0.20180658]
 [0.62989192 0.37010808]
 [0.61636611 0.38363389]]

4.3 模型评估方法 - ROC曲线与KS曲线

4.3.1 分类模型的评估方法 - ROC曲线

补充知识点:混淆矩阵的Python实现

In [3]:

from sklearn.metrics import confusion_matrixm = confusion_matrix(y_test, y_pred)  # 传入预测值和真实值print(m)
[[968  93]
 [192 156]]

In [4]:

a = pd.DataFrame(m, index=['0(实际不流失)', '1(实际流失)'], columns=['0(预测不流失)', '1(预测流失)'])a

Out[4]:


0(预测不流失)1(预测流失)
0(实际不流失)96893
1(实际流失)192156

In [5]:

from sklearn.metrics import classification_reportprint(classification_report(y_test, y_pred))  # 传入预测值和真实值
              precision    recall  f1-score   support

           0       0.83      0.91      0.87      1061
           1       0.63      0.45      0.52       348

    accuracy                           0.80      1409
   macro avg       0.73      0.68      0.70      1409
weighted avg       0.78      0.80      0.79      1409

4.3.2 案例实战 - 评估股票客户流失预警模型

In [6]:

y_pred_proba[:,1]

Out[6]:

array([0.17958509, 0.15970387, 0.20180658, ..., 0.04220544, 0.09782449,
       0.63586739])

下图这个表也被称为混淆矩阵
继续以上述案例为例,7000个客户中实际有2000个客户流失,假设模型预测所有客户都不会流失,那么模型的假警报率(FPR)为0,即没有误伤一个未流失客户,但是此时模型的命中率(TPR)也为0,即没有揪出一个流失客户,见下表。

一个优秀的客户流失预警模型,命中率(TPR)应尽可能高,即能尽量揪出潜在流失客户,同时假警报率(FPR)应尽可能低,即不要把未流失客户误判为流失客户。然而这两者往往成正相关,因为如果调高阈值,例如认为流失概率超过90%才认定为流失,那么会导致假警报率很低,但是命中率也很低;而如果调低阈值,例如认为流失概率超过10%就认定为流失,那么命中率就会很高,但是假警报率也会很高。因此,为了衡量一个模型的优劣,数据科学家根据不同阈值下的命中率和假警报率绘制了ROC曲线,如下图所示,其中横坐标为假警报率(FPR),纵坐标为命中率(TPR)。

在不同阈值条件下,都希望命中率尽可能高,假警报率尽可能低。举例来说,某一检测样本总量为100,其中流失客户为20人,未流失客户为80人。当阈值为20%时,也就是说当流失概率超过20%就认为客户会流失时,模型A和模型B预测出来的流失客户都是15人。如果模型A预测流失的15人中有10人的确流失,有5人属于误判,那么命中率为10/20=50%,此时假警报率为5/80=6.25%;如果模型B预测流失的15人中只有5人的确流失,有10人属于误判,那么其命中率为5/20=25%,假警报率为10/80=12.5%。此时模型A的命中率是模型B的2倍,假警报率是模型B的一半,因此可以认为模型A是一个较优的模型。如果把假警报率理解为代价的话,那么命中率就是收益,所以也可以说在阈值相同的情况下,希望假警报率(代价)尽可能小,命中率(收益)尽可能高,该思想反映在图形上就是ROC曲线尽可能地陡峭。曲线越靠近左上角,说明在相同的阈值条件下,命中率越高,假警报率越低,模型越完善。换一个角度来理解,一个完美的模型是在不同的阈值条件下,假警报率都接近于0,而命中率都接近于1,该特征反映在图形上就是ROC曲线非常接近(0,1)这个点,即曲线非常陡峭

In [7]:

# 1.计算ROC曲线需要的假警报率false positive result(fpr)、命中率true positive result(tpr)及阈值threshold(thres)from sklearn.metrics import roc_curvefpr, tpr, thres = roc_curve(y_test, y_pred_proba[:,1])

In [8]:

# # 感兴趣的读者可以查看下roc_curve()函数返回的内容# print(roc_curve(y_test, y_pred_proba[:,1]))# type(roc_curve(y_test, y_pred_proba[:,1]))# len(roc_curve(y_test, y_pred_proba[:,1]))

In [9]:

# 2.查看假警报率(fpr)、命中率(tpr)及阈值(thres)a = pd.DataFrame()  # 创建一个空DataFrame a['阈值'] = list(thres)a['假警报率'] = list(fpr)a['命中率'] = list(tpr)a.head()

Out[9]:


阈值假警报率命中率
01.9303690.0000000.000000
10.9303690.0000000.002874
20.8673420.0000000.034483
30.8641870.0018850.034483
40.8573030.0018850.040230

In [13]:

# 3.绘制ROC曲线import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文plt.plot(fpr, tpr)  # 通过plot()函数绘制折线图plt.title('ROC曲线')  # 添加标题,注意如果要写中文,需要在之前添加一行代码:plt.rcParams['font.sans-serif'] = ['SimHei']plt.xlabel('FPR')  # 添加X轴标签plt.ylabel('TPR')  # 添加Y轴标plt.show()

在数值上可以使用AUC值来衡量模型的好坏。AUC值(Area Under Curve)指ROC曲线下方的面积,该面积的取值范围通常为0.5~1,0.5表示随机判断,1则代表完美的模型。

In [11]:

# 4.求出模型的AUC值from sklearn.metrics import roc_auc_scorescore = roc_auc_score(y_test, y_pred_proba[:,1])score

Out[11]:

0.8103854528908967

补充知识点:对阈值取值的理解

In [11]:

max(y_pred_proba[:,1])

Out[11]:

0.9303686064600186

In [12]:

a = pd.DataFrame(y_pred_proba, columns=['分类为0概率', '分类为1概率'])a = a.sort_values('分类为1概率', ascending=False)a.head(15)

Out[12]:


分类为0概率分类为1概率
3260.0696310.930369
3660.0853730.914627
6620.0929230.907077
11540.1051180.894882
10360.1059060.894094
10930.1113030.888697
11640.1155500.884450
8910.1165940.883406
4370.1230600.876940
11530.1272930.872707
7490.1296330.870367
490.1326580.867342
6810.1334100.866590
13270.1358130.864187
2640.1365990.863401

补充知识点:KS曲线绘制

KS曲线将阈值作为横坐标,将命中率(TPR)与假警报率(FPR)之差作为纵坐标

与ROC曲线对应的是AUC值,而与KS曲线对应的则是KS值。KS值的计算公式如下。KS=max(TPR-FPR)

In [14]:

from sklearn.metrics import roc_curvefpr, tpr, thres = roc_curve(y_test, y_pred_proba[:,1])

In [15]:

a = pd.DataFrame()  # 创建一个空DataFrame a['阈值'] = list(thres)a['假警报率'] = list(fpr)a['命中率'] = list(tpr)a.head()

Out[15]:


阈值假警报率命中率
01.9303690.0000000.000000
10.9303690.0000000.002874
20.8673420.0000000.034483
30.8641870.0018850.034483
40.8573030.0018850.040230

In [16]:

plt.plot(thres[1:], tpr[1:])plt.plot(thres[1:], fpr[1:])plt.plot(thres[1:], tpr[1:] - fpr[1:])plt.xlabel('threshold')plt.legend(['tpr', 'fpr', 'tpr-fpr'])plt.gca().invert_xaxis() plt.show()

In [17]:

max(tpr - fpr)

Out[17]:

0.4744656418256471

In [18]:

# KS值对应的阈值a['TPR-FPR'] = a['命中率'] - a['假警报率']a.head()

Out[18]:


阈值假警报率命中率TPR-FPR
01.9303690.0000000.0000000.000000
10.9303690.0000000.0028740.002874
20.8673420.0000000.0344830.034483
30.8641870.0018850.0344830.032598
40.8573030.0018850.0402300.038345

In [19]:

# 另外一种获取KS值的方式max(a['TPR-FPR'])

Out[19]:

0.4744656418256471

In [20]:

# 获取KS值对应的阈值等信息a[a['TPR-FPR'] == max(a['TPR-FPR'])]

Out[20]:


阈值假警报率命中率TPR-FPR
2240.277690.2554190.7298850.474466

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多