树回归(二)

树剪枝

一棵树如果节点过多,说明该模型存在过拟合问题。

通过降低决策树的复杂度来避免过拟合的过程称为剪枝(pruning)。树回归(一)中的chooseBestSplit函数中的提前终止条件,实际上是一种预剪枝(prepruning)操作。另一种形式的剪枝需要使用测试集和训练集,称作后剪枝(postpruning)。

预剪枝的不足

树回归(一)中的树构建算法对参数tolStolN非常敏感,下面用树回归(一)中的第一个数据集,采用不同的ops参数,来观察结果。

dataSet = loadDataSet('ex00.txt')
myMat = np.mat(dataSet)
createTree(myMat, ops=(0,1))

结果如下:

{'spInd': 0,
 'spVal': 0.48813,
 'left': {'spInd': 0,
  'spVal': 0.620599,
  'left': {'spInd': 0,
 ......
  'right': {'spInd': 0,
   'spVal': 0.325412,
   'left': {'spInd': 0, 'spVal': 0.3371, 'left': 0.1910235, 'right': 0.118208},
   'right': -0.028594120689655174}}}

由于输出过长,这里省略部分内容。

与上文中只包含两个节点的树相比,这里构建的树过于臃肿。

下面用一个与ex00.txt数据集分布类似,但y轴数量级是其100倍的ex2.txt数据集来构建树。

dataSet = loadDataSet('ex2.txt')
myMat2 = np.mat(dataSet)
createTree(myMat2)

结果如下

{'spInd': 0,
 'spVal': 0.499171,
 'left': {'spInd': 0,
  'spVal': 0.729397,
  'left': {'spInd': 0,
   'spVal': 0.952833,
   'left': 108.838789625,
 ......
 'right': {'spInd': 0,
  'spVal': 0.457563,
  'left': 7.969946125,
  'right': -3.6244789069767447}}

用默认参数构建的树显得比较臃肿。下面是其分布。


ex00.txtex2.txt两个数据集分布类似,但在都采用默认参数的情况下,ex00.txt构建的树只有两个叶节点,而ex2.txt却有很多。产生这种现象的原因在于,停止条件tolS对误差的数量级十分敏感。如果在选项上花费时间并对上述误差容忍度取平方值,也能得到两个叶节点的树:

createTree(myMat2, ops=(10000, 4))

output:
{'spInd': 0,
 'spVal': 0.499171,
 'left': 101.35815937735848,
 'right': -2.637719329787234}

然而,通过不断修改参数来得到合理结果并不是很好的办法。

下面将介绍后剪枝,利用测试集来对树进行剪枝,并不需要指定参数,是一种更理想化的剪枝方法。

后剪枝

剪枝函数prune()的伪代码如下:

基于已有的树切分测试数据:
    如果存在任意子集是一棵树,则在该子集递归剪枝
    计算将当前两个叶节点合并后的误差
    计算不合并的误差
    如果合并会降低误差的话,就将叶节点合并
def isTree(obj):
    return (type(obj).__name__ == 'dict')

def getMean(tree):
    if isTree(tree['left']):
        tree['left'] = getMean(tree['left'])
    if isTree(tree['right']):
        tree['right'] = getMean(tree['right'])
    return (tree['left'] + tree['right'])/2

def prune(tree, testData):
    # 没有测试数据则对树进行塌陷处理
    if testData.shape[0] == 0: 
        return getMean(tree)
    
    if (isTree(tree['right']) or isTree(tree['left'])):
        lSet, rSet = splitDataSet(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 = splitDataSet(testData, tree['spInd'], tree['spVal'])
        errorNoMerge = sum(np.power(lSet[:,-1] - tree['left'],2)) +\
            sum(np.power(rSet[:,-1] - tree['right'],2))
        treeMean = (tree['left']+tree['right'])/2.0
        errorMerge = sum(np.power(testData[:,-1] - treeMean,2))
        if errorMerge < errorNoMerge: 
            print("merging")
            return treeMean
        else: return tree
    else: return tree

isTree()判断是否为树。
getMean()从上往下遍历树直到叶节点为止。该函数对树进行塌陷处理,即返回树平均值。
接下来看看实际效果。

# 构建一个过拟合的树
myTree = createTree(myMat2, ops=(0,1))
# 加载测试集
testData = loadDataSet('ex2test.txt')
testMat = np.mat(testData)
# 剪枝
prune(myTree, testMat)

运行后观察两棵树,可以发现大量节点被剪枝掉,但没有预期那样剪枝成两部分。
一般地,为了寻求最佳模型可以同时使用两种剪枝技术。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 姓名:唐来宾 学号:17101223417 转载http://mp.weixin.qq.com/s/-CSSh2p...
    ahbz_t阅读 1,359评论 1 4
  • 第9章 树回归 树回归 概述 我们本章介绍 CART(Classification And Regression ...
    Joyyx阅读 1,136评论 0 3
  • 前一章介绍了线性回归有很多强大的方法,但是缺点是创建的模型需要拟合所有的样本点(局部加权线性回归除外),当数据拥有...
    1597830b3381阅读 552评论 0 0
  • 一、树回归介绍 线性回归包含了一些强大的方法,但这些方法创建的模型需要拟合所有的样本点(局部加权线性回归除外)。当...
    nobodyyang阅读 560评论 0 0
  • 决策树理论在决策树理论中,有这样一句话,“用较少的东西,照样可以做很好的事情。越是小的决策树,越优于大的决策树”。...
    制杖灶灶阅读 5,848评论 0 25