python信用评分卡建模(附代码,博主录制)

 1.自变量进行筛选

IV的全称是Information Value,中文意思是信息价值,或者信息量。

我们在用逻辑回归、决策树等模型方法构建分类模型时,经常需要对自变量进行筛选。比如我们有200个候选自变量,通常情况下,不会直接把200个变量直接放到模型中去进行拟合训练,而是会用一些方法,从这200个自变量中挑选一些出来,放进模型,形成入模变量列表。那么我们怎么去挑选入模变量呢?

挑选入模变量过程是个比较复杂的过程,需要考虑的因素很多,比如:变量的预测能力,变量之间的相关性,变量的简单性(容易生成和使用),变量的强壮性(不容易被绕过),变量在业务上的可解释性(被挑战时可以解释的通)等等。但是,其中最主要和最直接的衡量标准是变量的预测能力。

“变量的预测能力”这个说法很笼统,很主观,非量化,在筛选变量的时候我们总不能说:“我觉得这个变量预测能力很强,所以他要进入模型”吧?我们需要一些具体的量化指标来衡量每自变量的预测能力,并根据这些量化指标的大小,来确定哪些变量进入模型。IV就是这样一种指标,他可以用来衡量自变量的预测能力。类似的指标还有信息增益、基尼系数等等。

补充说明对数简写

np.log(a) np.log10(a) np.log2(a) : 计算各元素的自然对数、10、2为底的对数

WOE(Weight of Evidence)

WOE的全称是“Weight of Evidence”,即证据权重。

因子数量/好客户总数,必须进行加权处理

文件夹内数据

