python实现连续变量最优分箱详解--CART算法
作者:贾杰森 发布时间:2023-01-15 16:33:05
关于变量分箱主要分为两大类:有监督型和无监督型
对应的分箱方法:
A. 无监督:(1) 等宽 (2) 等频 (3) 聚类
B. 有监督:(1) 卡方分箱法(ChiMerge) (2) ID3、C4.5、CART等单变量决策树算法 (3) 信用评分建模的IV最大化分箱 等
本篇使用python,基于CART算法对连续变量进行最优分箱
由于CART是决策树分类算法,所以相当于是单变量决策树分类。
简单介绍下理论:
CART是二叉树,每次仅进行二元分类,对于连续性变量,方法是依次计算相邻两元素值的中位数,将数据集一分为二,计算该点作为切割点时的基尼值较分割前的基尼值下降程度,每次切分时,选择基尼下降程度最大的点为最优切分点,再将切分后的数据集按同样原则切分,直至终止条件为止。
关于CART分类的终止条件:视实际情况而定,我的案例设置为 a.每个叶子节点的样本量>=总样本量的5% b.内部节点再划分所需的最小样本数>=总样本量的10%
python代码实现:
import pandas as pd
import numpy as np
#读取数据集,至少包含变量和target两列
sample_set = pd.read_excel('/数据样本.xlsx')
def calc_score_median(sample_set, var):
'''
计算相邻评分的中位数,以便进行决策树二元切分
param sample_set: 待切分样本
param var: 分割变量名称
'''
var_list = list(np.unique(sample_set[var]))
var_median_list = []
for i in range(len(var_list) -1):
var_median = (var_list[i] + var_list[i+1]) / 2
var_median_list.append(var_median)
return var_median_list
var表示需要进行分箱的变量名,返回一个样本变量中位数的list
def choose_best_split(sample_set, var, min_sample):
'''
使用CART分类决策树选择最好的样本切分点
返回切分点
param sample_set: 待切分样本
param var: 分割变量名称
param min_sample: 待切分样本的最小样本量(限制条件)
'''
# 根据样本评分计算相邻不同分数的中间值
score_median_list = calc_score_median(sample_set, var)
median_len = len(score_median_list)
sample_cnt = sample_set.shape[0]
sample1_cnt = sum(sample_set['target'])
sample0_cnt = sample_cnt- sample1_cnt
Gini = 1 - np.square(sample1_cnt / sample_cnt) - np.square(sample0_cnt / sample_cnt)
bestGini = 0.0; bestSplit_point = 0.0; bestSplit_position = 0.0
for i in range(median_len):
left = sample_set[sample_set[var] < score_median_list[i]]
right = sample_set[sample_set[var] > score_median_list[i]]
left_cnt = left.shape[0]; right_cnt = right.shape[0]
left1_cnt = sum(left['target']); right1_cnt = sum(right['target'])
left0_cnt = left_cnt - left1_cnt; right0_cnt = right_cnt - right1_cnt
left_ratio = left_cnt / sample_cnt; right_ratio = right_cnt / sample_cnt
if left_cnt < min_sample or right_cnt < min_sample:
continue
Gini_left = 1 - np.square(left1_cnt / left_cnt) - np.square(left0_cnt / left_cnt)
Gini_right = 1 - np.square(right1_cnt / right_cnt) - np.square(right0_cnt / right_cnt)
Gini_temp = Gini - (left_ratio * Gini_left + right_ratio * Gini_right)
if Gini_temp > bestGini:
bestGini = Gini_temp; bestSplit_point = score_median_list[i]
if median_len > 1:
bestSplit_position = i / (median_len - 1)
else:
bestSplit_position = i / median_len
else:
continue
Gini = Gini - bestGini
return bestSplit_point, bestSplit_position
min_sample 参数为最小叶子节点的样本阈值,如果小于该阈值则不进行切分,如前面所述设置为整体样本量的5%
返回的结果我这里只返回了最优分割点,如果需要返回其他的比如GINI值,可以自行添加。
def bining_data_split(sample_set, var, min_sample, split_list):
'''
划分数据找到最优分割点list
param sample_set: 待切分样本
param var: 分割变量名称
param min_sample: 待切分样本的最小样本量(限制条件)
param split_list: 最优分割点list
'''
split, position = choose_best_split(sample_set, var, min_sample)
if split != 0.0:
split_list.append(split)
# 根据分割点划分数据集,继续进行划分
sample_set_left = sample_set[sample_set[var] < split]
sample_set_right = sample_set[sample_set[var] > split]
# 如果左子树样本量超过2倍最小样本量,且分割点不是第一个分割点,则切分左子树
if len(sample_set_left) >= min_sample * 2 and position not in [0.0, 1.0]:
bining_data_split(sample_set_left, var, min_sample, split_list)
else:
None
# 如果右子树样本量超过2倍最小样本量,且分割点不是最后一个分割点,则切分右子树
if len(sample_set_right) >= min_sample * 2 and position not in [0.0, 1.0]:
bining_data_split(sample_set_right, var, min_sample, split_list)
else:
None
split_list 参数是用来保存返回的切分点,每次切分后返回的切分点存入该list
在这里判断切分点分割的左子树和右子树是否满足“内部节点再划分所需的最小样本数>=总样本量的10%”的条件,如果满足则进行递归调用。
def get_bestsplit_list(sample_set, var):
'''
根据分箱得到最优分割点list
param sample_set: 待切分样本
param var: 分割变量名称
'''
# 计算最小样本阈值(终止条件)
min_df = sample_set.shape[0] * 0.05
split_list = []
# 计算第一个和最后一个分割点
bining_data_split(sample_set, var, min_df, split_list)
return split_list
最后整合以下来个函数调用,返回一个分割点list。
可以使用sklearn库的决策树测试一下单变量分类对结果进行验证,在分类方法相同,剪枝条件一致的情况下结果是一致的。
来源:https://blog.csdn.net/weixin_42097808/article/details/80172824
猜你喜欢
- 如何发送一个XMLHttpRequest的检索的特定部分HTML标题数据。<html> <head> <tit
- 网站中很多表单都会用到上传图片,logo,照片,用户也会上传图片,这个时候网站就需要一个上传图片的功能,而且在上传后希望能预览一下看上传的对
- Web标准的web UI——来源、谬误与个人理解序我从2004年末开始接触web标准,2005年5月正式采取完全的web标准方式的网页制作,
- 在网上查了部分资料但是发现粘上去的代码都存在问题,无奈只好自己修改了一下,代码如下: 如下代码能正常运行,都是网上查找资料最后拼凑总结出来的
- #!/usr/bin/env python# -*- coding:utf-8 -*-#导入random和string模块import ra
- 看下面的一组例子:alert(true.toString());alert(false.toString());alert(1.123.to
- 文字的多行处理在dom元素中很好办。但是canvas中没有提供方法,只有通过截取指定字符串来达到目的。那么下面就介绍我自己处理的办法:wxm
- 概要:本文主要描述XHTML中相对定位和绝对定位各自的本质、用法、区别和两者之间的关系。以及使用CSS的Left、Right、Top、Bot
- 经常使用word办公的小伙伴们经常会遇到邮件合并的任务,通常会将数量有限的表格中的信息通过word的邮件合并功能,自动生成word文档,操作
- 轮播图的根本其实就是缓动函数的封装,如果说轮播图是一辆跑动的汽车,那么缓动函数就是它的发动机,今天本文章就带大家由简入繁,封装属于自己的缓动
- 前言一个简单的php➕mysql项目学生信息管理系统,用于广大学子完成期末作业的参考,该系统实现增、删、改、查等基本功能。1、登录界面<
- 一、高斯滤波 高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。 [1] 通俗的讲,高斯滤波就是对整幅图像进
- 高阶函数英文叫Higher-order function。什么是高阶函数?我们以实际代码为例子,一步一步深入概念。变量可以指向函数以Pyth
- 本文实例为大家分享了Python使用tkinter实现小时钟效果的具体代码,供大家参考,具体内容如下自己又调试了一下,分享一下# codin
- 看了下传统的方法,觉得不好,太麻烦。自己重写了个,思路比较新。这个函数的优点是html代码可以很简洁,使用图片也可以很少,只需要两张图片。事
- 如何用Cookie进行登录验证?很简单,看看这两个文件:login.htm请注册登录随风起舞<FORM ACTION=&qu
- 字体大小CSS2规范根据长度——水平和垂直尺寸——来定义字体。这个长度为一个数值,前面可能带一个可选的加(+)或减(-)标记符。另外,该数值
- 上次帮朋友写过的一个简单切换效果,超级简单,但也比较适用.因为用到了CSS Sprite技术,DEMO中附带了IE6兼容png的JS.核心J
- 昨天ie8正式发布了,偶也去下载了一个,感觉很爽, 还在美的时候,突然发现很多网页都出问题,更可气的是自己的网站编辑器eWebEditor也
- 阅读上一篇:微软建议的ASP性能优化28条守则(4)技巧 13:避免重新确定数组的维数 应尽量避免 Redim 数组。就性能而言,如果计算机