乙隻菜雞的決策樹入門(三)

2021-08-22 16:13:24 字數 3934 閱讀 9767

畫樹完成之後,發現資料形式的樹很難直觀的看出其中的分類決策,尤其當參與分類的特徵較多的情況下。個人工作是做信貸風控決策,碰到的特徵變數數不勝數,簡直頭疼,書上選用matplotlib庫的註解功能嘗試繪製屬性圖,這個庫之前入門python的時候就了解過,引數實在是太多,比較煩,用來試試。

以文字註解的形式繪製樹的節點:

from matplotlib import pyplot as plt

# 節點和箭頭的樣式確定一下

decisionnode = dict(boxstyle='sawtooth',fc='0.8')

leafnode = dict(boxstyle='round4',fc='0.8')

arrow_args = dict(arrowstyle='<-')

# 繪製節點函式

def plotnode(nodetext,cntrpt,parentpt,nodetype):

# ax1為createplot屬性,呼叫函式annotate()繪製節點

createplot.ax1.annotate(nodetext,xy=parentpt,xycoords='axes fraction',

xytext=cntrpt,textcoords='axes fraction',

va='center',ha='center',bbox=nodetype,

arrowprops=arrow_args)

# 繪製一下節點試試

def createplot():

fig = plt.figure(1,facecolor='white')

fig.clf() # 清空繪圖區

# 全域性變數createplot.ax1定義繪圖區域(變數預設均為全域性有效)

createplot.ax1 = plt.subplot(111,frameon=false) # 去除錶框軸

plotnode('決策節點',(0.5,0.8),(0.1,0.5),decisionnode)

plotnode('葉節點',(0.8,0.1),(0.3,0.8),leafnode)

plt.show()

然後遞迴函式計算葉子結點數量以及樹的層數:

# 計算葉子結點數量

def calcleafs(mytree):

numofleafs = 0

firststr = list(mytree.keys())[0]

seconddict = mytree[firststr]

for key in seconddict.keys():

if type(seconddict[key]).__name__ == 'dict':

numofleafs += calcleafs(seconddict[key])

else:

numofleafs += 1

return numofleafs

# 計算樹的層數(經過幾次特徵劃分)

def calcdepth(mytree):

numofdepth = 0

firststr = list(mytree.keys())[0]

seconddict = mytree[firststr]

for key in seconddict.keys():

if type(seconddict[key]).__name__ == 'dict':

thisdepth = 1 + calcdepth(seconddict[key])

else:

thsidepth = 1

if thisdepth > numofdepth:

numofdepth = thisdepth

return numofdepth

為最後繪製工作增加繪製父子節點間文字的部分:

def plotmidtext(cntrpt,parentpt,textstring):

xmid = (parentpt[0] - cntrpt[0]) / 2.0 + cntrpt[0]

ymid = (parentpt[1] - cntrpt[1]) / 2.0 + cntrpt[1]

createplot.ax1.text(xmid,ymid,textstring)

createplot才是真正的大哥,我們的主函式,其他都是小弟,其中的還有乙個小弟是負責畫樹的,把前面的小弟集合一下:

def plottree(mytree,parentpt,nodetxt):

numleafs = calcleafs(mytree)

depth = calcdepth(mytree)

firststr = list(mytree.keys())[0]

seconddict = mytree[firststr]

# 當前繪製的節點座標(x軸按照該層葉子結點數量均分,當前座標為中點)

cntrpt = (plottree.xoff + (1.0 + float(numleafs) / 2.0 / plottree.totalw,

plottree.yoff)

# 繪製第一層,當前分類的節點

plotmidtext(cntrpt,parentpt,nodetxt)

plotnode(firststr,cntrpt,parentpt,decisionnode)

# y軸按照層數depth均分,每層繪製完則遞減

plottree.yoff = plottree.yoff - 1.0 / plottree.totald

for key in seconddict.keys():

if type(seconddict[key]).__name__ == 'dict':

plottree(seconddict[key],cntrpt,str(key))

else:

plottree.xoff = plottree.xoff + 1.0 / plottree.totalw

plotnode(seconddict[key],(plottree.xoff,plottree.yoff),cntrpt,leafnode)

plotmidtext((plottree.xoff,plottree.yoff),cntrpt,str(key))

# 校正?

plottree.yoff = plottree.yoff + 1.0 / plottree.totald

有乙個看了很久看不懂的,當前節點座標cntrpt,書中根據該層葉子節點數量均分x軸,當前結點位置位於中間float(numleafs)/2.0/plottree.totalw,在初始化plottree.xoff值的時候取-0.5/plottree.totalw(葉子結點位於x中間),即整體向左挪動了0.5個x,所以需要將以上向左偏移的0.5個x補回來,葉子結點x座標則按照每次乙個x的距離增加。圖是按照比例繪製的。

接著用createplot繪製展示:

def createplot(intree):

fig = plt.figure(1,facecolor='white')

fig.clf()

axprops = dict(xticks,yticks) # 刻度軸設定為空

createplot.ax1 = plt.subplot(111,frameon=false,**axprops)

plottree.totalw = float(calcleafs(intree))

plottree.totald = float(calcdepth(intree))

plottree.xoff = -0.5 / plottree.totalw

plottree.yoff = 1.0 # 初始值為1.0,自上而下繪製且y遞減

plottree(intree,(0.5,1.0),'')

plt.show()

乙隻菜雞的半年技術部落格之路

然而重度拖延症的我一直帶著這個想法很久也沒有付諸行動,直到今年,我才將這個事情提上日程,逼著自己多學習,多記錄,多分享,所以就這樣開始了旅途 基礎篇 sringboot篇 docker容器篇 容器集群篇 綜合技術棧篇 趣味技術篇 最終確定了現在的這個personal blog 雖然現有的部落格平台寫...

決策樹(二)關於的決策樹的一些思考

如果我可以使用邏輯回歸解決分類問題和線性回歸解決回歸問題,為什麼需要使用樹模型?我們很多人都有這個問題。實際上,你可以使用任何演算法。這取決於你要解決的問題型別。其中有一些關鍵因素,它們將幫助你決定使用哪種演算法 過度擬合是決策樹建模時面臨的主要挑戰之一。如果沒有限制,它將為您提供100 的訓練集準...

機器學習中的那些樹 決策樹 一

從零基礎開始參加了幾場資料探勘方面的比賽,每次比賽都會學到不少東西,自從上次在elo的 kernel 中看見很多人都使用lightgbm xgboost,那之後我也開始用起了這些,但是卻從未花時間去了解過這是究竟是什麼,其內部工作原理是怎麼樣的,正好這段時間在參加df平台的消費者人群畫像 信用智慧型...