# -*- coding: utf-8 -*-
"""
Created on Thu Jan 11 10:09:47 2018 @author: Administrator
好客户数据是第一列
坏客户数据是第二列
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt #读取文件
readFileName="frequency_compare.xlsx"
#保存文件
saveFileName="woe_iv.xlsx" #读取excel
df=pd.read_excel(readFileName)
#如果有多个sheet表格,要用sheet_name参数 #第一列字段名(好客户属性)
column1Name_good=list(df.columns)[0]
#第二列字段名(坏客户属性)
column2Name_bad=list(df.columns)[1] #第一列好客户内容和第二列坏客户内容
column_goodCustomers=df[column1Name_good]
column_badCustomers=df[column2Name_bad] #去掉NAN
num_goodCustomers=column_goodCustomers.dropna()
#统计数量
num_goodCustomers=num_goodCustomers.size #去掉NAN
num_badCustomers=column_badCustomers.dropna()
#统计数量
num_badCustomers=num_badCustomers.size #第一列频率分析
fenquency_goodCustomers=column_goodCustomers.value_counts()
#第二列频率分析
fenquency_badCustomers=column_badCustomers.value_counts() #各个元素占比
ratio_goodCustomers=fenquency_goodCustomers/num_goodCustomers ratio_badCustomers=fenquency_badCustomers/num_badCustomers #最终好坏比例
ratio_goodDevideBad=ratio_goodCustomers/ratio_badCustomers #woe函数,阵列计算
def Woe(ratio_goodDevideBad):
woe=np.log(ratio_goodDevideBad)
return woe #iv函数,阵列计算
def Iv(woe):
iv=(ratio_goodCustomers-ratio_badCustomers)*woe
return iv #iv参数评估,参数iv_sum(变量iv总值)
def Iv_estimate(iv_sum):
#评估能力较强
if 0.5>iv_sum>0.3:
print("good informative")
return "A"
#评估能力一般
if 0.3>iv_sum>0.1:
print("medium informative")
return "B"
#评估能力强或可疑
if iv_sum>0.5:
print("good informative or suspicious")
return "C" #详细参数输出
def Print():
print("iv_sum",iv_sum)
#print("",)
#print("",) woe=Woe(ratio_goodDevideBad)
iv=Iv(woe) df_write=pd.DataFrame({"woe":woe,"iv":iv}) #ratio_badDevideGood数据写入到result_compare_badDevideGood.xlsx文件
df_write.to_excel(saveFileName, sheet_name='Sheet1') #计算iv总和,评估整体变量
iv_sum=sum([i for i in iv if np.isnan(i)!=True])
#iv参数评估,参数iv_sum(变量iv总值)
iv_estimate=Iv_estimate(iv_sum) Print()

  

结果:

预测有价值变量准确,但不完整,因为没有进行分箱,造成损失

举例说明

例如按年龄分组,一般进行分箱,我们都喜欢按照少年、青年、中年、老年几大类进行分组,但效果真的不一定好:

woe的第三方包(pip install woe; pip install reportgen)

https://pypi.org/project/woe/

实例:

https://blog.csdn.net/KIDxu/article/details/88647080

官方给的例子不是很好理解,以下是我写的一个使用示例。以此例来说明各主要函数的使用方法。计算woe的各相关函数主要在feature_process.py中定义。

import woe.feature_process as fp
import woe.eval as eval #%% woe分箱, iv and transform
data_woe = data #用于存储所有数据的woe值
civ_list = []
n_positive = sum(data['target'])
n_negtive = len(data) - n_positive
for column in list(data.columns[1:]):
if data[column].dtypes == 'object':
civ = fp.proc_woe_discrete(data, column, n_positive, n_negtive, 0.05*len(data), alpha=0.05)
else:
civ = fp.proc_woe_continuous(data, column, n_positive, n_negtive, 0.05*len(data), alpha=0.05)
civ_list.append(civ)
data_woe[column] = fp.woe_trans(data[column], civ) civ_df = eval.eval_feature_detail(civ_list,'output_feature_detail_0315.csv')
#删除iv值过小的变量
iv_thre = 0.001
iv = civ_df[['var_name','iv']].drop_duplicates()
x_columns = iv.var_name[iv.iv > iv_thre]

  

计算分箱,woe,iv

核心函数主要是freature_process.proc_woe_discrete()与freature_process.proc_woe_continuous(),分别用于计算连续变量与离散变量的woe。它们的输入形式相同:

proc_woe_discrete(df,var,global_bt,global_gt,min_sample,alpha=0.01)

proc_woe_continuous(df,var,global_bt,global_gt,min_sample,alpha=0.01)

输入:

df: DataFrame,要计算woe的数据,必须包含'target'变量,且变量取值为{0,1}

var:要计算woe的变量名

global_bt:全局变量bad total。df的正样本数量

global_gt:全局变量good total。df的负样本数量

min_sample:指定每个bin中最小样本量,一般设为样本总量的5%。

alpha:用于自动计算分箱时的一个标准,默认0.01.如果iv_划分>iv_不划分*(1+alpha)则划分。

输出:一个自定义的InfoValue类的object,包含了分箱的一切结果信息。

该类定义见以下一段代码。

class InfoValue(object):
'''
InfoValue Class
'''
def __init__(self):
self.var_name = []
self.split_list = []
self.iv = 0
self.woe_list = []
self.iv_list = []
self.is_discrete = 0
self.sub_total_sample_num = []
self.positive_sample_num = []
self.negative_sample_num = []
self.sub_total_num_percentage = []
self.positive_rate_in_sub_total = []
self.negative_rate_in_sub_total = [] def init(self,civ):
self.var_name = civ.var_name
self.split_list = civ.split_list
self.iv = civ.iv
self.woe_list = civ.woe_list
self.iv_list = civ.iv_list
self.is_discrete = civ.is_discrete
self.sub_total_sample_num = civ.sub_total_sample_num
self.positive_sample_num = civ.positive_sample_num
self.negative_sample_num = civ.negative_sample_num
self.sub_total_num_percentage = civ.sub_total_num_percentage
self.positive_rate_in_sub_total = civ.positive_rate_in_sub_total
self.negative_rate_in_sub_total = civ.negative_rate_in_sub_total

打印分箱结果

eval.eval_feature_detail(Info_Value_list,out_path=False)

输入:

Info_Value_list:存储各变量分箱结果(proc_woe_continuous/discrete的返回值)的List.

out_path:指定的分箱结果存储路径,输出为csv文件

输出:

各变量分箱结果的DataFrame。各列分别包含如下信息:

var_name 变量名
split_list 划分区间
sub_total_sample_num 该区间总样本数
positive_sample_num 该区间正样本数
negative_sample_num 该区间负样本数
sub_total_num_percentage 该区间总占比
positive_rate_in_sub_total 该区间正样本占总正样本比例
woe_list woe
iv_list 该区间iv
iv
该变量iv(各区间iv之和)
输出结果一个示例(截取部分):

woe转换

得到分箱及woe,iv结果后,对原数据进行woe转换,主要用以下函数

woe_trans(dvar,civ): replace the var value with the given woe value

输入:

dvar: 要转换的变量,Series

civ: proc_woe_discrete或proc_woe_discrete输出的分箱woe结果,自定义的InfoValue类

输出:

var: woe转换后的变量,Series

分箱原理

该包中对变量进行分箱的原理类似于二叉决策树,只是决定如何划分的目标函数是iv值。

1)连续变量分箱

首先简要描述分箱主要思想:

-------------------------------------------------------

1.初始化数据集D =D0为全量数据。转步骤2

2.对于D,将数据按从小到大排序并按数量等分为10份,记录各划分点。计算不进行仍何划分时的iv0,转步骤3.

3.遍历各划分点,计算利用各点进行二分时的iv。

如果最大iv>iv0*(1+alpha)(用户给定,默认0.01): 则进行划分,且最大iv对应的即确定为此次划分点。它将D划分为左右两个结点,数据集分别为DL, DR.转步骤4.

否则:停止。

4.分别令D=DL,D=DR,重复步骤2.

-------------------------------------------------------

为了便于理解,上面简化了一些条件。实际划分时还设计到一些限制条件,如不满足会进行区间合并。

主要限制条件有以下2个:

a.每个bin的数量占比>min_sample(用户给定)

b.每个bin的target取值个数>1,即每个bin必须同时包含正负样本。

2)连续变量分箱

对于离散变量分箱后续补充 to be continued...

--------------------------

python风控建模实战lendingClub(博主录制,catboost,lightgbm建模,2K超清分辨率)

https://study.163.com/course/courseMain.htm?courseId=1005988013&share=2&shareId=400000000398149

扫描和关注博主二维码,学习免费python视频教学资源

woe_iv原理和python代码建模的更多相关文章

  1. 单链表反转的原理和python代码实现

    链表是一种基础的数据结构,也是算法学习的重中之重.其中单链表反转是一个经常会被考察到的知识点. 单链表反转是将一个给定顺序的单链表通过算法转为逆序排列,尽管听起来很简单,但要通过算法实现也并不是非常容 ...

  2. 线性插值法的原理和python代码实现

    假设我们已知坐标 (x0, y0) 与 (x1, y1),要得到 [x0, x1] 区间内某一位置 x 在直线上的值.根据图中所示,我们得到 由于 x 值已知,所以可以从公式得到 y 的值 已知 y  ...

  3. k-means原理和python代码实现

    k-means:是无监督的分类算法 k代表要分的类数,即要将数据聚为k类; means是均值,代表着聚类中心的迭代策略. k-means算法思想: (1)随机选取k个聚类中心(一般在样本集中选取,也可 ...

  4. 机器学习之感知器算法原理和Python实现

    (1)感知器模型 感知器模型包含多个输入节点:X0-Xn,权重矩阵W0-Wn(其中X0和W0代表的偏置因子,一般X0=1,图中X0处应该是Xn)一个输出节点O,激活函数是sign函数. (2)感知器学 ...

  5. 对数损失函数(Logarithmic Loss Function)的原理和 Python 实现

    原理 对数损失, 即对数似然损失(Log-likelihood Loss), 也称逻辑斯谛回归损失(Logistic Loss)或交叉熵损失(cross-entropy Loss), 是在概率估计上定 ...

  6. 常见素数筛选方法原理和Python实现

    1. 普通筛选(常用于求解单个素数问题) 自然数中,除了1和它本身以外不再有其他因数. import math def func_get_prime(n): func = lambda x: not ...

  7. 【集成学习】:Stacking原理以及Python代码实现

    Stacking集成学习在各类机器学习竞赛当中得到了广泛的应用,尤其是在结构化的机器学习竞赛当中表现非常好.今天我们就来介绍下stacking这个在机器学习模型融合当中的大杀器的原理.并在博文的后面附 ...

  8. iOS开发UI篇—程序启动原理和UIApplication

    iOS开发UI篇—程序启动原理和UIApplication   一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就 ...

  9. 一个 11 行 Python 代码实现的神经网络

    一个 11 行 Python 代码实现的神经网络 2015/12/02 · 实践项目 · 15 评论· 神经网络 分享到:18 本文由 伯乐在线 - 耶鲁怕冷 翻译,Namco 校稿.未经许可,禁止转 ...

随机推荐

  1. 关于LeetCode上链表题目的一些trick

    最近在刷leetcode上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...

  2. Linux下载_Linux系统各种版本ISO镜像下载(redhat,centos,oracle,ubuntu,openSUSE)

    以下是风哥收集的Linux系统各种版本ISO镜像下载,包括redhat,centos,oracle,ubuntu等linux操作系统. Linux下载1:红帽RedHat Linux(RHEL5.RH ...

  3. 20181219-PostgreSQL 流复制监控脚本

    PostgreSQL 流复制监控脚本 https://github.com/AndyYHM/Writing/blob/PostgreSQL/20181219-PostgreSQL%20Stream%2 ...

  4. 内存与IO的交换【转】

    用户进程的内存页分为两种: file-backed pages(文件背景页) anonymous pages(匿名页) 比如进程的代码段.映射的文件都是file-backed,而进程的堆.栈都是不与文 ...

  5. git在开发中的一些使用

    git 获取远程分支: 步骤如下: 首先:git fetch --all 其次:git checkout 分支名 例如:git checkout pmt-45424-TOUCHWEB 这样就可以获取到 ...

  6. IBM developer:Kafka ACLs

    Overview In Apache Kafka, the security feature is supported from version 0.9. When Kerberos is enabl ...

  7. 简介---linux内核态和用户态

    内核态:进程运行在内核空间:管理系统的所有资源,比如读写磁盘文件,分配回收内存,从网络接口读写数据等等 用户态:进程运行在用户空间.比如一些应用程序 内核如何调用硬件资源的:内核空间中的代码控制了硬件 ...

  8. MySQL慢查询&执行计划

    参考文章: https://blog.csdn.net/tiantianw/article/details/53334566 http://www.cnblogs.com/luyucheng/p/62 ...

  9. 身边有个漂亮的java女程序员是什么体验?

    程序员都是一些追求完美的人.女程序员细致认真,不仅能写代码而且注释详尽清晰.能做好单元测试BUG最少.能写标准规范的设计文件不会对不上模块编号也不会少了类或接口说明,提交代码不会忘记写LOG,不会和测 ...

  10. 基于Python玩转人工智能最火框架 TensorFlow应用实践

    慕K网-299元-基于Python玩转人工智能最火框架 TensorFlow应用实践 需要联系我,QQ:1844912514