树回归

本文传送机

复杂数据的局部性建模

连续和离散型特征的树的构建

将CART算法用于回归

建树


回归的这篇文章中提供一一些强大的方法,但这些方法创建的模型需要你和所有的样本点(局部加强线性回归LWLR除外)。当数据拥有众多特征并且特征之间的关系十分复杂时,构建全局模型的想法就显得太难了。而且实际中很多问题都是非线性的,不可能使用全局限性模型来拟合任何数据。

一种可行的方法是数据集切分成很多份易建模的数据,然后利用线性回归技术来建模。如果首次切分之后仍然难以拟合线性模型就继续切分。在这种切分方式下,树构建和回归法就相当有用。

复杂数据的局部性建模

CART时十分著名且广泛记载的树构建算法,它使用二元切分来处理连续性变量。对CART稍作修改就可以处理回归问题。用于分类任务中的CART使用香农熵来度量集合的无组织程度。如果选用其他方法来代替香农熵,就可以使用树构建算法来完成回归。

树回归的一般方法

  1. 收集数据:采用任意方法收集数据
  2. 准备数据:需要数值型的数据,标称型数据应该映射成二值型数据
  3. 分析数据:绘出数据的二维可视化显示结果,以字典方式生成树
  4. 训练算法:大部分时间都花费在叶节点树模型的构建上
  5. 测试算法:使用测试数据上的R^2值来分析模型的效果
  6. 使用算法:使用训练出的树做预测,预测结果还可以用来做很多事情

连续和离散型特征的树的构建

这里将构建两种树:第一种是回归树(regression tree),其每个叶节点包含单个值;第二种是模型树(model tree),其叶节点包含一个线性方程。

函数create_tree()的伪代码:

  • 找到最佳的待切分特征:
    • 如果该节点不能再分,将该节点存为叶节点
    • 执行二元切分
    • 在右子树调用create_tree()方法
    • 在左子树调用create_tree()方法

 代码:

import numpy as np


def load_data_set(file_name):
    data_array = []
    file = open(file_name)
    for line in file.readlines():
        current_line = line.strip().split('\t')
        float_line = map(float, current_line)
        data_array.append(float_line)
    return data_array

def binary_split_data_set(data_set, feature, value):
    mat0 = data_set[np.nonzero(data_set[:, feature] > value)[0], :][0]
    mat1 = data_set[np.nonzero(data_set[:, feature] <= value)[0], :][0]
    return mat0, mat1

def create_tree(data_set, leaf_type=regress_leaf, error_type=regress_error, ops=(1, 4)):
    feature, value = choose_best_split(data_set, leaf_type, error_type, ops)
    if feature== None:
        return value
    return_tree = {}
    return_tree['split_feature'] = feature
    return_tree['split_value'] = value
    left_set, right_set = binary_split_data_set(data_set, feature, value)
    return_tree['left'] = create_tree(left_set, leaf_type, error_type, ops)
    return_tree['right'] = create_tree(right_set, leaf_type, error_type, ops)
    return return_tree

将CART算法用于回归

未成功构建以分段常熟为叶节点的树,需要度量出数据的一致性。那么如何计算连续性数值的混乱度呢?事实上,在数据集上计算混乱度非常简单,首先计算出所有数据的均值,然后计算每条数据的值到达均值的差值。为了对正负差值同等看待,一般使用平方值来代替上述差值。(即计算数据集的总方差)

构建树

为使上面代码中的create_tree()能够运行,首先要做的是实现choose_best_split()函数。给定某个误差计算方法,该函数会找到数据集上最佳的二元切分方式。另外,该函数还需要确定什么时候停止切分,一旦停止切分会生成一个叶节点。因此,choose_best_split()函数只需完成两件事:用最佳方式切分数据集和生成相应的叶节点。

代码:

import numpy as np


def load_data_set(file_name):
    data_array = []
    file = open(file_name)
    for line in file.readlines():
        current_line = line.strip().split('\t')
        float_line = list(map(float, current_line))
        data_array.append(float_line)
    return np.array(data_array)

def binary_split_data_set(data_set, feature, value):
    mat0 = data_set[np.nonzero(data_set[:, feature] > value)[0], :]
    mat1 = data_set[np.nonzero(data_set[:, feature] <= value)[0], :]
    return mat0, mat1

def regress_leaf(data_set):
    return np.mean(data_set[:, -1])

def regress_error(data_set):
    return np.var(data_set[:, -1]) * np.shape(data_set)[0]

def choose_best_split(data_set, leaf_type=regress_leaf, error_type=regress_error, ops=(1, 4)):
    tolerate_error = ops[0]
    tolerate_number = ops[1]
    if len(set(data_set[:, -1])) == 1:
        return None, leaf_type(data_set)
    m, n = np.shape(data_set)
    error = error_type(data_set)
    best_error = np.inf
    best_index = 0
    best_value = 0
    for feature_index in range(n-1):
        for split_value in set(data_set[:, feature_index]):
            mat0, mat1 = binary_split_data_set(data_set, feature_index, split_value)
            if np.shape(mat0)[0] < tolerate_number or np.shape(mat1)[0] < tolerate_number:
                continue
            new_error = error_type(mat0)+ error_type(mat1)
            if new_error < best_error:
                best_error = new_error
                best_index = feature_index
                best_value = split_value
    if error - best_error < tolerate_error:
        return None, leaf_type(data_set)
    mat0, mat1 = binary_split_data_set(data_set, best_index, best_value)
    if np.shape(mat0)[0] < tolerate_number or np.shape(mat1)[0] < tolerate_number:
        return None, leaf_type(data_set)
    return best_index, best_value

def create_tree(data_set, leaf_type=regress_leaf, error_type=regress_error, ops=(1, 4)):
    feature, value = choose_best_split(data_set, leaf_type, error_type, ops)
    if feature== None:
        return value
    return_tree = {}
    return_tree['split_feature'] = feature
    return_tree['split_value'] = value
    left_set, right_set = binary_split_data_set(data_set, feature, value)
    return_tree['left'] = create_tree(left_set, leaf_type, error_type, ops)
    return_tree['right'] = create_tree(right_set, leaf_type, error_type, ops)
    return return_tree

if __name__ == '__main__':
    data_set = load_data_set('ex0.txt')
    tree = create_tree(data_set)
    print(tree)

结果:

{'split_feature': 1, 'split_value': 0.39435, 'left': {'split_feature': 1, 'split_value': 0.582002, 'left': {'split_feature': 1, 'split_value': 0.797583, 'left': 3.9871632, 'right': 2.9836209534883724}, 'right': 1.980035071428571}, 'right': {'split_feature': 1, 'split_value': 0.197834, 'left': 1.0289583666666666, 'right': -0.023838155555555553}}

 

CONTACT INFORMATON

E-mail: birdguan@seu.edu.cn

QQ: 46611253

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值