技术控

    今日:17| 主题:49249
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] 树回归

[复制链接]
﹏戒蔔掉旳愛 发表于 2016-10-5 19:38:03
119 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

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

  binSplitDataSet()函数,有三个参数:数据集合,待切分的特征和该特征的某个值。在给定特征和特征值的情况下,该函数通过数组过滤方式将上述数据集合切分得到两个子集并返回。
  [code]def binSplitDataSet(dataSet, feature, value):
    mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:][0]
    mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:][0]
    return mat0, mat1[/code]  createTree()函数,有4个参数,数据集和其他三个可选参数,这些可选参数决定了树的类型: leafType给出了建立叶节点的函数,errorType代表误差计算函数,ops是一个包含树构建所需其它参数的元祖。
  [code]def createTree(dataSet, leafType = regLeaf, errType = regErr, ops=(1,4)):
    feat, val = chooseBestSplit(dataSet, leafType, errType, ops)
    if feat == None: return val
    retTree = {}
    retTree['spInd'] = feat
    retTree['spVal'] = val
    lSet, rSet = binSplitDataSet(dataSet, feat, val)
    retTree['left'] = createTree(lSet, leafType, errType, ops)
    retTree['right'] = createTree(rSet, leafType, errType, ops)
    return retTree[/code]  chooseBestSplit()函数,给定某个误差计算方法,该函数会找到数据集上的最佳二元切分方式。该函数需要完成两件事:用最佳方式切分数据集和生成相应的叶节点。
  伪代码如下:
  [code]对每个特征:
    对每个特征值:
        将数据集切分成两份
        计算切分的误差
        如果当前误差小于当前最小误差,将当前切分设定为最佳切分并更新最小误差
返回最佳切分的特征和阀值[/code]  coding:
  [code]def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):
    tolS = ops[0]; tolN = ops[1]
    #if all the target variables are the same value: quit and return value
    if len(set(dataSet[:,-1].T.tolist()[0])) == 1: #exit cond 1
        return None, leafType(dataSet)
    m,n = shape(dataSet)
    #the choice of the best feature is driven by Reduction in RSS error from mean
    S = errType(dataSet)
    bestS = inf; bestIndex = 0; bestValue = 0
    for featIndex in range(n-1):
        for splitVal in set(dataSet[:,featIndex]):
            mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)
            if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue
            newS = errType(mat0) + errType(mat1)
            if newS < bestS:
                bestIndex = featIndex
                bestValue = splitVal
                bestS = newS
    #if the decrease (S-bestS) is less than a threshold don't do the split
    if (S - bestS) < tolS:
        return None, leafType(dataSet) #exit cond 2
    mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)
    if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):  #exit cond 3
        return None, leafType(dataSet)
    return bestIndex,bestValue#returns the best feature to split on
                              #and the value used for that split[/code]  函数chooseBestSplit()一开始为ops设定了tolS和tolN这两个值,它们是用户指定的参数,用于控制函数的停止时机。其中tolS是容许的误差下降值,tolN是切分的最少样本数。通过对当前所有目标变量建立一个集合,然后统计不同剩余特征值的数目,如果该数目为1,那么不需要再切分直接返回,然后函数计算了当前数据集的大小和误差,该误差S将用于和新切分误差进行对比,检查新切分能否降低误差。 如果切分数据集后效果提升不够大,那么就不进行切分操作而直接创建叶节点。
  另外,还需要检验两个切分后的子集大小,如果某个子集大小小于用户定义的参数tolN,那么也不进行切分。
  运行结果:
   
树回归-1 (return)

  后剪枝

  伪代码:
  [code]基于已有的树切分测试数据:
    如果存在任一子集是一棵树,则在该子集递归剪枝过程
    计算将当前两个节点合并后的误差
    计算不合并的误差
    如果合并会降低误差的话,就将叶节点合并。[/code]  coding:
  [code]def prune(tree, testData):
    if shape(testData)[0] == 0: return getMean(tree)
    if (isTree(tree['right']) or isTree(tree['left'])):
        lSet, rSet = binSplitDataSet(testData, tree['spInd'],tree['spVal'])
    if isTree(tree['left']): tree['left'] = prune(tree['left'],lSet)
    if isTree(tree['right']): tree['right'] = prune(tree['right'],rSet)
    if not isTree(tree['left']) and not isTree(tree['right']):
        lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal'])
        errorNoMerge = sum(power(lSet[:,-1] - tree['left'],2)) + \
        sum(power(rSet[:,-1] - tree['right'],2))
        treeMean = (tree['left'] + tree['right']) / 2.0
        errorMerge = sum(power(testData[:,-1] - treeMean,2))
        if errorMerge < errorNoMerge:
            print "merging"
            return treeMean
        else : return tree
    else:return tree[/code]  函数prune()有两个参数,待剪枝的树与剪枝所需的测试集。首先确认测试集是否为空,如果非空,则反复递归调用prune()对测试数据进行切分。检查某个分支到底是子树还是节点。如果是子树,就调用函数来对子树进行剪枝。再对左右两个分支完成剪枝后,还需要检查它们是否仍然还是子树,如果已经不再是子树,那么就可以进行合并。具体做法是对合并前后的误差进行比较,如果合并后的误差比不合并的小就进行合并操作,反之不合并直接返回。
  运行结果:

树回归-2 (return)

  模型树

  用树来对数据进行建模,除了把叶节点设定为常数值外,还可以将其设定为分段线性函数,分段线性(piecewise linear)即模型由多个线性片段组成。
12下一页
友荐云推荐




上一篇:Next Generation Server Compression With Brotli
下一篇:Using Neo4j & Structr to Measure the Impact of 1 Tonne of Carbon
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

奇葩朵朵向阳开 发表于 2016-10-15 14:34:40
突然觉得﹏戒蔔掉旳愛说的很有道理,赞一个!
回复 支持 反对

使用道具 举报

日付20网赚网 发表于 2016-10-22 00:47:36
鸳鸳相抱何时了,鸯在一边看热闹。  
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表