日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

决策树——CART和模型树

發(fā)布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 决策树——CART和模型树 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

CART樹

理解: ???? 如果CART樹處理離散型數據,叫做分類決策樹,那么,引入基尼指數作為尋找最好的數據劃分的依據,基尼指數越小,說明數據的“純度越高”,隨機森林的代碼里邊就運用到了基尼指數。如果CART樹處理連續(xù)型數據時,叫做回歸決策樹,那么,引入了平方誤差,首先,它使用二元切分來處理數據,得到兩個子集,計算誤差,找到最小誤差,確定最佳切分的特征編號和特征值,然后進行建樹。

構建回歸樹,需要給定某個誤差計算方法,該函數會找到數據集上最佳的二元切分方式。另外,該函數還要確定什么時候停止劃分,一旦停止劃分會生成一個葉節(jié)點。這里引入reLeaf(),regErr()分別得到葉節(jié)點和總方差。葉節(jié)點的模型是目標變量的 均值,var()是均方差,所以需要乘以數據集的樣本個數。

劃分數據集時,如果找不到一個‘好’的二元切分,該函數返回None值并產生葉節(jié)點,葉節(jié)點的值也為None。

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#切分數據集為兩個子集 # dataSet: 數據集合 # feature: 待切分的特征 # value: 該特征的某個值 #nonzero():得到數組非零元素的位置(數組索引) def binSplitDataSet(dataSet, feature, value) :mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:]mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:]return mat0, mat1# 負責生成葉節(jié)點,當chooseBestSplit()函數確定不再對數據進行切分時, # 將調用該regLeaf()函數來得到葉節(jié)點的模型,在回歸樹中,該模型其實就是目標變量的均值 def regLeaf(dataSet) :return mean(dataSet[:, -1])# 誤差估計函數,該函數在給定的數據上計算目標變量的平方誤差,這里直接調用均方差函數var # 因為這里需要返回的是總方差,所以要用均方差乘以數據集中樣本的個數 def regErr(dataSet) :return var(dataSet[:, -1]) * shape(dataSet)[0]# dataSet: 數據集合 # leafType: 給出建立葉節(jié)點的函數 # errType: 誤差計算函數 # ops: 包含樹構建所需其他參數的元組 def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)) :# 將數據集分成兩個部分,若滿足停止條件,chooseBestSplit將返回None和某類模型的值# 若構建的是回歸樹,該模型是個常數。若是模型樹,其模型是一個線性方程。# 若不滿足停止條件,chooseBestSplit()將創(chuàng)建一個新的Python字典,并將數據集分成兩份,# 在這兩份數據集上將分別繼續(xù)遞歸調用createTree()函數feat, val = chooseBestSplit(dataSet, leafType, errType, ops)if feat == None : return valretTree = {}retTree['spInd'] = featretTree['spVal'] = vallSet, rSet = binSplitDataSet(dataSet, feat, val)retTree['left'] = createTree(lSet, leafType, errType, ops)retTree['right'] = createTree(rSet, leafType, errType, ops)return retTree# 回歸樹的切分函數,構建回歸樹的核心函數。目的:找出數據的最佳二元切分方式。如果找不到 # 一個“好”的二元切分,該函數返回None并同時調用createTree()方法來產生葉節(jié)點,葉節(jié)點的 # 值也將返回None。 # 如果找到一個“好”的切分方式,則返回特征編號和切分特征值。 # 最佳切分就是使得切分后能達到最低誤差的切分。 def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)) :# tolS是容許的誤差下降值# tolN是切分的最小樣本數tolS = ops[0]; tolN = ops[1]# 如果剩余特征值的數目為1,那么就不再切分而返回if len(set(dataSet[:, -1].T.tolist()[0])) == 1 :return None, leafType(dataSet)# 當前數據集的大小m,n = shape(dataSet)# 當前數據集的誤差S = errType(dataSet)bestS = inf; bestIndex = 0; bestValue = 0for featIndex in range(n-1) : # for splitVal in set(dataSet[:, featIndex]) :for splitVal in set(dataSet[:,featIndex].T.tolist()[0]):mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN) : continuenewS = errType(mat0) + errType(mat1)if newS < bestS :bestIndex = featIndexbestValue = splitValbestS = newS# 如果切分數據集后效果提升不夠大,那么就不應該進行切分操作而直接創(chuàng)建葉節(jié)點if (S - bestS) < tolS :return None, leafType(dataSet)mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)# 檢查切分后的子集大小,如果某個子集的大小小于用戶定義的參數tolN,那么也不應切分。if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN) :return None, leafType(dataSet)# 如果前面的這些終止條件都不滿足,那么就返回切分特征和特征值。return bestIndex, bestValue

通過降低決策樹的復雜度來避免過擬合的過程叫剪枝,預剪枝和后剪枝的單個效果可能是不好的,一般來說,我們可以同時采用這兩種剪枝方法。

模型樹:

理解:模型樹和回歸樹的區(qū)別就是回歸樹的葉節(jié)點是一個常數值,而模型樹的葉節(jié)點是分段線性函數,分段線性模型就是我們對數據集的一部分數據以某個線性模型建模,而另一份數據以另一個線性模型建模。

