樹(shù)回歸

當(dāng)數(shù)據(jù)擁有眾多特征并且特征之間關(guān)系十分復(fù)雜時(shí),構(gòu)建全局模型的想法就顯得太難了蹄咖。實(shí)際生活中很多問(wèn)題都是非線性的,不可能使用全局性模型來(lái)擬合任何數(shù)據(jù)钢拧。

一種可行的方法就是將數(shù)據(jù)集切分成很多易建模的數(shù)據(jù)青扔,然后再利用線性回歸技術(shù)來(lái)建模锅纺。本章介紹一種新的叫做CART的樹(shù)構(gòu)建算法,該算法可用于分類也可用于回歸。

復(fù)雜數(shù)據(jù)的局部性建模

樹(shù)構(gòu)建算法:

  • ID3 每次選取當(dāng)前最佳的特征來(lái)分割數(shù)據(jù),并按照該特征的所有可能取值來(lái)切分拗秘。如果一個(gè)特征有4個(gè)取值,那么數(shù)據(jù)將被切分成4份祈惶。一旦按某特征切分后雕旨,該特征在之后的算法執(zhí)行中將不會(huì)再起作用扮匠。
  • 二分法 每次把數(shù)據(jù)切成兩份。如果特征值大于給定值就走左子樹(shù)奸腺,否則就走右子樹(shù)餐禁。
    CART使用二元切分來(lái)處理連續(xù)型變量。對(duì)CART稍作修改就可以處理回歸問(wèn)題突照。

在樹(shù)的構(gòu)建過(guò)程中,需要解決多種類型數(shù)據(jù)的存儲(chǔ)問(wèn)題氧吐。這里使用字典來(lái)存儲(chǔ)樹(shù)的數(shù)據(jù)結(jié)構(gòu)讹蘑,字典包括1、待切分的特征 2筑舅、待切分的特征值座慰。 3、右子樹(shù)翠拣。當(dāng)不再需要切分的時(shí)候也可以是單個(gè)值版仔。4、左子樹(shù)误墓。 與右子樹(shù)類似蛮粮。

'''
創(chuàng)建樹(shù)節(jié)點(diǎn)
'''
class treeNode():
    def __init__(self,feat,val,right,left):
        self.featureToSplitOn = feat
        self.valueOfSpit = val
        self.rightBranch = right
        self.leftBranch = left
'''
加載數(shù)據(jù)
'''
def loadDataSet(fileName):
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float,curLine))
        dataMat.append(fltLine)
    return dataMat

'''
構(gòu)建樹(shù)  
dataSet 數(shù)據(jù)集
leafType 建立葉子節(jié)點(diǎn)的函數(shù)
errType  代表誤差計(jì)算函數(shù)
ops 代表樹(shù)構(gòu)建所需其他參數(shù)的元組
'''
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 = bindSplitDataSet(dataSet,feat,val)
    retTree['left'] = createTree(lSet,leafType,errType,ops)
    retTree['right'] = createTree(rSet,leafType,errType,ops)
    return retTree


'''
負(fù)責(zé)生成葉子節(jié)點(diǎn) 當(dāng)chooseBestSplit確定不再對(duì)數(shù)據(jù)進(jìn)行切分時(shí),調(diào)用子方法得到葉子節(jié)點(diǎn)
該函數(shù)就是目標(biāo)變量的均值
'''
def regLeaf(dataSet):
    return mean(dataSet[:,-1])

'''
在給定數(shù)據(jù)上計(jì)算目標(biāo)變量的平均誤差
'''
def regErr(dataSet):
    return var(dataSet[:,-1]) * shape(dataSet)[0]

'''
三個(gè)參數(shù) 分別為數(shù)據(jù)集合谜慌,待切分的特征和該特診的某個(gè)值
'''
def bindSplitDataSet(dataSet,feature,value):
    mats0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:]
    mats1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:]
    mat0 = [];mat1 = []
    if len(mats0) > 1:mat0 = mats0
    if len(mats1) > 1:mat1 = mats1
    return mat0,mat1

