机器学习实战学习笔记(八)树回归

PS:该系列数据都可以在图灵社区(点击此链接)中随书下载中下载(如下)
在这里插入图片描述

1 复杂数据的局部性建模

                                                      树回归
	优点:可以对复杂和非线性的数据建模。
	缺点:结果不易理解。
	适用数据类型:数值型和标称型数据。

  之前决策树适用的算法是ID3,其做法是每次选取当前最佳的特征来分割数据,并按照该特征的所有可能取值来切分。也就是说,如果一个特征有4中取值,那么数据将被切成4份。一旦按某特征切分后,该特征在之后的算法执行过程中将不会再起作用,这种切分方式过于迅速。ID3算法也不能直接处理连续型变量。
  另一种方法是二元切分法,即每次把数据集切成两份。易于对树构建过程进行调整以处理连续型特征,具体做法是:如果特征值大于给定值就走左子树,否则就走右子树。
  CART(Classification And Regression Trees,分类回归树) 是十分著名的树构建算法,它使用二元切分来处理连续型变量。

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

  python中可以直接使用字典来存储树结构而无需另外自定义一个类,从而有效地减少代码量。下面会构建两种树:回归树(regression tree),其每个叶节点包含单个值;模型树(model tree),其每个叶节点包含一个线性方程。
  共用函数createTree()伪代码:

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

  创建文件regTrees.py,并在python命令行进行测试:

import numpy as np 
import matplotlib.pyplot as plt

def loadDataSet(fileName):
    dataMat = []
    with open(fileName, 'r') as fileObject:
        for line in fileObject.readlines():
            curLine = line.strip().split('\t')
            fltLine = list(map(float, curLine))
            dataMat.append(fltLine)
    return dataMat

def binSplitDataSet(dataSet, feature, value):
    '''根据待切分的feature和值value执行二元切分'''
    mat0 = dataSet[np.nonzero(dataSet[:, feature] > value)[0], :]
    mat1 = dataSet[np.nonzero(dataSet[:, feature] <= value)[0], :]
    return mat0, mat1

在这里插入图片描述

3 将CART算法用于回归

  数据集混乱度计算:首先计算所有数据的均值,然后计算每条数据的值到均值的差值。为了对正负差值同等看待,一般使用绝对值或者平方值来代替上述差值,所以这里使用平方误差的总值(总方差)。

3.1 构建树

  需要编写函数chooseBestSplit(),该函数的目标是找到数据集切分的最佳位置。它遍历所有的特征及其可能的取值来找到使误差最小化的切分阈值。伪代码如下:

对每个特征:
	对每个特征值:
		将数据集切分成两份
		计算切分的误差
		如果当前误差小于当前最小误差,那么将当前切分设定为最佳切分并更新最小误差
返回最佳切分的特征和阈值

  添加代码,把数据文件拷贝到regTrees.py所在文件夹,并进行测试:

def regLeaf(dataSet):
    '''返回叶节点'''
    return np.mean(dataSet[:, -1])
    
def regErr(dataSet):
    '''返回平方误差'''
    return np.var(dataSet[:, -1]) * np.shape(dataSet)[0]

def choseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
    '''找到数据的最佳二元切分方式,生成相应的叶节点'''
    tolS = ops[0] #容许的误差下降值 
    tolN = ops[1] #切分的最少样本数
    if len(set(dataSet[:, -1].T.tolist()[0])) == 1:
        #如果所有特征值相等则退出
        return None, leafType(dataSet)
    m, n = np.shape(dataSet)
    S = errType(dataSet)
    bestS = float('inf')
    bestIndex = 0
    bestValue = 0
    #所有可能的特征和可能的取值上遍历
    for featIndex in range(n-1):
        for splitVal in set((dataSet[:, featIndex].T.A.tolist())[0]):
            mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)
            if np.shape(mat0)[0] < tolN or np.shape(mat1)[0] < tolN:
                continue
            newS = errType(mat0) + errType(mat1)
            if newS < bestS:
                bestIndex = featIndex
                bestValue = splitVal
                bestS = newS
    if (S - bestS) < tolS:
        #如果误差减少不大则退出
        return None, leafType(dataSet)
    mat0, mat1 = binSpl
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值