#模型樹 # 主要功能:將數據格式化成目標變量Y和自變量X。X、Y用于執(zhí)行簡單的線性規(guī)劃。 def linearSolve(dataSet) :m,n = shape(dataSet) X = mat(ones((m,n))); Y = mat(ones((m,1)))X[:, 1:n] = dataSet[:, 0:n-1]; Y = dataSet[:, -1]xTx = X.T*X# 矩陣的逆不存在時會造成程序異常if linalg.det(xTx) == 0.0 :raise NameError('This matrix is singular, cannot do inverse, \n try increasing the second value of ops')ws = xTx.I * (X.T * Y)return ws, X, Y# 與regLeaf()類似,當數據不需要切分時,它負責生成葉節(jié)點的模型。 def modelLeaf(dataSet) :ws, X, Y = linearSolve(dataSet)return ws# 在給定的數據集上計算誤差。與regErr()類似,會被chooseBestSplit()調用來找到最佳切分。 def modelErr(dataSet) :ws, X, Y = linearSolve(dataSet)yHat = X * wsreturn sum(power(Y-yHat, 2))# 為了和modeTreeEval()保持一致,保留兩個輸入參數 def regTreeEval(model, inDat) :return float(model)# 對輸入數據進行格式化處理,在原數據矩陣上增加第0列,元素的值都是1 def modelTreeEval(model, inDat) :n = shape(inDat)[1]X = mat(ones((1, n+1)))X[:, 1:n+1] = inDatreturn float(X*model)def isTree(obj): return (type(obj).__name__=='dict') # 在給定樹結構的情況下,對于單個數據點,該函數會給出一個預測值。 # modeEval是對葉節(jié)點進行預測的函數引用,指定樹的類型,以便在葉節(jié)點上調用合適的模型。 # 此函數自頂向下遍歷整棵樹,直到命中葉節(jié)點為止,一旦到達葉節(jié)點,它就會在輸入數據上 # 調用modelEval()函數,該函數的默認值為regTreeEval() def treeForeCast(tree, inData, modelEval=regTreeEval) :if not isTree(tree) : return modelEval(tree, inData)if inData[tree['spInd']] > tree['spVal'] :if isTree(tree['left']) :return treeForeCast(tree['left'], inData, modelEval)else : return modelEval(tree['left'], inData)else :if isTree(tree['right']) :return treeForeCast(tree['right'], inData, modelEval)else :return modelEval(tree['right'], inData)# 多次調用treeForeCast()函數,以向量形式返回預測值,在整個測試集進行預測非常有用 def createForeCast(tree, testData, modelEval=regTreeEval) :m = len(testData)yHat = mat(zeros((m,1)))for i in range(m) :yHat[i,0] = treeForeCast(tree, mat(testData[i]), modelEval)return yHat

使用Tkinter工具構建圖形用戶界面:

from numpy import * from tkinter import * import regTrees as regTreesimport matplotlib matplotlib.use('TkAgg') #設置后端TkAgg #將TkAgg和matplotlib鏈接起來 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure# def reDraw(tolS, tolN) :reDraw.f.clf() #清空之前的圖像reDraw.a = reDraw.f.add_subplot(111) #重新添加新圖if chkBtnVar.get() : #檢查選框model tree是否被選中if tolN < 2 : tolN = 2myTree = regTrees.createTree(reDraw.rawDat, regTrees.modelLeaf, regTrees.modelErr, (tolS, tolN))yHat = regTrees.createForeCast(myTree, reDraw.testDat, regTrees.modelTreeEval)else :myTree = regTrees.createTree(reDraw.rawDat, ops=(tolS, tolN))yHat = regTrees.createForeCast(myTree, reDraw.testDat)# reDraw.rawDat[:,0].A,需要將矩陣轉換成數組reDraw.a.scatter(reDraw.rawDat[:,0].A, reDraw.rawDat[:,1].A, s=5) # 繪制真實值reDraw.a.plot(reDraw.testDat, yHat, linewidth=2.0) # 繪制預測值reDraw.canvas.show()# def getInputs() :#獲取輸入try : tolN = int(tolNentry.get()) #期望輸入是整數except : #清楚錯誤用默認值替換tolN = 10print ("enter Integer for tolN")tolNentry.delete(0, END)tolNentry.insert(0, '10')try : tolS = float(tolSentry.get())except : #期望輸入是浮點數tolS = 1.0print ("enter Float for tolS")tolSentry.delete(0, END)tolSentry.insert(0, '1.0')return tolN, tolS# def drawNewTree() :# 取得輸入框的值tolN, tolS = getInputs() # 從輸入文本框中獲取參數# 利用tolN,tolS,調用reDraw生成漂亮的圖reDraw(tolS, tolN) #繪制圖#布局GUI root = Tk() # 創(chuàng)建畫布 Label(root, text='Plot Place Holder').grid(row=0, columnspan=3)Label(root, text='tolN').grid(row=1, column=0) tolNentry = Entry(root) tolNentry.grid(row=1, column=1) tolNentry.insert(0, '10') Label(root, text='tolS').grid(row=2, column=0) tolSentry = Entry(root) tolSentry.grid(row=2, column=1) tolSentry.insert(0, '1.0') # 點擊“ReDraw”按鈕后,調用drawNewTree()函數 Button(root, text='ReDraw', command=drawNewTree).grid(row=1, column=2, rowspan=3)chkBtnVar = IntVar() chkBtn = Checkbutton(root, text='Model Tree', variable=chkBtnVar) chkBtn.grid(row=3, column=0, columnspan=2)reDraw.f = Figure(figsize=(5,4), dpi=100) reDraw.canvas = FigureCanvasTkAgg(reDraw.f, master=root) reDraw.canvas.show() reDraw.canvas.get_tk_widget().grid(row=0, columnspan=3)reDraw.rawDat = mat(regTrees.loadDataSet('ex00.txt')) reDraw.testDat = arange(min(reDraw.rawDat[:, 0]), max(reDraw.rawDat[:, 0]), 0.01)reDraw(1.0, 10)root.mainloop()

總結

以上是生活随笔為你收集整理的决策树——CART和模型树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。