当特征数量或者模型数量很多的时候,使用PySpark去计算相关指标会节省很多的时间。网上关于使用PySpark计算相关指标的资料较少,这里抛砖引玉,写了三个风控常用的指标AUC,KS和PSI相关的计算方法,供参考。

AUC

AUC的相关概念网上已经有很多的很好的文章,这里不在赘述,AUC使用的到的计算公式如下:

\[AUC=\frac{\sum_{i\in positiveClass}rank_i-{\displaystyle\frac{M(1+M)}2}}{M\times N}
\]

其中M为负类样本的数目,N为正类样本的数目

使用PySpark计算代码如下:

from pyspark.sql import functions as F
from pyspark.sql.window import Window true_y_col = 'y'
pred_y_col = 'pred_y'
date_col = 'day' auc_df = df.filter(F.col(true_y_col)>=0).filter(F.col(pred_y_col)>=0)\
.select(true_y_col, pred_y_col, date_col, 'model_name')\
.withColumn('totalbad', F.sum(F.col(true_y_col)).over(Window.patitonBy(date_col, 'model_name').orderBy(F.lit(1))))\
.withColumn('totalgood', F.sum(1-F.col(true_y_col)).over(Window.patitonBy(date_col, 'model_name').orderBy(F.lit(1))))\
.withColumn('rnk2', F.row_number().over(Window.partitionBy(date_col, 'model_name').orderBy(F.col(pred_y_col).asc())))\
.filter(F.col(true_y_col)==1)\
.groupBy(date_col, 'model_name')\
.agg(((F.sum(F.col('rnk2'))-0.5*(F.max(F.col('totalbad')))*(1+F.max(F.col('totalbad'))))/(F.max(F.col('totalbad'))*F.max(F.col('totalgood')))).alias('AUC'))\
.orderBy('model_name', date_col)

KS

KS统计量是基于经验累积分布函数(Empirical Cumulative Distribution Function,ECDF)

建立的,一般定义为:

\[KS=\max\left\{\left|cum\left(bad\_rate\right)-cum\left(good\_rate\right)\right|\right\}
\]

即为TPRFPR差值绝对值的最大值。

\[KS=max\left(\left|TPR-FPR\right|\right)
\]

KS计算方法有很多种,这里使用的是分箱法分别计算TPRFPR,然后得到KS。

使用PySpark计算代码如下:

from pyspark.sql import functions as F
from pyspark.sql.window import Window true_y_col = 'y'
pred_y_col = 'pred_y'
date_col = 'day'
nBins = 10 ks_df = df.filter(F.col(true_y_col)>=0).filter(F.col(pred_y_col)>=0)\
.select(true_y_col, pred_y_col, date_col, 'model_name')\
.withColumn('Bin', F.ntile(nBins).over(Window.partitionBy(date_col, 'model_name').orderBy(pred_y_col)))\
.groupBy(date_col, 'model_name', 'Bin').agg(F.sum(true_y_col).alias('N_1'), F.sum(1-F.col(true_y_col)).alias('N-0'))\
.withColumn('ALL_1', F.sum('N_1').over(Window.partitionBy(date_col, 'model_name')))\
.withColumn('ALL_0', F.sum('N_0').over(Window.partitionBy(date_col, 'model_name')))\
.withColumn('SUM_1', F.sum('N_1').over(Window.partitionBy(date_col, 'model_name').orderBy('Bin')))\
.withColumn('ALL_0', F.sum('N_0').over(Window.partitionBy(date_col, 'model_name').orderBy('Bin')))\
.withColumn('KSn', F.expr('round(abs(SUM_1/ALL_1-SUM_0/ALL_0),6)'))\
.withColumn('KS', F.round(F.max('KSn').over(Window.partitionBy(date_col, 'model_name')),6)) ks_df = ks_df.select(date_col, 'model_name', 'KS').filter(col('KS').isNotNull()).dropDuplicates()

PSI

群体稳定性指标(Population Stability Index,PSI)是风控场景常用的验证样本在各分数段的分布与建模样本分布的稳定性。在建模中,常用来筛选特征变量、评估模型稳定性

