python实现连续变量最优分箱详解--CART算法


Posted in Python onNovember 22, 2019

关于变量分箱主要分为两大类:有监督型和无监督型

对应的分箱方法:

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库的决策树测试一下单变量分类对结果进行验证,在分类方法相同,剪枝条件一致的情况下结果是一致的。

以上这篇python实现连续变量最优分箱详解--CART算法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python线程中对join方法的运用的教程
Apr 09 Python
Python监控主机是否存活并以邮件报警
Sep 22 Python
Python使用Matplotlib实现Logos设计代码
Dec 25 Python
python3写的简单本地文件上传服务器实例
Jun 04 Python
django缓存配置的几种方法详解
Jul 16 Python
利用python画出折线图
Jul 26 Python
详解用python写网络爬虫-爬取新浪微博评论
May 10 Python
Flask框架学习笔记之模板操作实例详解
Aug 15 Python
通过celery异步处理一个查询任务的完整代码
Nov 19 Python
Python中内建模块collections如何使用
May 27 Python
pycharm中如何自定义设置通过“ctrl+滚轮”进行放大和缩小实现方法
Sep 16 Python
Python爬虫实战案例之爬取喜马拉雅音频数据详解
Dec 07 Python
pycharm运行scrapy过程图解
Nov 22 #Python
python迭代器常见用法实例分析
Nov 22 #Python
python自动分箱,计算woe,iv的实例代码
Nov 22 #Python
python创建学生管理系统
Nov 22 #Python
Python如何计算语句执行时间
Nov 22 #Python
python生成器用法实例详解
Nov 22 #Python
关于pandas的离散化,面元划分详解
Nov 22 #Python
You might like
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
兼容firefox,chrome的网页灰度效果
2011/08/08 PHP
php类自动加载器实现方法
2015/07/28 PHP
php+MySQL实现登录时验证登录名和密码是否正确
2016/05/10 PHP
PHP7 echo和print语句实例用法
2019/02/15 PHP
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
js 获取、清空input type=&quot;file&quot;的值(示例代码)
2013/12/24 Javascript
javascript删除字符串最后一个字符
2014/01/14 Javascript
jquery validate表单验证的基本用法入门
2016/01/18 Javascript
Jquery Easyui搜索框组件SearchBox使用详解(19)
2016/12/17 Javascript
angular forEach方法遍历源码解读
2017/01/25 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
支付宝小程序tabbar底部导航
2018/11/06 Javascript
JS工厂模式开发实践案例分析
2019/10/17 Javascript
微信小程序实现点击生成随机验证码
2020/09/09 Javascript
vue+element_ui上传文件,并传递额外参数操作
2020/12/05 Vue.js
[55:54]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
[01:12:53]完美世界DOTA2联赛PWL S2 Forest vs SZ 第一场 11.25
2020/11/26 DOTA
Python中用于转换字母为小写的lower()方法使用简介
2015/05/19 Python
简单谈谈Python中的元祖(Tuple)和字典(Dict)
2017/04/21 Python
Python编程求解二叉树中和为某一值的路径代码示例
2018/01/04 Python
python实现汽车管理系统
2018/11/30 Python
Windows下PyCharm2018.3.2 安装教程(图文详解)
2019/10/24 Python
Python全局变量与global关键字常见错误解决方案
2020/10/05 Python
中国宠物用品商城:E宠商城
2016/08/27 全球购物
Lungolivigno Fashion官网:高级时装在线购物
2020/10/17 全球购物
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排
2014/01/13 面试题
机械制造与自动化应届生求职信
2013/11/16 职场文书
酒店保洁主管岗位职责
2013/11/28 职场文书
信息工作经验交流材料
2014/05/28 职场文书
商场开业庆典策划方案
2014/06/02 职场文书
文明城市标语
2014/06/16 职场文书
新教师个人总结
2015/02/06 职场文书
大学学生个人总结
2015/02/15 职场文书
2015暑期工社会实践报告
2015/07/13 职场文书