六昼蛀、Sklearn之使用決策樹預(yù)測隱形眼睛類型
1雀瓢、實戰(zhàn)背景
進(jìn)入本文的正題:眼科醫(yī)生是如何判斷患者需要佩戴隱形眼鏡的類型的梅掠?一旦理解了決策樹的工作原理种玛,我們甚至也可以幫助人們判斷需要佩戴的鏡片類型。
隱形眼鏡數(shù)據(jù)集是非常著名的數(shù)據(jù)集瓤檐,它包含很多換著眼部狀態(tài)的觀察條件以及醫(yī)生推薦的隱形眼鏡類型赂韵。隱形眼鏡類型包括硬材質(zhì)(hard)、軟材質(zhì)(soft)以及不適合佩戴隱形眼鏡(no lenses)挠蛉。數(shù)據(jù)來源與UCI數(shù)據(jù)庫祭示,數(shù)據(jù)集下載地址:https://github.com/Jack-Cherish/Machine-Learning/blob/master/Decision%20Tree/classifierStorage.txt
一共有24組數(shù)據(jù),數(shù)據(jù)的Labels依次是age谴古、prescript质涛、astigmatic、tearRate掰担、class汇陆,也就是第一列是年齡,第二列是癥狀带饱,第三列是是否散光毡代,第四列是眼淚數(shù)量阅羹,第五列是最終的分類標(biāo)簽。數(shù)據(jù)如下圖所示:
可以使用已經(jīng)寫好的Python程序構(gòu)建決策樹教寂,不過出于繼續(xù)學(xué)習(xí)的目的捏鱼,本文使用Sklearn實現(xiàn)。
2酪耕、使用Sklearn構(gòu)建決策樹
官方英文文檔地址:http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html
sklearn.tree模塊提供了決策樹模型导梆,用于解決分類問題和回歸問題。方法如下圖所示:
本次實戰(zhàn)內(nèi)容使用的是DecisionTreeClassifier和export_graphviz迂烁,前者用于決策樹構(gòu)建看尼,后者用于決策樹可視化。
DecisionTreeClassifier構(gòu)建決策樹:
讓我們先看下DecisionTreeClassifier這個函數(shù)盟步,一共有12個參數(shù):
參數(shù)說明如下:
criterion:特征選擇標(biāo)準(zhǔn)狡忙,可選參數(shù),默認(rèn)是gini址芯,可以設(shè)置為entropy灾茁。gini是基尼不純度,是將來自集合的某種結(jié)果隨機(jī)應(yīng)用于某一數(shù)據(jù)項的預(yù)期誤差率谷炸,是一種基于統(tǒng)計的思想北专。entropy是香農(nóng)熵,也就是上篇文章講過的內(nèi)容旬陡,是一種基于信息論的思想拓颓。Sklearn把gini設(shè)為默認(rèn)參數(shù),應(yīng)該也是做了相應(yīng)的斟酌的描孟,精度也許更高些驶睦?ID3算法使用的是entropy,CART算法使用的則是gini匿醒。
splitter:特征劃分點(diǎn)選擇標(biāo)準(zhǔn)场航,可選參數(shù),默認(rèn)是best廉羔,可以設(shè)置為random溉痢。每個結(jié)點(diǎn)的選擇策略。best參數(shù)是根據(jù)算法選擇最佳的切分特征憋他,例如gini孩饼、entropy。random隨機(jī)的在部分劃分點(diǎn)中找局部最優(yōu)的劃分點(diǎn)竹挡。默認(rèn)的"best"適合樣本量不大的時候镀娶,而如果樣本數(shù)據(jù)量非常大,此時決策樹構(gòu)建推薦"random"揪罕。
max_features:劃分時考慮的最大特征數(shù)梯码,可選參數(shù)宝泵,默認(rèn)是None。尋找最佳切分時考慮的最大特征數(shù)(n_features為總共的特征數(shù))忍些,有如下6種情況:
如果max_features是整型的數(shù)鲁猩,則考慮max_features個特征坎怪;
如果max_features是浮點(diǎn)型的數(shù)罢坝,則考慮int(max_features * n_features)個特征;
如果max_features設(shè)為auto搅窿,那么max_features = sqrt(n_features)嘁酿;
如果max_features設(shè)為sqrt,那么max_featrues = sqrt(n_features)男应,跟auto一樣闹司;
如果max_features設(shè)為log2,那么max_features = log2(n_features)沐飘;
如果max_features設(shè)為None游桩,那么max_features = n_features,也就是所有特征都用耐朴。
一般來說借卧,如果樣本特征數(shù)不多,比如小于50筛峭,我們用默認(rèn)的"None"就可以了铐刘,如果特征數(shù)非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特征數(shù)影晓,以控制決策樹的生成時間镰吵。
max_depth:決策樹最大深,可選參數(shù)挂签,默認(rèn)是None疤祭。這個參數(shù)是這是樹的層數(shù)的。層數(shù)的概念就是饵婆,比如在貸款的例子中画株,決策樹的層數(shù)是2層。如果這個參數(shù)設(shè)置為None啦辐,那么決策樹在建立子樹的時候不會限制子樹的深度谓传。一般來說,數(shù)據(jù)少或者特征少的時候可以不管這個值芹关⌒或者如果設(shè)置了min_samples_slipt參數(shù),那么直到少于min_smaples_split個樣本為止侥衬。如果模型樣本量多诗祸,特征也多的情況下跑芳,推薦限制這個最大深度,具體的取值取決于數(shù)據(jù)的分布直颅。常用的可以取值10-100之間博个。
min_samples_split:內(nèi)部節(jié)點(diǎn)再劃分所需最小樣本數(shù),可選參數(shù)功偿,默認(rèn)是2盆佣。這個值限制了子樹繼續(xù)劃分的條件。如果min_samples_split為整數(shù)械荷,那么在切分內(nèi)部結(jié)點(diǎn)的時候共耍,min_samples_split作為最小的樣本數(shù),也就是說吨瞎,如果樣本已經(jīng)少于min_samples_split個樣本痹兜,則停止繼續(xù)切分。如果min_samples_split為浮點(diǎn)數(shù)颤诀,那么min_samples_split就是一個百分比字旭,ceil(min_samples_split * n_samples),數(shù)是向上取整的崖叫。如果樣本量不大遗淳,不需要管這個值。如果樣本量數(shù)量級非常大归露,則推薦增大這個值洲脂。
min_samples_leaf:葉子節(jié)點(diǎn)最少樣本數(shù),可選參數(shù)剧包,默認(rèn)是1恐锦。這個值限制了葉子節(jié)點(diǎn)最少的樣本數(shù),如果某葉子節(jié)點(diǎn)數(shù)目小于樣本數(shù)疆液,則會和兄弟節(jié)點(diǎn)一起被剪枝一铅。葉結(jié)點(diǎn)需要最少的樣本數(shù),也就是最后到葉結(jié)點(diǎn)堕油,需要多少個樣本才能算一個葉結(jié)點(diǎn)潘飘。如果設(shè)置為1,哪怕這個類別只有1個樣本掉缺,決策樹也會構(gòu)建出來卜录。如果min_samples_leaf是整數(shù),那么min_samples_leaf作為最小的樣本數(shù)眶明。如果是浮點(diǎn)數(shù)艰毒,那么min_samples_leaf就是一個百分比,同上搜囱,celi(min_samples_leaf * n_samples)丑瞧,數(shù)是向上取整的柑土。如果樣本量不大,不需要管這個值绊汹。如果樣本量數(shù)量級非常大稽屏,則推薦增大這個值。
min_weight_fraction_leaf:葉子節(jié)點(diǎn)最小的樣本權(quán)重和西乖,可選參數(shù)狐榔,默認(rèn)是0。這個值限制了葉子節(jié)點(diǎn)所有樣本權(quán)重和的最小值浴栽,如果小于這個值荒叼,則會和兄弟節(jié)點(diǎn)一起被剪枝轿偎。一般來說典鸡,如果我們有較多樣本有缺失值,或者分類樹樣本的分布類別偏差很大坏晦,就會引入樣本權(quán)重萝玷,這時我們就要注意這個值了。
max_leaf_nodes:最大葉子節(jié)點(diǎn)數(shù)昆婿,可選參數(shù)球碉,默認(rèn)是None。通過限制最大葉子節(jié)點(diǎn)數(shù)仓蛆,可以防止過擬合睁冬。如果加了限制,算法會建立在最大葉子節(jié)點(diǎn)數(shù)內(nèi)最優(yōu)的決策樹看疙。如果特征不多豆拨,可以不考慮這個值,但是如果特征分成多的話能庆,可以加以限制施禾,具體的值可以通過交叉驗證得到。
class_weight:類別權(quán)重搁胆,可選參數(shù)弥搞,默認(rèn)是None,也可以字典渠旁、字典列表攀例、balanced。指定樣本各類別的的權(quán)重顾腊,主要是為了防止訓(xùn)練集某些類別的樣本過多粤铭,導(dǎo)致訓(xùn)練的決策樹過于偏向這些類別。類別的權(quán)重可以通過{class_label:weight}這樣的格式給出投慈,這里可以自己指定各個樣本的權(quán)重承耿,或者用balanced冠骄,如果使用balanced,則算法會自己計算權(quán)重加袋,樣本量少的類別所對應(yīng)的樣本權(quán)重會高凛辣。當(dāng)然,如果你的樣本類別分布沒有明顯的偏倚职烧,則可以不管這個參數(shù)扁誓,選擇默認(rèn)的None。
random_state:可選參數(shù)蚀之,默認(rèn)是None蝗敢。隨機(jī)數(shù)種子。如果是證書足删,那么random_state會作為隨機(jī)數(shù)生成器的隨機(jī)數(shù)種子寿谴。隨機(jī)數(shù)種子,如果沒有設(shè)置隨機(jī)數(shù)失受,隨機(jī)出來的數(shù)與當(dāng)前系統(tǒng)時間有關(guān)讶泰,每個時刻都是不同的。如果設(shè)置了隨機(jī)數(shù)種子拂到,那么相同隨機(jī)數(shù)種子痪署,不同時刻產(chǎn)生的隨機(jī)數(shù)也是相同的。如果是RandomState instance兄旬,那么random_state是隨機(jī)數(shù)生成器狼犯。如果為None,則隨機(jī)數(shù)生成器使用np.random领铐。
min_impurity_split:節(jié)點(diǎn)劃分最小不純度,可選參數(shù)悯森,默認(rèn)是1e-7。這是個閾值罐孝,這個值限制了決策樹的增長呐馆,如果某節(jié)點(diǎn)的不純度(基尼系數(shù),信息增益莲兢,均方差汹来,絕對差)小于這個閾值,則該節(jié)點(diǎn)不再生成子節(jié)點(diǎn)改艇。即為葉子節(jié)點(diǎn) 收班。
presort:數(shù)據(jù)是否預(yù)排序,可選參數(shù)谒兄,默認(rèn)為False摔桦,這個值是布爾值,默認(rèn)是False不排序。一般來說邻耕,如果樣本量少或者限制了一個深度很小的決策樹鸥咖,設(shè)置為true可以讓劃分點(diǎn)選擇更加快,決策樹建立的更加快兄世。如果樣本量太大的話啼辣,反而沒有什么好處。問題是樣本量少的時候御滩,我速度本來就不慢鸥拧。所以這個值一般懶得理它就可以了。
除了這些參數(shù)要注意以外削解,其他在調(diào)參時的注意點(diǎn)有:
當(dāng)樣本數(shù)量少但是樣本特征非常多的時候富弦,決策樹很容易過擬合,一般來說氛驮,樣本數(shù)比特征數(shù)多一些會比較容易建立健壯的模型
如果樣本數(shù)量少但是樣本特征非常多腕柜,在擬合決策樹模型前,推薦先做維度規(guī)約柳爽,比如主成分分析(PCA)媳握,特征選擇(Losso)或者獨(dú)立成分分析(ICA)碱屁。這樣特征的維度會大大減小磷脯。再來擬合決策樹模型效果會好。
推薦多用決策樹的可視化娩脾,同時先限制決策樹的深度赵誓,這樣可以先觀察下生成的決策樹里數(shù)據(jù)的初步擬合情況,然后再決定是否要增加深度柿赊。
在訓(xùn)練模型時俩功,注意觀察樣本的類別情況(主要指分類樹),如果類別分布非常不均勻碰声,就要考慮用class_weight來限制模型過于偏向樣本多的類別诡蜓。
決策樹的數(shù)組使用的是numpy的float32類型,如果訓(xùn)練數(shù)據(jù)不是這樣的格式胰挑,算法會先做copy再運(yùn)行蔓罚。
如果輸入的樣本矩陣是稀疏的,推薦在擬合前調(diào)用csc_matrix稀疏化瞻颂,在預(yù)測前調(diào)用csr_matrix稀疏化豺谈。
sklearn.tree.DecisionTreeClassifier()提供了一些方法供我們使用,如下圖所示:
了解到這些贡这,我們就可以編寫代碼了茬末。
# -*- coding: UTF-8 -*-
from sklearn import tree
if __name__ == '__main__':
? ? fr = open('lenses.txt')
? ? lenses = [inst.strip().split('\t') for inst in fr.readlines()]
? ? print(lenses)
? ? lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
? ? clf = tree.DecisionTreeClassifier()
? ? lenses = clf.fit(lenses, lensesLabels)
運(yùn)行代碼,會得到如下結(jié)果:
我們可以看到程序報錯了盖矫,這是為什么丽惭?因為在fit()函數(shù)不能接收string類型的數(shù)據(jù)击奶,通過打印的信息可以看到,數(shù)據(jù)都是string類型的责掏。在使用fit()函數(shù)之前正歼,我們需要對數(shù)據(jù)集進(jìn)行編碼,這里可以使用兩種方法:
LabelEncoder :將字符串轉(zhuǎn)換為增量值
OneHotEncoder:使用One-of-K算法將字符串轉(zhuǎn)換為整數(shù)
為了對string類型的數(shù)據(jù)序列化拷橘,需要先生成pandas數(shù)據(jù)局义,這樣方便我們的序列化工作。這里我使用的方法是冗疮,原始數(shù)據(jù)->字典->pandas數(shù)據(jù)萄唇,編寫代碼如下:
# -*- coding: UTF-8 -*-
import pandas as pd
if __name__ == '__main__':
? ? with open('lenses.txt', 'r') as fr:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #加載文件
? ? ? ? lenses = [inst.strip().split('\t') for inst in fr.readlines()]? ? ? ? #處理文件
? ? lenses_target = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取每組數(shù)據(jù)的類別,保存在列表里
? ? for each in lenses:
? ? ? ? lenses_target.append(each[-1])
? ? lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']? ? ? ? ? ? #特征標(biāo)簽? ? ?
? ? lenses_list = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的臨時列表
? ? lenses_dict = {}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的字典术幔,用于生成pandas
? ? for each_label in lensesLabels:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取信息另萤,生成字典
? ? ? ? for each in lenses:
? ? ? ? ? ? lenses_list.append(each[lensesLabels.index(each_label)])
? ? ? ? lenses_dict[each_label] = lenses_list
? ? ? ? lenses_list = []
? ? print(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印字典信息
? ? lenses_pd = pd.DataFrame(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #生成pandas.DataFrame
? ? print(lenses_pd)
從運(yùn)行結(jié)果可以看出,順利生成pandas數(shù)據(jù)诅挑。
接下來四敞,將數(shù)據(jù)序列化,編寫代碼如下:
# -*- coding: UTF-8 -*-
import pandas as pd
from sklearn.preprocessing import LabelEncoder
import pydotplus
from sklearn.externals.six import StringIO
if __name__ == '__main__':
? ? with open('lenses.txt', 'r') as fr:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #加載文件
? ? ? ? lenses = [inst.strip().split('\t') for inst in fr.readlines()]? ? ? ? #處理文件
? ? lenses_target = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取每組數(shù)據(jù)的類別拔妥,保存在列表里
? ? for each in lenses:
? ? ? ? lenses_target.append(each[-1])
? ? lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']? ? ? ? ? ? #特征標(biāo)簽? ? ?
? ? lenses_list = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的臨時列表
? ? lenses_dict = {}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的字典忿危,用于生成pandas
? ? for each_label in lensesLabels:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取信息,生成字典
? ? ? ? for each in lenses:
? ? ? ? ? ? lenses_list.append(each[lensesLabels.index(each_label)])
? ? ? ? lenses_dict[each_label] = lenses_list
? ? ? ? lenses_list = []
? ? # print(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印字典信息
? ? lenses_pd = pd.DataFrame(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #生成pandas.DataFrame
? ? print(lenses_pd)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印pandas.DataFrame
? ? le = LabelEncoder()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建LabelEncoder()對象没龙,用于序列化? ? ? ? ? ?
? ? for col in lenses_pd.columns:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #為每一列序列化
? ? ? ? lenses_pd[col] = le.fit_transform(lenses_pd[col])
? ? print(lenses_pd)
從打印結(jié)果可以看到铺厨,我們已經(jīng)將數(shù)據(jù)順利序列化,接下來硬纤。我們就可以fit()數(shù)據(jù)解滓,構(gòu)建決策樹了。
3筝家、使用Graphviz可視化決策樹
Graphviz的是AT&T Labs Research開發(fā)的圖形繪制工具洼裤,他可以很方便的用來繪制結(jié)構(gòu)化的圖形網(wǎng)絡(luò),支持多種格式輸出溪王,生成圖片的質(zhì)量和速度都不錯腮鞍。它的輸入是一個用dot語言編寫的繪圖腳本,通過對輸入腳本的解析在扰,分析出其中的點(diǎn)缕减,邊以及子圖,然后根據(jù)屬性進(jìn)行繪制芒珠。是使用Sklearn生成的決策樹就是dot格式的桥狡,因此我們可以直接利用Graphviz將決策樹可視化。
在講解編寫代碼之前,我們需要安裝兩樣?xùn)|西裹芝,即pydotplus和Grphviz部逮。
(1)安裝Pydotplus
pydotplus可以在CMD窗口中,直接使用指令安裝:
pip3 install pydotplus
2)安裝Graphviz
Graphviz不能使用pip進(jìn)行安裝嫂易,我們需要手動安裝兄朋,下載地址:https://www.graphviz.org
找到相應(yīng)的版本進(jìn)行安裝即可,不過這個網(wǎng)站的下載速度感人怜械,每秒10k的速度也是沒誰了颅和。因此我已經(jīng)將Graphviz for Windows的版本下載好了,供各位直接下載缕允,這樣速度很快峡扩,節(jié)省各位的時間(密碼:ja9n):下載地址
下載好安裝包,進(jìn)行安裝障本,安裝完畢之后教届,需要設(shè)置Graphviz的環(huán)境變量。
首先驾霜,按快捷鍵win+r案训,在出現(xiàn)的運(yùn)行對話框中輸入sysdm.cpl,點(diǎn)擊確定粪糙,出現(xiàn)如下對話框:
選擇高級->環(huán)境變量强霎。在系統(tǒng)變量的Path變量中,添加Graphviz的環(huán)境變量猜旬,比如Graphviz安裝在了D盤的根目錄脆栋,則添加:D:\Graphviz\bin;
添加好環(huán)境變量之后,我們就可以正常使用Graphviz了洒擦。
(3)編寫代碼
Talk is Cheap, show me the code.(廢話少說,放碼過來)怕膛∈炷郏可視化部分的代碼不難,都是有套路的褐捻,直接填參數(shù)就好掸茅,詳細(xì)內(nèi)容可以查看官方教程:http://scikit-learn.org/stable/modules/tree.html#tree
# -*- coding: UTF-8 -*-
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.externals.six import StringIO
from sklearn import tree
import pandas as pd
import numpy as np
import pydotplus
if __name__ == '__main__':
? ? with open('lenses.txt', 'r') as fr:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #加載文件
? ? ? ? lenses = [inst.strip().split('\t') for inst in fr.readlines()]? ? ? ? #處理文件
? ? lenses_target = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取每組數(shù)據(jù)的類別,保存在列表里
? ? for each in lenses:
? ? ? ? lenses_target.append(each[-1])
? ? print(lenses_target)
? ? lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']? ? ? ? ? ? #特征標(biāo)簽? ? ?
? ? lenses_list = []? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的臨時列表
? ? lenses_dict = {}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存lenses數(shù)據(jù)的字典柠逞,用于生成pandas
? ? for each_label in lensesLabels:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #提取信息昧狮,生成字典
? ? ? ? for each in lenses:
? ? ? ? ? ? lenses_list.append(each[lensesLabels.index(each_label)])
? ? ? ? lenses_dict[each_label] = lenses_list
? ? ? ? lenses_list = []
? ? # print(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印字典信息
? ? lenses_pd = pd.DataFrame(lenses_dict)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #生成pandas.DataFrame
? ? # print(lenses_pd)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印pandas.DataFrame
? ? le = LabelEncoder()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建LabelEncoder()對象,用于序列化? ? ? ? ?
? ? for col in lenses_pd.columns:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #序列化
? ? ? ? lenses_pd[col] = le.fit_transform(lenses_pd[col])
? ? # print(lenses_pd)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #打印編碼信息
? ? clf = tree.DecisionTreeClassifier(max_depth = 4)? ? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建DecisionTreeClassifier()類
? ? clf = clf.fit(lenses_pd.values.tolist(), lenses_target)? ? ? ? ? ? ? ? ? ? #使用數(shù)據(jù)板壮,構(gòu)建決策樹
? ? dot_data = StringIO()
? ? tree.export_graphviz(clf, out_file = dot_data,? ? ? ? ? ? ? ? ? ? ? ? ? ? #繪制決策樹
? ? ? ? ? ? ? ? ? ? ? ? feature_names = lenses_pd.keys(),
? ? ? ? ? ? ? ? ? ? ? ? class_names = clf.classes_,
? ? ? ? ? ? ? ? ? ? ? ? filled=True, rounded=True,
? ? ? ? ? ? ? ? ? ? ? ? special_characters=True)
? ? graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
? ? graph.write_pdf("tree.pdf")? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #保存繪制好的決策樹逗鸣,以PDF的形式存儲。
運(yùn)行代碼,在該python文件保存的相同目錄下撒璧,會生成一個名為tree的PDF文件透葛,打開文件,我們就可以看到?jīng)Q策樹的可視化效果圖了卿樱。
確定好決策樹之后僚害,我們就可以做預(yù)測了》钡鳎可以根據(jù)自己的眼睛情況和年齡等特征萨蚕,看一看自己適合何種材質(zhì)的隱形眼鏡。使用如下代碼就可以看到預(yù)測結(jié)果:
print(clf.predict([[1,1,1,0]]))? ? ? ? ? ? ? ? ? ? #預(yù)測
代碼簡單蹄胰,官方手冊都有门岔,就不全貼出來了。
本來是想繼續(xù)討論決策樹的過擬合問題烤送,但是看到《機(jī)器學(xué)習(xí)實戰(zhàn)》將此部分內(nèi)容放到了第九章寒随,那我也放在后面好了。
七帮坚、總結(jié)
決策樹的一些優(yōu)點(diǎn):
易于理解和解釋妻往。決策樹可以可視化。
幾乎不需要數(shù)據(jù)預(yù)處理试和。其他方法經(jīng)常需要數(shù)據(jù)標(biāo)準(zhǔn)化讯泣,創(chuàng)建虛擬變量和刪除缺失值。決策樹還不支持缺失值阅悍。
使用樹的花費(fèi)(例如預(yù)測數(shù)據(jù))是訓(xùn)練數(shù)據(jù)點(diǎn)(data points)數(shù)量的對數(shù)好渠。
可以同時處理數(shù)值變量和分類變量。其他方法大都適用于分析一種變量的集合节视。
可以處理多值輸出變量問題拳锚。
使用白盒模型。如果一個情況被觀察到寻行,使用邏輯判斷容易表示這種規(guī)則霍掺。相反,如果是黑盒模型(例如人工神經(jīng)網(wǎng)絡(luò))拌蜘,結(jié)果會非常難解釋杆烁。
即使對真實模型來說,假設(shè)無效的情況下简卧,也可以較好的適用兔魂。
決策樹的一些缺點(diǎn):
決策樹學(xué)習(xí)可能創(chuàng)建一個過于復(fù)雜的樹,并不能很好的預(yù)測數(shù)據(jù)举娩。也就是過擬合析校。修剪機(jī)制(現(xiàn)在不支持)构罗,設(shè)置一個葉子節(jié)點(diǎn)需要的最小樣本數(shù)量,或者數(shù)的最大深度勺良,可以避免過擬合绰播。
決策樹可能是不穩(wěn)定的,因為即使非常小的變異尚困,可能會產(chǎn)生一顆完全不同的樹蠢箩。這個問題通過decision trees with an ensemble來緩解。
概念難以學(xué)習(xí)事甜,因為決策樹沒有很好的解釋他們谬泌,例如,XOR, parity or multiplexer problems逻谦。
如果某些分類占優(yōu)勢掌实,決策樹將會創(chuàng)建一棵有偏差的樹。因此邦马,建議在訓(xùn)練之前贱鼻,先抽樣使樣本均衡。免費(fèi)視頻教程:www.mlxs.top? ??