- 阅读权限
- 255
- 威望
- 0 级
- 论坛币
- 256 个
- 通用积分
- 1.0500
- 学术水平
- 0 点
- 热心指数
- 0 点
- 信用等级
- 0 点
- 经验
- 934 点
- 帖子
- 43
- 精华
- 0
- 在线时间
- 156 小时
- 注册时间
- 2011-11-8
- 最后登录
- 2025-12-17
本科生
还不是VIP/贵宾
- 威望
- 0 级
- 论坛币
 - 256 个
- 通用积分
- 1.0500
- 学术水平
- 0 点
- 热心指数
- 0 点
- 信用等级
- 0 点
- 经验
- 934 点
- 帖子
- 43
- 精华
- 0
- 在线时间
- 156 小时
- 注册时间
- 2011-11-8
- 最后登录
- 2025-12-17
 | 开心 2021-8-6 11:09:22 |
|---|
签到天数: 249 天 连续签到: 1 天 [LV.8]以坛为家I
|
100论坛币
|
- calc_score_median<- function(df, col){
- # 计算相邻评分的中位数,以便进行决策树二元切分
- #
- # param df: 待切分样本
- # param col: 分割变量名称
- var_list <- sort(unique(df[,col]))
- var_median_list <- numeric(length(var_list)-1)
- for(i in 1:(length(var_list)-1)){
- var_median_list[i] = (var_list[i] + var_list[i+1]) / 2
- }
- return(var_median_list)
- }
- choose_best_split <- function(df,col,target,min_sample){
- # 使用CART分类决策树选择最好的样本切分点
- # 返回切分点
- # param sample_set: 待切分样本
- # param var: 分割变量名称
- # param min_sample: 待切分样本的最小样本量(限制条件),如果小于该阈值则不进行切分,可设置为整体样本量的5%
- var_median_list <- calc_score_median(df,col)
- median_len = length(var_median_list)
- sample_cnt <- dim(df)[1]
- sample1_cnt <- sum(df[,target])
- sample0_cnt <- sample_cnt-sample1_cnt
- Gini <- 1- ((sample1_cnt/sample_cnt)**2)-((sample0_cnt/sample_cnt)**2)
- bestGini <- 0.0
- bestSplit_point <- 0.0
- bestSplit_position <- 0.0
- for(i in 1:median_len){
- left <- df[which(df[,col] < var_median_list[i]),]
- right <- df[which(df[,col] > var_median_list[i]),]
- left_cnt <- dim(left)[1]
- right_cnt <- dim(right)[1]
- 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
- Gini_left = 1 - ((left1_cnt / left_cnt)**2) - ((left0_cnt / left_cnt)**2)
- Gini_right = 1 - ((right1_cnt / right_cnt)**2) - ((right0_cnt / right_cnt)**2)
- Gini_temp = Gini - (left_ratio * Gini_left + right_ratio * Gini_right)
- if(left_cnt < min_sample || right_cnt < min_sample){
- next
- }
- if(Gini_temp > bestGini){
- bestGini = Gini_temp
- bestSplit_point = var_median_list[i]
- if(median_len>1){
- bestSplit_position = i / (median_len - 1)
- }else{
- bestSplit_position = i / median_len
- }
- }else{
- next
- }
- }
- Gini = Gini - bestGini
- return(list(bestSplit_point, bestSplit_position))
- }
- bining_data_split <- function(df, col, target,min_sample,split_list){
- # 划分数据找到最优分割点list
- # param sample_set: 待切分样本
- # param var: 分割变量名称
- # param min_sample: 待切分样本的最小样本量(限制条件),如果小于该阈值则不进行切分,可设置为整体样本量的5%
- # param split_list: 最优分割点list,split_list 参数是用来保存返回的切分点,每次切分后返回的切分点存入该list
- middle <- choose_best_split(df,col,target,min_sample)
- split <- middle[[1]]
- position <- middle[[2]]
- if(split != 0){
- split_list <- c(split_list,split)
- }
- # 根据分割点划分数据集,继续进行划分
- sample_set_left <- df[which(df[,col] < split),]
- sample_set_right <- df[which(df[,col] > split),]
- # 如果左子树样本量超过2倍最小样本量,且分割点不是第一个分割点,则切分左子树
- #在这里判断切分点分割的左子树和右子树是否满足“内部节点再划分所需的最小样本数>=总样本量的10%”的条件,如果满足则进行递归调用。
- if(length(sample_set_left) >= (min_sample * 2) && ! position %in% c(0, 1)){
- bining_data_split(sample_set_left, col, target,min_sample, split_list)
- }else{
- return(NULL)
- }
- if(length(sample_set_right) >= (min_sample * 2) && ! position %in% c(0, 1)){
- bining_data_split(sample_set_right, col, target,min_sample, split_list)
- }else{
- return(NULL)
- }
- }
- get_bestsplit_list <- function(df, col,target,min_sample_ratio){
- # 计算最小样本阈值(终止条件)
- min_sample <- dim(df)[1]*min_sample_ratio
- split_list = c()
- bining_data_split(df, col, target,min_sample, split_list)
- return(split_list)
- }
复制代码 bining_data_split函数被设计成一个递归函数,其中有一个关键的地方就是参数split_list,每次bining_data_split循环调用自身时希望会值能够不断的添加到split_list,最终用get_bestsplit_list 求split_list的结果,但是bining_data_split 函数中if(split != 0){
split_list <- c(split_list,split)
}这种设计好像是有问题的,导致结果出不来
求大神能帮忙解答解答,万分感谢
|
|