侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   300

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

对应的分箱方法:

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 pdimport 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迭代器常见用法实例分析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客