使用PySpark计算AUC,KS与PSI
当特征数量或者模型数量很多的时候,使用PySpark去计算相关指标会节省很多的时间。网上关于使用PySpark计算相关指标的资料较少,这里抛砖引玉,写了三个风控常用的指标AUC,KS和PSI相关的计算方法,供参考。
AUC
AUC的相关概念网上已经有很多的很好的文章,这里不在赘述,AUC使用的到的计算公式如下:
\]
其中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)
建立的,一般定义为:
\]
即为TPR与FPR差值绝对值的最大值。
\]
KS计算方法有很多种,这里使用的是分箱法分别计算TPR与FPR,然后得到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)是风控场景常用的验证样本在各分数段的分布与建模样本分布的稳定性。在建模中,常用来筛选特征变量、评估模型稳定性。
计算公式如下:
\]
其中\(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的更多相关文章
- MATLAB画ROC曲线,及计算AUC值
根据决策值和真实标签画ROC曲线,同时计算AUC的值 步骤: 根据决策值和真实标签画ROC曲线,同时计算AUC的值: 计算算法的决策函数值deci 根据决策函数值deci对真实标签y进行降序排序,得到 ...
- python计算auc指标
1.安装scikit-learn 1.1Scikit-learn 依赖 Python (>= 2.7 or >= 3.3), NumPy (>= 1.8.2), SciPy (> ...
- pyspark计算最大值、最小值、平均值
需求:使用pyspark计算相同key的最大值.最小值.平均值 说明: 最大值和最小值好计算,直接reduceByKey后使用python内置的max.min方法 平均值计算提供两种计算方法,直接先上 ...
- Python计算AUC
AUC(Area under curve)是机器学习常用的二分类评测手段,直接含义是ROC曲线下的面积.另一种解释是:随机抽出一对样本(一个正样本,一个负样本),然后用训练得到的分类器来对这两个样本进 ...
- 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( ...
- SQL->Python->PySpark计算KS,AUC及PSI
KS,AUC 和 PSI 是风控算法中最常计算的几个指标,本文记录了多种工具计算这些指标的方法. 生成本文的测试数据: import pandas as pd import numpy as np i ...
- 模型监控指标- 混淆矩阵、ROC曲线,AUC值,KS曲线以及KS值、PSI值,Lift图,Gain图,KT值,迁移矩阵
1. 混淆矩阵 确定截断点后,评价学习器性能 假设训练之初以及预测后,一个样本是正例还是反例是已经确定的,这个时候,样本应该有两个类别值,一个是真实的0/1,一个是预测的0/1 TP(实际为正预测为正 ...
- tensorflow添加自定义的auc计算operator
tensorflow可以很方便的添加用户自定义的operator(如果不添加也可以采用sklearn的auc计算函数或者自己写一个 但是会在python执行,这里希望在graph中也就是c++端执行这 ...
- AUC计算 - 进阶操作
首先AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前 ...
- AUC计算 - 手把手步进操作
2017-07-10 14:38:24 理论参考: 评估分类器性能的度量,像混淆矩阵.ROC.AUC等 http://www.cnblogs.com/suanec/p/5941630.html ROC ...
随机推荐
- 使用ONE.Abp快速开发微服务,再也不用加班了
项目背景 公司采用项目制工作方式,因此在不同项目上可能存在多个团队开发独立的代码库,但通用的基础设施却是相同的,这可能导致每个项目都需要编写相同的代码,并重复造轮子.更严重的是,每个项目都有自己的用户 ...
- 前端自动识别CAD图纸提取信息方法总结
前言 CAD图纸自动识别和提取信息具有许多意义,包括以下几个方面: 提高工作效率:传统上,对于大量的CAD图纸,人工识别和提取信息是一项耗时且繁琐的任务.通过自动化这一过程,可以大大提高工作效率,节省 ...
- .Net Core后端架构实战【3-介入IOC控制反转】
摘要:基于.NET Core 7.0WebApi后端架构实战[2-介入IOC控制反转] 2023/04/09, ASP.NET Core 7.0, VS2022 引言 Inversion of Co ...
- 文件系统考古2:1984 - BSD Fast Filing System
今天继续与大家分享系列文章<50 years in filesystems>,由 KRISTIAN KÖHNTOPP 撰写. 我们将进入文件系统的第二个十年,即1984年,计算机由微型计算 ...
- Python获取系统当前时间并进行类型转换
# 1.使用Python获取系统当前时间print('---------下面是方法1-----------')import timeprint(time.strftime('%Y-%m-%d %H:% ...
- 尚医通day11-Java中阿里云对象存储OSS
页面预览 用户认证 用户登录成功后都要进行身份认证,认证通过后才可以预约挂号. 认证过程:用户填写基本信息(姓名.证件类型.证件号码和证件照片),提交平台审核 用户认证相关接口: (1)上传证件图片 ...
- JetBrain学信网注册(Clion)
一.打开网站 首先打开JetBrains关于学生认证的网站:https://www.jetbrains.com/shop/eform/students,可以看见以下页面: 二.人工验证 人工验证适合于 ...
- 如何在Databricks中使用Spark进行数据处理与分析
目录 <如何在Databricks中使用Spark进行数据处理与分析> 随着大数据时代的到来,数据处理与分析变得越来越重要.在数据处理与分析过程中,数据的存储.处理.分析和展示是不可或缺的 ...
- requests的基础使用
爬虫介绍 # 爬虫:又称网络蜘蛛,spider,一堆程序,从互联网中抓取数据---->数据清洗---->入库 # 爬虫需要掌握的知识 -抓取数据:发送网络请求(http),获得响应(htt ...
- 给程序员准备的“蜜糍”--SOD框架简介
注:本文是SOD框架源码仓库的首页介绍,原文地址 一.框架介绍 1,SOD框架是什么? 以前有一个著名的国产化妆品"大宝SOD密",SOD框架虽然跟它没有什么关系,但是名字的确受到 ...