计算公式如下:

\[psi=\sum_{i=1}^n\left(A_i-E_i\right)\ast\ln\left(A_i/E_i\right)
\]

其中\(A_i\)代表的是第i个分箱中实际分布(actual)样本占比,同理\(E_i\)代表的是第i个分箱中预期分布(excepted)样本占比

使用PySpark计算代码如下:

from pyspark.sql import functions as F
from pyspark.sql.window import Window
from pyspark.sql.functions import when date_col = 'day'
nBins = 10
feature_list = ['fea_1', 'fea_2', 'fea_3'] df = df.withColumn('flag', when(F.col(date_col) == 'actual_date'), 0).when(F.col(date_col) == 'excepted_date').otherwise(None) quantitles = df.filter(F.col('flag') == 0)\
.approxQuantile(feature_list, [i/nBins for i in range(1, nBins)], 0.001) # 基准样本分箱 quantitles_dict = {col: quantitles[idx] for idx, col in enumerate(feature_list)}
f_quantitles_dict = F.create_map([F.lit(x) if isinstance(x, str) else F.array(*[F.lit(xx) for xx in x]) for i in quantitles_dict.items() for x in i]) unpivotExpr = "stack(3, 'fea_1', fea_1, 'fea_2', fea_2, 'fea_3', fea_3)" psi_df = df.filter(F.col('flag').isNotNull()).select('flag', F.expr(unpivotExpr))\
.withColumn('Bin', when(F.col('value').isNull(), 'Missing').otherwise(
when(F.col('value') < f_quantitles_dict[F.col('varname')][0], 'bin_0')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][1], 'bin_1')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][2], 'bin_2')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][3], 'bin_3')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][4], 'bin_4')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][5], 'bin_5')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][6], 'bin_6')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][7], 'bin_7')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][8], 'bin_8')
.when(F.col('value') < f_quantitles_dict[F.col('varname')][8], 'bin_9')))\
.groupBy('varname', 'Bin').agg(F.sum('flag').alias('N_1'), F.sum(1-F.col('flag')).alias('N_0'))\
.withColumn('ALL_1', F.sum('N_1').over(Window.partitionBy('varname')))\
.withColumn('ALL_0', F.sum('N_0').over(Window.partitionBy('varname')))\
.withColumn('actual', F.expr('round(N_0/ALL_0, 6)'))\
.withColumn('excepted', F.expr('round(N_1/ALL_1, 6)'))\
.withColumn('PSIn', F.expr('round((actual-excepted)*ln(actual/excepted), 6'))\
.withColumn('PSI', F.round(F.sum('PSIn').over(Window.partitionBy('varname')), 6))

Reference

