機器學習 | 樹迴歸

因爲近期學業繁重QAQ,因此我就不說廢話了,直接上代碼~python

運行結果

圖片描述

圖片描述

代碼

from numpy import *
#使用二元切分法——每次將數據集切成兩份
#若是數據的某特徵值等於切分所要求的值,
#那麼這些數據就進入樹的左子樹,反之則
# 進入右子樹
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


#參數:數據集,待切分的特徵,該特徵的某個值
def binSplitDataSet(dataSet,feature,value):
    #將數據集合切分獲得兩個子集並返回
    mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:]
    mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:]

    return mat0,mat1

#創建葉結點的函數
#當chooseBestSplit函數決定再也不對數據集進行切分時,將調用該regLeaf函數
#來獲得葉節點的模型。在迴歸樹種,該模型其實就是目標變量的均值
def regLeaf(dataSet):
    return mean(dataSet[:,-1])

#計算偏差的函數——這裏計算的是總方差
def regErr(dataSet):
    #均方差函數var*數據集中樣本的個數=總方差
    return var(dataSet[:,-1]) * shape(dataSet)[0]

#給定某個偏差計算方法,該函數會找到數據集上最佳的二元切割方式
#(他遍歷全部的特徵及可能的取值來找到使偏差最小化的切分閾值)
#另外,該函數還要肯定何時中止切分,一旦中止切分就會生成一個葉節點
#errType爲平方偏差的總值(總方差)
def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):
    #用戶指定的參數,用於控制函數中止時機
    #tolS爲偏差降低值,tolN爲切分的最少樣本數
    tolS = ops[0]; tolN = ops[1]
    #若是全部值相等則退出
    if len(set(dataSet[:,-1].T.tolist()[0])) == 1:
        #找不到一個「好」的二元切分,返回None並同時調用leafType來生成葉節點
        return None, leafType(dataSet)
    m,n = shape(dataSet)
    S = errType(dataSet)
    bestS = 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 (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 (S - bestS) < tolS: 
        return None, leafType(dataSet) 
    mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)
    #若是切分出的數據集很小則退出
    if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): 
        return None, leafType(dataSet)
    #找到了一個「好」的切分方式,返回特徵編號和切分特徵值
    #找到了最佳的切分方式:切分後能達到最低偏差的切分
    return bestIndex,bestValue


#構建樹的函數
#dataSet爲數據集
#leafType爲創建葉結點的函數,errType爲偏差計算函數
#ops是一個包含書構建所需其餘參數的元組
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):
    #chooseBestSplit爲切分函數
    #若知足中止條件chooseBestSplit將返回None和某類模型的值
    #若是構建的是迴歸樹,該模型是一個常數,若是是模型樹,其
    #模型是一個線性方程(迴歸樹假設葉節點是常數值)
    #若不知足中止條件,chooseBestSplit將建立一個新的python
    #字典,並將數據集分紅兩份,在這兩份數據集上分別繼續遞歸調
    #用createTree函數
    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


def drawFigure1():
    # import matplotlib.pyplot as plt 
    # myDat=loadDataSet('ex00.txt') 
    # myMat=mat(myDat) 
    # createTree(myMat) 
    # plt.plot(myMat[:,0],myMat[:,1],'ro') 
    # plt.show()
    import matplotlib.pyplot as plt 
    myDat=loadDataSet('ex0.txt') 
    myMat=mat(myDat) 
    createTree(myMat) 
    plt.plot(myMat[:,1],myMat[:,2],'ro') 
    plt.show()



def main():
    drawFigure1()
    # myDat=loadDataSet('ex00.txt')
    # myMat=mat(myDat)
    # myTree=createTree(myMat)
    # print(myTree)


    #創建一個主對角線元素全爲1的矩陣
    #testMat=mat(eye(4))
    #print(testMat)
    #要分割的特徵位於第一列
    #按照0.5去劃分
    #mat0,mat1=binSplitDataSet(testMat,0,0.5)
    # print(mat0)
    # print(mat1)

if __name__=='__main__':
    main()```


  [1]: /img/bVbqGCZ
相關文章
相關標籤/搜索