'''
找到最佳二元切分
dataSet 數(shù)據(jù)集
leafType 建立葉子節(jié)點(diǎn)的函數(shù)
errType  代表誤差計(jì)算函數(shù)
ops 代表樹(shù)構(gòu)建所需其他參數(shù)的元組
'''
def chooseBestSplit(dataSet,leafType=regLeaf,errType = regErr,ops=(1,4)):
    #ops的兩個(gè)值  用于控制函數(shù)的退出機(jī)制
    #tolS容許的誤差下降值
    #tolN切分的最好樣本
    tolS = ops[0];tolN = ops[1]
    #如果所有值相等則退出   如果該數(shù)目為1 就不需要再切分了
    if len(set(dataSet[:,-1].T.tolist()[0])) == 1:
        return None,leafType(dataSet)
    m,n = shape(dataSet)
    S = errType(dataSet)
    bestS = inf; bestIndx = 0; bestValue = 0
    # 在所有可能的特征和可能取值上遍歷
    #最佳的切分就是切分后能達(dá)到最低誤差的切分
    for featIndex in range(n-1):
        #書(shū)中源代碼有錯(cuò)誤然想。
        for splitVal in set(dataSet[:,featIndex].T.A.tolist()[0]):
            mat0,mat1 = bindSplitDataSet(dataSet,featIndex,splitVal)
            if(shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):continue
            newS = errType(mat0) + errType(mat1)
            if newS < bestS:
                bestIndx = featIndex
                bestValue = splitVal
                bestS = newS
    #如果誤差減少不大則退出
    if(S - bestS) < tolS:
        return None,leafType(dataSet)
    mat0,mat1 = bindSplitDataSet(dataSet,bestIndx,bestValue)
    #如果切分的數(shù)據(jù)小則退出
    if(shape(mat0)[0] < tolN) or (shape(mat1)[0]<tolN):
        return None,leafType(dataSet)
    return bestIndx,bestValue


if __name__ == '__main__':
    myDat = loadDataSet('eex00.txt')
    myMat = mat(myDat)
    retTree = createTree(myMat)
    print(retTree)

>>> {'left': 1.0180967672413792, 'spVal': 0.48813, 'spInd': 0, 'right': -0.044650285714285719}



if __name__ == '__main__':
    myDat = loadDataSet('regTreesex0.txt')
    myMat = mat(myDat)
    retTree = createTree(myMat)
    print(retTree)
>>> {'right': {'right': -0.023838155555555553, 'left': 1.0289583666666666, 'spInd': 1, 'spVal': 0.197834},
'left': {'right': 1.980035071428571, 'left': {'right': 2.9836209534883724, 'left': 3.9871631999999999, 'spInd': 1, 'spVal': 0.797583}, 'spInd': 1, 'spVal': 0.582002}, 'spInd': 1, 'spVal': 0.39435}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市欣范,隨后出現(xiàn)的幾起案子变泄,更是在濱河造成了極大的恐慌,老刑警劉巖恼琼,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妨蛹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡晴竞,警方通過(guò)查閱死者的電腦和手機(jī)蛙卤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颓鲜,“玉大人表窘,你說(shuō)我怎么就攤上這事√鸨酰” “怎么了乐严?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)衣摩。 經(jīng)常有香客問(wèn)我昂验,道長(zhǎng)捂敌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任既琴,我火速辦了婚禮占婉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甫恩。我一直安慰自己逆济,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布磺箕。 她就那樣靜靜地躺著奖慌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪松靡。 梳的紋絲不亂的頭發(fā)上简僧,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音雕欺,去河邊找鬼岛马。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屠列,可吹牛的內(nèi)容都是我干的啦逆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脸哀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蹦浦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起撞蜂,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盲镶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蝌诡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體溉贿,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年浦旱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宇色。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颁湖,死狀恐怖宣蠕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甥捺,我是刑警寧澤抢蚀,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站镰禾,受9級(jí)特大地震影響皿曲,放射性物質(zhì)發(fā)生泄漏唱逢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一屋休、第九天 我趴在偏房一處隱蔽的房頂上張望坞古。 院中可真熱鬧,春花似錦劫樟、人聲如沸痪枫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)听怕。三九已至,卻和暖如春虑绵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闽烙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工翅睛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人黑竞。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓捕发,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親很魂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扎酷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容