回归 - 决策树

1.概述

CART, Classification And Regression Tree, 分类与回归树. 该模型由Breiman等人在1984年提出.
该模型中决策树是二叉树, 每个内部节点对应一个二元判断, 判断为 ‘真’, 走左子树, 否则走右子树.

1.2 GBDT

GBDT, Gradient Boosting Decision tree. 梯度提升决策树.
使用提升树的集成学习boosting思想, 使用梯度下降的优化方法, 以CART树做模型.
见参考[1].

2. 思想

类似于分类决策树中, 通过信息熵度量分布的随机情况. 回归树中, 用方差总和(即方差*该集合中样本数) 来度量.

  • 公式
    arg ⁡ min ⁡ j , s [ ∑ x i ∈ R 1 ( j , s ) ( y i − y ˉ ) 2 + ∑ x i ∈ R 2 ( j , s ) ( y i − y ˉ ) 2 ] (1) \arg \min_{j,s}[\sum_{x_i\in R_1(j,s)}(y_i-\bar y)^2+\sum_{x_i\in R_2(j,s)}(y_i-\bar y)^2] \tag 1 argj,smin[xiR1(j,s)(yiyˉ)2+xiR2(j,s)(yiyˉ)2](1)
    其中 s ∈ 特 征 集 合 , j ∈ s 特 征 下 的 取 值 集 合 , R 1 , R 2 为 切 分 特 征 s 与 切 分 值 j 切 分 后 的 两 个 子 样 本 集 s \in 特征集合, j \in s特征下的取值集合, R_1, R_2为切分特征s与切分值j切分后的两个子样本集 s,js,R1,R2sj.

  • 伪代码

for 特征i in 特征集合:
	for 特征取值j in 特征i的取值集合:
		在 特征i 维度依据 取值j 将集合划分成两部分A与B
		计算切分后的误差x
		if( 该轮误差 <上轮误差):
			split_feature=特征i
			split_value=取值j

依据split_feature,split_value划分集合得到A B,得到左右子树,再递归地使用上述步骤建立完整的树.
		

3.代码

"""
回归决策树
主要方法为chooseBestSplit(), 依靠它递归地创建二叉树.
该代码体现了大致思想, 实际中还需要 
tolN=切分的最小样本数, tolS=允许的最小误差下降值 
来决定该次划分是产生叶子节点还是递归划分下去.
"""
import numpy as np
import pandas as pd

df=pd.read_csv('D:/code-study/py/diy/regression_problem_training_set.csv')
X = df.loc[:, ['feature1','feature2']]
y= np.ravel(df.loc[:, ['label']])

def chooseBestSplit(X,y):
    '''
    选择最佳split_feature和split_value
    :param X:
    :param y:
    :return: split_feature,split_value
    '''
    min_total_error=float('inf')
    # 双层for循环
    for feature in X.columns:
        series_of_feature=X[feature]
        for value in set(series_of_feature):
            X1,y1,X2,y2=split_by_feature_and_value(X,y,feature,value)
            total_error=calc_error(y1)+calc_error(y2)
            if(total_error<min_total_error):
                min_total_error=total_error
                split_feature=feature
                split_value=value
    return split_feature,split_value


def split_by_feature_and_value(X,y,split_feature,split_value):
    '''
    依照split_feature,split_value, 切分数据集
    :param X:
    :param y:
    :return: 切分后的 X1,y1,X2,y2
    '''
    tmp=X.copy()
    tmp['label']=y
    tmp1=tmp[tmp[split_feature]>split_value]
    tmp2=tmp[tmp[split_feature]<=split_value]
    X1=tmp1.drop('label',1) # 在axis=1的维度上扔掉'label'列
    y1=tmp1['label']

    X2=tmp2.drop('label',1)
    y2=tmp2['label']

    return X1,y1,X2,y2


def calc_error(y):
    '''
    :param y:
    :return: 方差*元素个数
    '''
    return np.var(y)*len(y);

print(chooseBestSplit(X,y))

改代码参考自 <<机器学习实战>>, [美] Peter Harrington, P164.

参考

  1. my blog, 集成学习-GBDT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值