使用PySpark计算AUC,KS与PSI的更多相关文章

  1. MATLAB画ROC曲线,及计算AUC值

    根据决策值和真实标签画ROC曲线,同时计算AUC的值 步骤: 根据决策值和真实标签画ROC曲线,同时计算AUC的值: 计算算法的决策函数值deci 根据决策函数值deci对真实标签y进行降序排序,得到 ...

  2. python计算auc指标

    1.安装scikit-learn 1.1Scikit-learn 依赖 Python (>= 2.7 or >= 3.3), NumPy (>= 1.8.2), SciPy (> ...

  3. pyspark计算最大值、最小值、平均值

    需求:使用pyspark计算相同key的最大值.最小值.平均值 说明: 最大值和最小值好计算,直接reduceByKey后使用python内置的max.min方法 平均值计算提供两种计算方法,直接先上 ...

  4. Python计算AUC

    AUC(Area under curve)是机器学习常用的二分类评测手段,直接含义是ROC曲线下的面积.另一种解释是:随机抽出一对样本(一个正样本,一个负样本),然后用训练得到的分类器来对这两个样本进 ...

  5. matlab 矢量化编程(一)—— 计算 AUC

    AUC = sum( (Y(2:end)+Y(1:end-1))/2 .* (X(2:end) - X(1:end-1)) X 和 Y 均是向量: Y(2:end) - Y(1:end-1),是 Y( ...

  6. SQL->Python->PySpark计算KS,AUC及PSI

    KS,AUC 和 PSI 是风控算法中最常计算的几个指标,本文记录了多种工具计算这些指标的方法. 生成本文的测试数据: import pandas as pd import numpy as np i ...

  7. 模型监控指标- 混淆矩阵、ROC曲线,AUC值,KS曲线以及KS值、PSI值,Lift图,Gain图,KT值,迁移矩阵

    1. 混淆矩阵 确定截断点后,评价学习器性能 假设训练之初以及预测后,一个样本是正例还是反例是已经确定的,这个时候,样本应该有两个类别值,一个是真实的0/1,一个是预测的0/1 TP(实际为正预测为正 ...

  8. tensorflow添加自定义的auc计算operator

    tensorflow可以很方便的添加用户自定义的operator(如果不添加也可以采用sklearn的auc计算函数或者自己写一个 但是会在python执行,这里希望在graph中也就是c++端执行这 ...

  9. AUC计算 - 进阶操作

    首先AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前 ...

  10. AUC计算 - 手把手步进操作

    2017-07-10 14:38:24 理论参考: 评估分类器性能的度量,像混淆矩阵.ROC.AUC等 http://www.cnblogs.com/suanec/p/5941630.html ROC ...

随机推荐

  1. 2022-03-22:二进制取反。 有一个二进制字符串,可以选择该串中的任意一段区间进行取反(可以进行一次或不进行),取反指将0变为1,将1变为0。那么取反之后的num可能的最大的字典序是多少呢。如有

    2022-03-22:二进制取反. 有一个二进制字符串,可以选择该串中的任意一段区间进行取反(可以进行一次或不进行),取反指将0变为1,将1变为0.那么取反之后的num可能的最大的字典序是多少呢.如有 ...

  2. 2021-09-04:加油站。在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost

    2021-09-04:加油站.在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升.你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost ...

  3. LC19. 删除链表的倒数第 N 个结点

    删除链表的倒数第N个结点(中等) Q:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 示例: 示例一:输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3, ...

  4. Windows服务程序管理器 - 开源研究系列文章

    这些天弄了一个Windows服务程序管理器,主要是对需要的Windows服务程序进行管理.这个也能够将自己开发的服务程序注册到操作系统里去运行. 1.        项目目录: 目录见下图,对代码进行 ...

  5. 在程序里如何停止整个python项目的运行

    我们的项目无可避免的会遇到一些场景,当出现某个故障或者异常,必须停止整个项目的运行,这时只需要在抛出的异常里执行以下即可: os._exit(0)

  6. linux DHCP

    目录 一.DHCP概念 二.DHCP工作过程 三.DHCP实验 一.DHCP概念 概念:动态主机配置协议,自动为计算机分配tcp/ip参数 DHCP的优点:1.减少管理员的工作难度 2.避免错误的可能 ...

  7. 渗透测试-struts2攻防环境搭建拿shell

    一.下载Jspstudy 打开目录D:\JspStudy\tomcat\webapps 二.打开struts2并进行拿shell 1.打开struts2 在浏览器中输入网址http://localho ...

  8. 大型 3D 互动开发和优化实践

    开发背景 得益于"元宇宙"概念在前段时间的爆火,各家公司都推出了使用 3D 场景的活动或频道. 3D 场景相比传统的 2D 页面优点是多一个维度,同屏展示的内容可以更多,能完整的展 ...

  9. 【技术积累】Java中的泛型【一】

    泛型是什么 Java中的泛型是一种能够让用户在编写代码时避免使用明确的类型而进行类型参数化的机制.Java中的泛型可以让编程者在代码编写时不必关心具体类型,只用关心类型之间的关系和相互转换,从而在编写 ...

  10. 【技术积累】Linux中的基础知识【一】

    Linux系统是什么 Linux系统是一种开源操作系统,它极具可定制性和灵活性,因此受到了许多人的欢迎.Linux系统以简单,强大和兼容性而著称.它可用于各种设备,从个人计算机到超级计算机,从移动设备 ...