因为近期学业繁重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