畫樹完成之後,發現資料形式的樹很難直觀的看出其中的分類決策,尤其當參與分類的特徵較多的情況下。個人工作是做信貸風控決策,碰到的特徵變數數不勝數,簡直頭疼,書上選用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平台的消費者人群畫像 信用智慧型...