单调最优装箱的Python实现
py-mob的Python项目详细描述
简介
作为模仿mob R包(https://CRAN.R-project.org/package=mob)的尝试,py_mob是python函数的集合,这些函数将生成单调的binning,并执行消费信贷记分卡开发中使用的WoE(证据权重)转换。在
作为logistic回归中的分段常数变换,WoE也被应用于其他用例,如消费信贷损失估计、预付款,甚至欺诈检测模型。除单调binning和WoE变换外,还计算了各自变量的信息值和KS统计量来评价变量的预测性。在
与其他用于相同目的的python包不同,py_mob包非常轻量级,底层计算由内置的python列表或numpy数组驱动。函数将返回字典列表,这些字典可以很容易地转换为其他数据结构,例如熊猫.DataFrame或者astropy.table公司. 在
bin()、binu()、binu()、binu()和binu()实现了不同的预测能力。有关详细信息,请参见https://github.com/statcompute/py_mob。在
没有消费者风险模型背景知识的人可能会想知道为什么单调的binning和随后的WoE转换是重要的。根据我的经验,以下是几个原因。它们在具有二元结果的logistic回归的其他用例中是完全可概括的。在
- 因为这是一个基于数据离散化的分段转换,所有丢失的值都将单独归入一个类别,或者单独或与具有相似坏率的邻居合并。因此,不需要对缺失值进行特殊处理。在
- 在对每个变量进行单调装箱后,由于每个bin的WoE值是从预测值到由事件和非事件分布之间的对数比率定义的响应的投影,因此预测值的任何原始值都不再重要,因此与异常值相关的问题将消失。在
- 虽然许多建模者希望使用对数或幂变换来实现预测值和响应对数概率之间的良好线性关系,这充其量是启发式的,不能保证得到良好的结果,但是WoE变换对于具有单位相关性的响应的对数概率是严格线性的。值得一提的是,一个数值变量及其严格单调函数应该收敛到相同的单调WoE变换。在
- 最后,由于WoE被定义为事件和非事件分布之间的对数比,它表示Y=0和Y=1的情况之间的分离。信息值是事件分布和非事件分布之差的加权和,是衡量预测值重要性的重要统计量。在
安装
pip3installpy_mob
核心功能
^{pr2}$
示例
import py_mob, pandas
dt = py_mob.get_data("accepts")
utl = dt["rev_util"]
bad = dt["bad"]
utl_bin = py_mob.qtl_bin(utl, bad)
### SHOW WHAT IS IN THE FINAL BINNING OUTCOME
for key in utl_bin:
print(key + ":")
for lst in utl_bin[key]:
print(lst)
#cut:
#30.0
#tbl:
#{'bin': 1, 'freq': 2962, 'miss': 0, 'bads': 467.0, 'rate': 0.1577, 'woe': -0.3198, 'iv': 0.047,
# 'rule': '$X$ <= 30.0'}
#{'bin': 2, 'freq': 2875, 'miss': 0, 'bads': 729.0, 'rate': 0.2536, 'woe': 0.2763, 'iv': 0.0406,
# 'rule': '$X$ > 30.0'}
### REPORT THE BINNING OUTCOME IN THE TABULAR FORMAT
py_mob.view_bin(utl_bin)
#| bin | freq | miss | bads | rate | woe | iv | ks | rule |
#|-------|--------|--------|--------|--------|---------|--------|-------|-----------------------------------------------|
#| 1 | 2962 | 0 | 467 | 0.1577 | -0.3198 | 0.0470 | 14.71 | $X$ <= 30.0 |
#| 2 | 2875 | 0 | 729 | 0.2536 | 0.2763 | 0.0406 | 0.00 | $X$ > 30.0 |
### SUMMARIZE THE BINNING OUTCOME
py_mob.summ_bin(utl_bin)
#{'sample size': 5837, 'bad rate': 0.2049, 'iv': 0.0876, 'ks': 14.71, 'missing': 0.0}
### APPLY THE WOE TRANSFORMATION
for x in py_mob.cal_woe(utl[:3], py_mob.iso_bin(utl, bad)):
print(x)
#{'x': 0.0, 'bin': 1, 'woe': -0.3254}
#{'x': 2.0, 'bin': 1, 'woe': -0.3254}
#{'x': 21.0, 'bin': 1, 'woe': -0.3254}
### DISCRETIZES VECTORS IN PANDAS DATAFRAME
df = pandas.DataFrame(dt)
rst = py_mob.pd_bin(df['bad'], df[['ltv', 'bureau_score', 'tot_derog']])
rst.keys()
# dict_keys(['bin_sum', 'bin_out'])
### APPLIES WOE TRANSFORMATIONS TO VECTORS IN PANDAS DATAFRAME
out = py_mob.pd_woe(df[['ltv', 'bureau_score', 'tot_derog']], rst["bin_out"])
out.head(2)
# ltv bureau_score tot_derog
# 0 0.1619 -1.2560 0.6557
# 1 0.0804 -1.1961 -0.3811
标签:
- 项目
示例
import py_mob, pandas
dt = py_mob.get_data("accepts")
utl = dt["rev_util"]
bad = dt["bad"]
utl_bin = py_mob.qtl_bin(utl, bad)
### SHOW WHAT IS IN THE FINAL BINNING OUTCOME
for key in utl_bin:
print(key + ":")
for lst in utl_bin[key]:
print(lst)
#cut:
#30.0
#tbl:
#{'bin': 1, 'freq': 2962, 'miss': 0, 'bads': 467.0, 'rate': 0.1577, 'woe': -0.3198, 'iv': 0.047,
# 'rule': '$X$ <= 30.0'}
#{'bin': 2, 'freq': 2875, 'miss': 0, 'bads': 729.0, 'rate': 0.2536, 'woe': 0.2763, 'iv': 0.0406,
# 'rule': '$X$ > 30.0'}
### REPORT THE BINNING OUTCOME IN THE TABULAR FORMAT
py_mob.view_bin(utl_bin)
#| bin | freq | miss | bads | rate | woe | iv | ks | rule |
#|-------|--------|--------|--------|--------|---------|--------|-------|-----------------------------------------------|
#| 1 | 2962 | 0 | 467 | 0.1577 | -0.3198 | 0.0470 | 14.71 | $X$ <= 30.0 |
#| 2 | 2875 | 0 | 729 | 0.2536 | 0.2763 | 0.0406 | 0.00 | $X$ > 30.0 |
### SUMMARIZE THE BINNING OUTCOME
py_mob.summ_bin(utl_bin)
#{'sample size': 5837, 'bad rate': 0.2049, 'iv': 0.0876, 'ks': 14.71, 'missing': 0.0}
### APPLY THE WOE TRANSFORMATION
for x in py_mob.cal_woe(utl[:3], py_mob.iso_bin(utl, bad)):
print(x)
#{'x': 0.0, 'bin': 1, 'woe': -0.3254}
#{'x': 2.0, 'bin': 1, 'woe': -0.3254}
#{'x': 21.0, 'bin': 1, 'woe': -0.3254}
### DISCRETIZES VECTORS IN PANDAS DATAFRAME
df = pandas.DataFrame(dt)
rst = py_mob.pd_bin(df['bad'], df[['ltv', 'bureau_score', 'tot_derog']])
rst.keys()
# dict_keys(['bin_sum', 'bin_out'])
### APPLIES WOE TRANSFORMATIONS TO VECTORS IN PANDAS DATAFRAME
out = py_mob.pd_woe(df[['ltv', 'bureau_score', 'tot_derog']], rst["bin_out"])
out.head(2)
# ltv bureau_score tot_derog
# 0 0.1619 -1.2560 0.6557
# 1 0.0804 -1.1961 -0.3811
标签:
- 项目
import py_mob, pandas
dt = py_mob.get_data("accepts")
utl = dt["rev_util"]
bad = dt["bad"]
utl_bin = py_mob.qtl_bin(utl, bad)
### SHOW WHAT IS IN THE FINAL BINNING OUTCOME
for key in utl_bin:
print(key + ":")
for lst in utl_bin[key]:
print(lst)
#cut:
#30.0
#tbl:
#{'bin': 1, 'freq': 2962, 'miss': 0, 'bads': 467.0, 'rate': 0.1577, 'woe': -0.3198, 'iv': 0.047,
# 'rule': '$X$ <= 30.0'}
#{'bin': 2, 'freq': 2875, 'miss': 0, 'bads': 729.0, 'rate': 0.2536, 'woe': 0.2763, 'iv': 0.0406,
# 'rule': '$X$ > 30.0'}
### REPORT THE BINNING OUTCOME IN THE TABULAR FORMAT
py_mob.view_bin(utl_bin)
#| bin | freq | miss | bads | rate | woe | iv | ks | rule |
#|-------|--------|--------|--------|--------|---------|--------|-------|-----------------------------------------------|
#| 1 | 2962 | 0 | 467 | 0.1577 | -0.3198 | 0.0470 | 14.71 | $X$ <= 30.0 |
#| 2 | 2875 | 0 | 729 | 0.2536 | 0.2763 | 0.0406 | 0.00 | $X$ > 30.0 |
### SUMMARIZE THE BINNING OUTCOME
py_mob.summ_bin(utl_bin)
#{'sample size': 5837, 'bad rate': 0.2049, 'iv': 0.0876, 'ks': 14.71, 'missing': 0.0}
### APPLY THE WOE TRANSFORMATION
for x in py_mob.cal_woe(utl[:3], py_mob.iso_bin(utl, bad)):
print(x)
#{'x': 0.0, 'bin': 1, 'woe': -0.3254}
#{'x': 2.0, 'bin': 1, 'woe': -0.3254}
#{'x': 21.0, 'bin': 1, 'woe': -0.3254}
### DISCRETIZES VECTORS IN PANDAS DATAFRAME
df = pandas.DataFrame(dt)
rst = py_mob.pd_bin(df['bad'], df[['ltv', 'bureau_score', 'tot_derog']])
rst.keys()
# dict_keys(['bin_sum', 'bin_out'])
### APPLIES WOE TRANSFORMATIONS TO VECTORS IN PANDAS DATAFRAME
out = py_mob.pd_woe(df[['ltv', 'bureau_score', 'tot_derog']], rst["bin_out"])
out.head(2)
# ltv bureau_score tot_derog
# 0 0.1619 -1.2560 0.6557
# 1 0.0804 -1.1961 -0.3811
标签: