因爲近期學業繁重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