1 概述html
1.1 決策樹是如何工做的node
1.2 構建決策樹
1.2.1 ID3算法構建決策樹
1.2.2 簡單實例
1.2.3 ID3的侷限性
1.3 C4.5算法 & CART算法
1.3.1 修改局部最優化條件
1.3.2 連續變量處理手段python
1.4 sklearn中的決策樹算法
2 DecisionTreeClassifier與紅酒數據集數據庫
2.1 重要參數數組
2.1.1 criterion網絡
2.1.2 random_state & splitterapp
2.1.3 剪枝參數dom
2.1.4 目標權重參數機器學習
2.2 重要屬性和接口
3 DecisionTreeRegressor
3.1 重要參數,屬性及接口
criterion
3.2 實例:一維迴歸的圖像繪製
4 實例:泰坦尼克號倖存者的預測
5 決策樹的優缺點
6 附錄
6.1 分類樹參數列表
6.2 分類樹屬性列表
6.3 分類樹接口列表
Bonus Chapter I 實例:分類樹在合成數集上的表現
決策樹(Decision Tree)是一種非參數的有監督學習方法,它可以從一系列有特徵和標籤的數據中總結出決策規則,並用樹狀圖的結構來呈現這些規則,以解決分類和迴歸問題。決策樹算法容易理解,適用各類數據,在解決各類問題時都有良好表現,尤爲是以樹模型爲核心的各類集成算法,在各個行業和領域都有普遍的應用。
咱們來簡單瞭解一下決策樹是如何工做的。決策樹算法的本質是一種圖結構,咱們只須要問一系列問題就能夠對數據進行分類了。好比說,來看看下面這組數據集,這是一系列已知物種以及所屬類別的數據:
咱們如今的目標是,將動物們分爲哺乳類和非哺乳類。那根據已經收集到的數據,決策樹算法爲咱們算出了下面的這棵決策樹:
假如咱們如今發現了一種新物種Python,它是冷血動物,體表帶鱗片,而且不是胎生,咱們就能夠經過這棵決策樹來判斷它的所屬類別。
能夠看出,在這個決策過程當中,咱們一直在對記錄的特徵進行提問。最初的問題所在的地方叫作根節點,在獲得結論前的每個問題都是中間節點,而獲得的每個結論(動物的類別)都叫作葉子節點。
關鍵概念:節點
根節點:沒有進邊,有出邊。包含最初的,針對特徵的提問。
中間節點:既有進邊也有出邊,進邊只有一條,出邊能夠有不少條。都是針對特徵的提問。
葉子節點:有進邊,沒有出邊,每一個葉子節點都是一個類別標籤。
*子節點和父節點:在兩個相連的節點中,更接近根節點的是父節點,另外一個是子節點。
決策樹算法的核心是要解決兩個問題:
1)如何從數據表中找出最佳節點和最佳分枝?
2)如何讓決策樹中止生長,防止過擬合?
幾乎全部決策樹有關的模型調整方法,都圍繞這兩個問題展開。接下來,咱們就來了解一下決策樹背後的原理。
接下來討論如何根據已有的數據集來創建有效的決策樹。原則上講,任意一個數據集上的全部特徵均可以被拿來分枝,特徵上的任意節點又能夠自由組合,因此一個數據集上能夠發展出很是很是多棵決策樹,其數量可達指數級。在這些樹中,總有那麼一棵樹比其餘的樹分類效力都好,那樣的樹叫作」全局最優樹"。
關鍵概念:全局最優,局部最優
全局最優:通過組合造成的,總體來講分類效果最好的模型;
局部最優:每一次分枝的時候都向着更好的分類效果分枝,但沒法確認如今生成的樹在全局上是不是最優的。
要在這麼多棵決策樹中去一次性找到分類效果最佳的那一棵是不可能的,若是經過排列組合來進行篩選,計算量過於大並且低效,所以咱們不會這樣作。相對的,機器學習研究者們開發了一些有效的算法,可以在合理的時間內構造出具備必定準確率的次最優決策樹。這些算法基本都執行」貪心策略",即經過局部的最優來達到咱們相信是最接近全局最優的結果。
關鍵概念:貪心算法
經過實現局部最優來達到接近全局最優結果的算法,全部的樹模型都是這樣的算法。
最典型的決策樹算法是Hunt算法,該算法是由Hunt等人提出的最先的決策樹算法。現代,Hunt算法是許多決策樹算法的基礎,包括ID三、C4.5和CART等。Hunt算法誕生時間較早,且基礎理論並不是特別完善,此處以應用較廣、理論基礎較爲完善的ID3算法的基本原理開始,討論如何利用局部最優化方法來建立決策模型。
ID3算法原型見於J.R Quinlan的博士論文,是基礎理論較爲完善,使用較爲普遍的決策樹模型,在此基礎上J.RQuinlan進行優化後,陸續推出了C4.5和C5.0決策樹算法,後兩者現已稱爲當前最流行的決策樹算法,咱們先從ID3開始講起,再討論如何從ID3逐漸優化至C4.5。
爲了要將表格轉化爲一棵樹,決策樹須要找出最佳節點和最佳的分枝方法,而衡量這個「最佳」的指標叫作「不純度」。不純度基於葉子節點來計算的,因此樹中的每一個節點都會有一個不純度,而且子節點的不純度必定是低於父節點的,也就是說,在同一棵決策樹上,葉子節點的不純度必定是最低的。
重要概念:不純度
決策樹的每一個葉子節點中都會包含一組數據,在這組數據中,若是有某一類標籤佔有較大的比例,咱們就說葉子節點「純」,分枝分得好。某一類標籤佔的比例越大,葉子就越純,不純度就越低,分枝就越好。 若是沒有哪一類標籤的比例很大,各種標籤都相對平均,則說葉子節點」不純「,分枝很差,不純度高。
這個其實很是容易理解。分類型決策樹在葉子節點上的決策規則是少數服從多數,在一個葉子節點上,若是某一類標籤所佔的比例較大,那全部進入這個葉子節點的樣本都回被認爲是這一類別。具體來講,若是90%根據規則進入葉子節點的樣本都是類別0(葉子比較純),那新進入葉子節點的測試樣本的類別也頗有多是0。可是,若是51%的樣本是0,49%的樣本是1(極端狀況),葉子節點仍是會被認爲是0類葉子節點,但此時此刻進入這個葉子的測試樣本點幾乎有一半的可能性應該是類別1。從數學上來講,類分佈爲(0,100%)的結點具備零不純性,而均衡分佈(50%,50%)的結點具備最高的不純性。若是葉子自己不純,那測試樣本就頗有可能被判斷錯誤,相對的葉子越純,那樣本被判斷錯誤的可能性就越小。
一般來講,不純度越低,決策樹對訓練集的擬合越好。如今使用的決策樹算法在分枝方法上的核心大可能是圍繞在對某個不純度相關指標的最優化上。若咱們定義 t 表明決策樹的某節點, Dt 是 t 節點所對應的數據集,設 p(i|t) 表示給定結點 t 中屬於類別 i 的樣本所佔的比例,這個比例越高,則表明葉子越純。
【練習】從下面的圖來看,哪一個不純度最高?哪一個不純度最低?
怎樣計算不純度?
對於節點不純度的計算和表示方法因決策樹模型而異,但無論不純度的度量方法如何,都是由偏差率衍生而來,其計算公式以下:
偏差率越低,則純度越高。由此還衍生出了其餘兩個經常使用指標,一個是ID3中Information gain(信息增益)的計算方法可用Entropy推導,即最爲人熟知的信息熵,又叫作香農熵,其計算公式以下:
其中c表示葉子節點上標籤類別的個數,c-1表示標籤的索引。注意在這裏,是從第0類標籤開始計算,因此最後的標籤類別應該是總共c個標籤,c-1爲最後一個標籤的索引。在計算Entropy時設定log20 = 0。
另外一個指標則是Gini(基尼)指數,主要用於CART決策樹的純度斷定中,其計算公式以下:
假設在二分類問題中各節點呈現以下分佈,則可進一步計算上述三指數的結果
可以看出,三種方法本質上都相同,在類分佈均衡時(即當p=0.5時)達到最大值,而當全部記錄都屬於同一個類時(p等於1或0)達到最小值。換而言之,在純度較高時三個指數均較低,而當純度較低時,三個指數都比較大,且能夠計算得出,嫡在0-1區間內分佈,而Gini指數和分類偏差均在0-0.5區間內分佈,三個指數隨某變量佔比增長而變化的曲線以下所示:
決策樹最終的優化目標是使得葉節點的總不純度最低,即對應衡量不純度的指標最低。
ID3採用信息熵來衡量不純度,此處就先以信息嫡爲例進行討論。ID3最優條件是葉節點的總信息熵最小,所以ID3決策樹在決定是否對某節點進行切分的時候,會盡量選取使得該節點對應的子節點信息熵最小的特徵進行切分。換而言之,就是要求父節點信息熵和子節點總信息熵之差要最大。對於ID3而言,兩者之差就是信息增益,即Information gain。
但這裏須要注意,一個父節點下可能有多個子節點,而每一個子節點又有本身的信息熵,因此父節點信息熵和子節點信息熵之差,應該是父節點的信息熵-全部子節點信息熵的加權平均。其中,權重是使用單個葉子節點上所佔的樣本量比上父節點上的總樣本量來肯定的一個權重。
而父節點和子節點的不純度降低數可由下述公式進行計算:
I(.)是給定結點的不純性度量(便是基尼係數或者信息上),N是父結點上的樣本數,k是這一層上子節點的個數,NVj)是與子結點相關聯的樣本個數。決策樹算法一般選擇最大化增益△的測試條件,由於對任何分枝過程來講,
(parent)都是一個不變的值(由於此時父節點已經存在而且不可修改),因此最大化增益等價於最小化子結點的不純性衡量的加權平均。最後,當選擇熵(entropy)做爲公式的不純性度量時,烯的差就是所謂信息增益(Information gain)△info。
接下來對此進行舉例說明。
假設如今有以下數據集,是一個消費者我的屬性和信用評分數據,標籤是「是否會發生購買電腦行爲",仍然是個而分類問題,在此數據集之上咱們使用ID3構建決策樹模型,並提取有效的分類規則。
sklearn中決策樹的類都在」tree「這個模塊之下。這個模塊總共包含五個類:
咱們會主要講解分類樹和迴歸樹,並用圖像呈現給你們。
在那以前,咱們先來了解一下sklearn建模的基本流程。
在這個流程下,分類樹對應的代碼是:
from sklearn import tree #導入須要的模塊 clf = tree.DecisionTreeClassifier() #實例化 clf = clf.fit(X_train,y_train) #用訓練集數據訓練模型 result = clf.score(X_test,y_test) #導入測試集,從接口中調用須要的信息
class sklearn.tree.DecisionTreeClassifier (criterion=’gini’, splitter=’best’, max_depth=None,min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None,class_weight=None, presort=False)
爲了要將表格轉化爲一棵樹,決策樹須要找出最佳節點和最佳的分枝方法,對分類樹來講,衡量這個「最佳」的指標叫作「不純度」。一般來講,不純度越低,決策樹對訓練集的擬合越好。如今使用的決策樹算法在分枝方法上的核心大可能是圍繞在對某個不純度相關指標的最優化上。
不純度基於節點來計算,樹中的每一個節點都會有一個不純度,而且子節點的不純度必定是低於父節點的,也就是說,在同一棵決策樹上,葉子節點的不純度必定是最低的。
Criterion這個參數正是用來決定不純度的計算方法的。sklearn提供了兩種選擇:
其中 t 表明給定的節點, i 表明標籤的任意分類, p(i|t) 表明標籤分類 i 在節點 t 上所佔的比例。注意,當使用信息熵時,sklearn實際計算的是基於信息熵的信息增益(Information Gain),即父節點的信息熵和子節點的信息熵之差。
比起基尼係數,信息熵對不純度更加敏感,對不純度的懲罰最強。可是在實際使用中,信息熵和基尼係數的效果基本相同。信息熵的計算比基尼係數緩慢一些,由於基尼係數的計算不涉及對數。另外,由於信息熵對不純度更加敏感,因此信息熵做爲指標時,決策樹的生長會更加「精細」,所以對於高維數據或者噪音不少的數據,信息熵很容易過擬合,基尼係數在這種狀況下效果每每比較好。當模型擬合程度不足的時候,即當模型在訓練集和測試集上都表現不太好的時候,使用信息熵(欠擬合狀況下使用多)。固然,這些不是絕對的。
到這裏,決策樹的基本流程其實能夠簡單歸納以下:
直到沒有更多的特徵可用,或總體的不純度指標已經最優,決策樹就會中止生長。
from sklearn import tree from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split
wine = load_wine() wine.data.shape#(178,13) wine.target #若是wine是一張表,應該長這樣: import pandas as pd pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1) wine.feature_names wine.target_names
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3) Xtrain.shape Xtest.shape
clf = tree.DecisionTreeClassifier(criterion="entropy")#實例化,criterion不寫的話默認是基尼係數 clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #返回預測的準確度 score
feature_name = ['酒精','蘋果酸','灰','灰的鹼性','鎂','總酚','類黃酮','非黃烷類酚類','花青素','顏色強度','色調','od280/od315稀釋葡萄酒','脯氨酸'] import graphviz dot_data = tree.export_graphviz(clf # ,out_file = None ,feature_names= feature_name ,class_names=["琴酒","雪莉","貝爾摩德"] ,filled=True#讓樹的每一塊有顏色,顏色越淺,表示不純度越高 ,rounded=True#樹的塊的形狀 ) graph = graphviz.Source(dot_data) graph.render("Tree") graph# graph.view()
#特徵重要性 clf.feature_importances_ [*zip(feature_name,clf.feature_importances_)]
咱們已經在只瞭解一個參數的狀況下,創建了一棵完整的決策樹。可是回到步驟4創建模型,score會在某個值附近波動,引發步驟5中畫出來的每一棵樹都不同。它爲何會不穩定呢?若是使用其餘數據集,它還會不穩定嗎?
咱們以前提到過,不管決策樹模型如何進化,在分枝上的本質都仍是追求某個不純度相關的指標的優化,而正如咱們提到的,不純度是基於節點來計算的,也就是說,決策樹在建樹時,是靠優化節點來追求一棵優化的樹,但最優的節點可以保證最優的樹嗎?集成算法被用來解決這個問題:sklearn表示,既然一棵樹不能保證最優,那就建更多的不一樣的樹,而後從中取最好的。怎樣從一組數據集中建不一樣的樹?在每次分枝時,不從使用所有特徵,而是隨機選取一部分特徵,從中選取不純度相關指標最優的做爲分枝用的節點。這樣,每次生成的樹也就不一樣了。
clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=30) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #返回預測的準確度 score
random_state用來設置分枝中的隨機模式的參數,默認None,在高維度時隨機性會表現更明顯,低維度的數據(好比鳶尾花數據集),隨機性幾乎不會顯現。輸入任意整數,會一直長出同一棵樹,讓模型穩定下來。
splitter也是用來控制決策樹中的隨機選項的,有兩種輸入值,輸入」best",決策樹在分枝時雖然隨機,可是仍是會優先選擇更重要的特徵進行分枝(重要性能夠經過屬性feature_importances_查看),輸入「random",決策樹在分枝時會更加隨機,樹會由於含有更多的沒必要要信息而更深更大,並因這些沒必要要信息而下降對訓練集的擬合。這也是防止過擬合的一種方式。當你預測到你的模型會過擬合,用這兩個參數來幫助你下降樹建成以後過擬合的可能性。固然,樹一旦建成,咱們依然是使用剪枝參數來防止過擬合。
clf = tree.DecisionTreeClassifier(criterion="entropy" ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) score#0.9814814814814815 import graphviz dot_data = tree.export_graphviz(clf ,feature_names= feature_name ,class_names=["琴酒","雪莉","貝爾摩德"] ,filled=True ,rounded=True ) graph = graphviz.Source(dot_data) graph
在不加限制的狀況下,一棵決策樹會生長到衡量不純度的指標最優,或者沒有更多的特徵可用爲止。這樣的決策樹每每會過擬合,這就是說,它會在訓練集上表現很好,在測試集上卻表現糟糕。咱們收集的樣本數據不可能和總體的情況徹底一致,所以當一棵決策樹對訓練數據有了過於優秀的解釋性,它找出的規則必然包含了訓練樣本中的噪聲,並使它對未知數據的擬合程度不。
#咱們的樹對訓練集的擬合程度如何? score_train = clf.score(Xtrain, Ytrain) score_train#1.0
爲了讓決策樹有更好的泛化性,咱們要對決策樹進行剪枝。剪枝策略對決策樹的影響巨大,正確的剪枝策略是優化決策樹算法的核心。sklearn爲咱們提供了不一樣的剪枝策略:
限制樹的最大深度,超過設定深度的樹枝所有剪掉。
這是用得最普遍的剪枝參數,在高維度低樣本量時很是有效。決策樹多生長一層,對樣本量的需求會增長一倍,因此限制樹深度可以有效地限制過擬合。在集成算法中也很是實用。實際使用時,建議從=3開始嘗試,看看擬合的效果再決定是否增長設定深度。
min_samples_leaf限定,一個節點在分枝後的每一個子節點都必須包含至少min_samples_leaf個訓練樣本,不然分枝就不會發生,或者,分枝會朝着知足每一個子節點都包含min_samples_leaf個樣本的方向去發生。
通常搭配max_depth使用,在迴歸樹中有神奇的效果,可讓模型變得更加平滑。這個參數的數量設置得過小會引發過擬合,設置得太大就會阻止模型學習數據。通常來講,建議從=5開始使用。若是葉節點中含有的樣本量變化很大,建議輸入浮點數做爲樣本量的百分比來使用。同時,這個參數能夠保證每一個葉子的最小尺寸,能夠在迴歸問題中避免低方差,過擬合的葉子節點出現。對於類別很少的分類問題,=1一般就是最佳選擇。
min_samples_split限定,一個節點必需要包含至少min_samples_split個訓練樣本,這個節點才容許被分枝,不然分枝就不會發生。
clf = tree.DecisionTreeClassifier(criterion="entropy" ,random_state=30 ,splitter="random" ,max_depth=3 # ,min_samples_leaf=10 # ,min_samples_split=25 ) clf = clf.fit(Xtrain, Ytrain) dot_data = tree.export_graphviz(clf ,feature_names= feature_name ,class_names=["琴酒","雪莉","貝爾摩德"] ,filled=True ,rounded=True ) graph = graphviz.Source(dot_data) graph score = clf.score(Xtest, Ytest) score#0.9814814814814815
通常max_depth使用,用做樹的」精修「。
max_features限制分枝時考慮的特徵個數,超過限制個數的特徵都會被捨棄。和max_depth殊途同歸,max_features是用來限制高維度數據的過擬合的剪枝參數,但其方法比較暴力,是直接限制可使用的特徵數量而強行使決策樹停下的參數,在不知道決策樹中的各個特徵的重要性的狀況下,強行設定這個參數可能會致使模型學習不足。若是但願經過降維的方式防止過擬合,建議使用PCA,ICA或者特徵選擇模塊中的降維算法。
min_impurity_decrease限制信息增益的大小,信息增益小於設定數值的分枝不會發生。這是在0.19版本中更新的功能,在0.19版本以前時使用min_impurity_split。
那具體怎麼來肯定每一個參數填寫什麼值呢?這時候,咱們就要使用肯定超參數的曲線來進行判斷了,繼續使用咱們已經訓練好的決策樹模型clf。超參數的學習曲線,是一條以超參數的取值爲橫座標,模型的度量指標爲縱座標的曲線,它是用來衡量不一樣超參數取值下模型的表現的線。在咱們建好的決策樹裏,咱們的模型度量指標就是score。
import matplotlib.pyplot as plt test = [] for i in range(10): clf = tree.DecisionTreeClassifier(max_depth=i+1 ,criterion="entropy" ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) test.append(score) plt.plot(range(1,11),test,color="red",label="max_depth") plt.legend() plt.show()
結果:
思考:
不管如何,剪枝參數的默認值會讓樹無盡地生長,這些樹在某些數據集上可能很是巨大,對內存的消耗也很是巨大。因此若是你手中的數據集很是巨大,你已經預測到不管如何你都是要剪枝的,那提早設定這些參數來控制樹的複雜性和大小會比較好。
完成樣本標籤平衡的參數。樣本不平衡是指在一組數據集中,標籤的一類天生佔有很大的比例。好比說,在銀行要判斷「一個辦了信用卡的人是否會違約",就是是vs否(1%:99%)的比例。這種分類情況下,即使模型什麼也不作,全把結果預測成「否」,正確率也能有99%。所以咱們要使用class_weight參數對樣本標籤進行必定的均衡,給少許的標籤更多的權重,讓模型更偏向少數類,向捕獲少數類的方向建模。該參數默認None,此模式表示自動給與數據集中的全部標籤相同的權重。
有了權重以後,樣本量就再也不是單純地記錄數目,而是受輸入的權重影響了,所以這時候剪枝,就須要搭配min_weight_fraction_leaf這個基於權重的剪枝參數來使用。另請注意,基於權重的剪枝參數(例如min_weight_fraction_leaf)將比不知道樣本權重的標準(好比min_samples_leaf)更少偏向主導類。若是樣本是加權的,則使用基於權重的預修剪標準來更容易優化樹結構,這確保葉節點至少包含樣本權重的總和的一小部分。
屬性是在模型訓練以後,可以調用查看的模型的各類性質。對決策樹來講,最重要的是feature_importances_,可以查看各個特徵對模型的重要性。sklearn中許多算法的接口都是類似的,好比說咱們以前已經用到的fit和score,幾乎對每一個算法均可以使用。除了這兩個接口以外,決策樹最經常使用的接口還有apply和predict。apply中輸入測試集返回每一個測試樣本所在的葉子節點的索引,predict輸入測試集返回每一個測試樣本的標籤。返回的內容一目瞭然而且很是容易,你們感興趣能夠本身下去試試看。
在這裏不得不提的是,全部接口中要求輸入X_train和X_test的部分,輸入的特徵矩陣必須至少是一個二維矩陣。sklearn不接受任何一維矩陣做爲特徵矩陣被輸入。若是你的數據的確只有一個特徵,那必須用reshape(-1,1)來給矩陣增維;若是你的數據只有一個特徵和一個樣本,使用reshape(1,-1)來給你的數據增維。
#apply返回每一個測試樣本所在的葉子節點的索引 clf.apply(Xtest)
結果:
array([19, 27, 19, 27, 7, 7, 7, 27, 19, 27, 21, 21, 7, 18, 7, 21, 7, 10, 7, 19, 7, 27, 19, 19, 27, 21, 7, 21, 27, 7, 19, 7, 7, 27, 21, 27, 27, 7, 27, 7, 19, 27, 7, 27, 27, 19, 19, 10, 27, 27, 27, 10, 7, 21], dtype=int64)
#predict返回每一個測試樣本的分類/迴歸結果 clf.predict(Xtest)
結果:
array([1, 0, 1, 0, 2, 2, 2, 0, 1, 0, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 1, 1, 0, 1, 2, 1, 0, 2, 1, 2, 2, 0, 1, 0, 0, 2, 0, 2, 1, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 1, 2, 1])
至此,咱們已經學完了分類樹DecisionTreeClassifier和用決策樹繪圖(export_graphviz)的全部基礎。咱們講解了決策樹的基本流程,分類樹的八個參數,一個屬性,四個接口,以及繪圖所用的代碼。
八個參數:Criterion,兩個隨機性相關的參數(random_state,splitter),五個剪枝參數(max_depth, min_samples_split,min_samples_leaf,max_feature,min_impurity_decrease)
一個屬性:feature_importances_
四個接口:fit,score,apply,predict
有了這些知識,基本上分類樹的使用你們都可以掌握了,接下來再到實例中去磨練就好。
class sklearn.tree.DecisionTreeRegressor (criterion=’mse’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, presort=False)
幾乎全部參數,屬性及接口都和分類樹如出一轍。須要注意的是,在迴歸樹種,沒有標籤分佈是否均衡的問題,所以沒有class_weight這樣的參數。
迴歸樹衡量分枝質量的指標,支持的標準有三種:
屬性中最重要的依然是feature_importances_,接口依然是apply, fit, predict, score最核心。
其中N是樣本數量,i是每個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤。因此MSE的本質,實際上是樣本真實數據與迴歸結果的差別。在迴歸樹中,MSE不僅是咱們的分枝質量衡量指標,也是咱們最經常使用的衡量回歸樹迴歸質量的指標,當咱們在使用交叉驗證,或者其餘方式獲取迴歸樹的結果時,咱們每每選擇均方偏差做爲咱們的評估(在分類樹中這個指標是score表明的預測準確率)。在迴歸中,咱們追求的是,MSE越小越好。然而,迴歸樹的接口score返回的是R平方,並非MSE。R平方被定義以下:
其中u是殘差平方和(MSE * N),v是總平方和,N是樣本數量,i是每個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤。y帽是真實數值標籤的平均數。R平方能夠爲正爲負(若是模型的殘差平方和遠遠大於模型的總平方和,模型很是糟糕,R平方就會爲負),而均方偏差永遠爲正。
值得一提的是,雖然均方偏差永遠爲正,可是sklearn當中使用均方偏差做爲評判標準時,倒是計算」負均方偏差「(neg_mean_squared_error)。這是由於sklearn在計算模型評估指標的時候,會考慮指標自己的性質,均方偏差自己是一種偏差,因此被sklearn劃分爲模型的一種損失(loss),所以在sklearn當中,都以負數表示。真正的均方偏差MSE的數值,其實就是neg_mean_squared_error去掉負號的數字。
簡單看看回歸樹是怎樣工做的
from sklearn.datasets import load_boston from sklearn.model_selection import cross_val_score from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
boston.data
結果:
array([[6.3200e-03, 1.8000e+01, 2.3100e+00, ..., 1.5300e+01, 3.9690e+02, 4.9800e+00], [2.7310e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9690e+02, 9.1400e+00], [2.7290e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9283e+02, 4.0300e+00], ..., [6.0760e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02, 5.6400e+00], [1.0959e-01, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9345e+02, 6.4800e+00], [4.7410e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02, 7.8800e+00]])
boston.target
結果:
array([24. , 21.6, 34.7, 33.4, 36.2, 28.7, 22.9, 27.1, 16.5, 18.9, 15. , 18.9, 21.7, 20.4, 18.2, 19.9, 23.1, 17.5, 20.2, 18.2, 13.6, 19.6, 15.2, 14.5, 15.6, 13.9, 16.6, 14.8, 18.4, 21. , 12.7, 14.5, 13.2, 13.1, 13.5, 18.9, 20. , 21. , 24.7, 30.8, 34.9, 26.6, 25.3, 24.7, 21.2, 19.3, 20. , 16.6, 14.4, 19.4, 19.7, 20.5, 25. , 23.4, 18.9, 35.4, 24.7, 31.6, 23.3, 19.6, 18.7, 16. , 22.2, 25. , 33. , 23.5, 19.4, 22. , 17.4, 20.9, 24.2, 21.7, 22.8, 23.4, 24.1, 21.4, 20. , 20.8, 21.2, 20.3, 28. , 23.9, 24.8, 22.9, 23.9, 26.6, 22.5, 22.2, 23.6, 28.7, 22.6, 22. , 22.9, 25. , 20.6, 28.4, 21.4, 38.7, 43.8, 33.2, 27.5, 26.5, 18.6, 19.3, 20.1, 19.5, 19.5, 20.4, 19.8, 19.4, 21.7, 22.8, 18.8, 18.7, 18.5, 18.3, 21.2, 19.2, 20.4, 19.3, 22. , 20.3, 20.5, 17.3, 18.8, 21.4, 15.7, 16.2, 18. , 14.3, 19.2, 19.6, 23. , 18.4, 15.6, 18.1, 17.4, 17.1, 13.3, 17.8, 14. , 14.4, 13.4, 15.6, 11.8, 13.8, 15.6, 14.6, 17.8, 15.4, 21.5, 19.6, 15.3, 19.4, 17. , 15.6, 13.1, 41.3, 24.3, 23.3, 27. , 50. , 50. , 50. , 22.7, 25. , 50. , 23.8, 23.8, 22.3, 17.4, 19.1, 23.1, 23.6, 22.6, 29.4, 23.2, 24.6, 29.9, 37.2, 39.8, 36.2, 37.9, 32.5, 26.4, 29.6, 50. , 32. , 29.8, 34.9, 37. , 30.5, 36.4, 31.1, 29.1, 50. , 33.3, 30.3, 34.6, 34.9, 32.9, 24.1, 42.3, 48.5, 50. , 22.6, 24.4, 22.5, 24.4, 20. , 21.7, 19.3, 22.4, 28.1, 23.7, 25. , 23.3, 28.7, 21.5, 23. , 26.7, 21.7, 27.5, 30.1, 44.8, 50. , 37.6, 31.6, 46.7, 31.5, 24.3, 31.7, 41.7, 48.3, 29. , 24. , 25.1, 31.5, 23.7, 23.3, 22. , 20.1, 22.2, 23.7, 17.6, 18.5, 24.3, 20.5, 24.5, 26.2, 24.4, 24.8, 29.6, 42.8, 21.9, 20.9, 44. , 50. , 36. , 30.1, 33.8, 43.1, 48.8, 31. , 36.5, 22.8, 30.7, 50. , 43.5, 20.7, 21.1, 25.2, 24.4, 35.2, 32.4, 32. , 33.2, 33.1, 29.1, 35.1, 45.4, 35.4, 46. , 50. , 32.2, 22. , 20.1, 23.2, 22.3, 24.8, 28.5, 37.3, 27.9, 23.9, 21.7, 28.6, 27.1, 20.3, 22.5, 29. , 24.8, 22. , 26.4, 33.1, 36.1, 28.4, 33.4, 28.2, 22.8, 20.3, 16.1, 22.1, 19.4, 21.6, 23.8, 16.2, 17.8, 19.8, 23.1, 21. , 23.8, 23.1, 20.4, 18.5, 25. , 24.6, 23. , 22.2, 19.3, 22.6, 19.8, 17.1, 19.4, 22.2, 20.7, 21.1, 19.5, 18.5, 20.6, 19. , 18.7, 32.7, 16.5, 23.9, 31.2, 17.5, 17.2, 23.1, 24.5, 26.6, 22.9, 24.1, 18.6, 30.1, 18.2, 20.6, 17.8, 21.7, 22.7, 22.6, 25. , 19.9, 20.8, 16.8, 21.9, 27.5, 21.9, 23.1, 50. , 50. , 50. , 50. , 50. , 13.8, 13.8, 15. , 13.9, 13.3, 13.1, 10.2, 10.4, 10.9, 11.3, 12.3, 8.8, 7.2, 10.5, 7.4, 10.2, 11.5, 15.1, 23.2, 9.7, 13.8, 12.7, 13.1, 12.5, 8.5, 5. , 6.3, 5.6, 7.2, 12.1, 8.3, 8.5, 5. , 11.9, 27.9, 17.2, 27.5, 15. , 17.2, 17.9, 16.3, 7. , 7.2, 7.5, 10.4, 8.8, 8.4, 16.7, 14.2, 20.8, 13.4, 11.7, 8.3, 10.2, 10.9, 11. , 9.5, 14.5, 14.1, 16.1, 14.3, 11.7, 13.4, 9.6, 8.7, 8.4, 12.8, 10.5, 17.1, 18.4, 15.4, 10.8, 11.8, 14.9, 12.6, 14.1, 13. , 13.4, 15.2, 16.1, 17.8, 14.9, 14.1, 12.7, 13.5, 14.9, 20. , 16.4, 17.7, 19.5, 20.2, 21.4, 19.9, 19. , 19.1, 19.1, 20.1, 19.9, 19.6, 23.2, 29.8, 13.8, 13.3, 16.7, 12. , 14.6, 21.4, 23. , 23.7, 25. , 21.8, 20.6, 21.2, 19.1, 20.6, 15.2, 7. , 8.1, 13.6, 20.1, 21.8, 24.5, 23.1, 19.7, 18.3, 21.2, 17.5, 16.8, 22.4, 20.6, 23.9, 22. , 11.9])
regressor = DecisionTreeRegressor(random_state=0)#實例化 cross_val_score(regressor, boston.data, boston.target, cv=10,#交叉驗證會自動劃分數據集爲測試集與驗證集,不須要本身單獨劃分,cv爲劃分的數量,默認是5 scoring = "neg_mean_squared_error"#scoring指的是返回的是均方偏差,若是不寫返回的是R的平方 )
結果:
array([-16.41568627, -10.61843137, -18.30176471, -55.36803922, -16.01470588, -44.70117647, -12.2148 , -91.3888 , -57.764 , -36.8134 ])
cross_val_score(regressor, boston.data, boston.target, cv=10).mean()#返回的是R方的均值:-0.1253505322812249
交叉驗證是用來觀察模型的穩定性的一種方法,咱們將數據劃分爲n份,依次使用其中一份做爲測試集,其餘n-1份做爲訓練集,屢次計算模型的精確性來評估模型的平均準確程度。訓練集和測試集的劃分會干擾模型的結果,所以用交叉驗證n次的結果求出的平均值,是對模型效果的一個更好的度量。
接下來咱們到二維平面上來觀察決策樹是怎樣擬合一條曲線的。咱們用迴歸樹來擬合正弦曲線,並添加一些噪聲來觀察迴歸樹的表現。
import numpy as np from sklearn.tree import DecisionTreeRegressor import matplotlib.pyplot as plt
在這一步,咱們的基本思路是,先建立一組隨機的,分佈在0~5上的橫座標軸的取值(x),而後將這一組值放到sin函數中去生成縱座標的值(y),接着再到y上去添加噪聲。全程咱們會使用numpy庫來爲咱們生成這個正弦曲線。
rng = np.random.RandomState(1) #隨機數種子 #np.random.rand(數組結構),生成隨機數組的函數 X = np.sort(5 * rng.rand(80,1), axis=0) #生成0~5之間隨機的x的取值,80行1列,按照axis = 0(行)進行從小到大排序 y = np.sin(X).ravel() #生成正弦曲線 np.sin(X)生成的是80行1列的數組,經過.ravel()降爲1維,.ravel()能夠將n維數組降爲n-1維,屢次容許n-1次能夠降爲1維 y[::5] += 3 * (0.5 - rng.rand(16)) #在正弦曲線上加噪聲, rng.rand(16)指的是生成16個0~1之間的隨機數
plt.figure() plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")#散點圖
結果:<matplotlib.collections.PathCollection at 0xb04a2e8>
#瞭解降維函數ravel()的用法 np.random.random((2,1)) np.random.random((2,1)).ravel() np.random.random((2,1)).ravel().shape
regr_1 = DecisionTreeRegressor(max_depth=2) regr_2 = DecisionTreeRegressor(max_depth=5) regr_1.fit(X, y) regr_2.fit(X, y)
結果:
DecisionTreeRegressor(criterion='mse', max_depth=5, max_features=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort=False, random_state=None, splitter='best')
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]#np.newaxis做用是增長1個維度 y_1 = regr_1.predict(X_test) y_2 = regr_2.predict(X_test)
#瞭解增維切片np.newaxis的用法 l = np.array([1,2,3,4]) l#array([1, 2, 3, 4]) l.shape#(4,) l[:,np.newaxis] # array([[1], # [2], # [3], # [4]]) l[:,np.newaxis].shape#(4, 1) l[np.newaxis,:].shape#(1, 4) l[np.newaxis,:]#array([[1, 2, 3, 4]])
plt.figure() plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")#s指的是點的大小 plt.plot(X_test, y_1, color="cornflowerblue",label="max_depth=2", linewidth=2)#折線圖 plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2) plt.xlabel("data") plt.ylabel("target") plt.title("Decision Tree Regression") plt.legend() plt.show()
結果:
可見,迴歸樹學習了近似正弦曲線的局部線性迴歸。咱們能夠看到,若是樹的最大深度(由max_depth參數控制)設置得過高,則決策樹學習得太精細,它從訓練數據中學了不少細節,包括噪聲得呈現,從而使模型偏離真實的正弦曲線,造成過擬合。
泰坦尼克號的沉沒是世界上最嚴重的海難事故之一,今天咱們經過分類樹模型來預測一下哪些人可能成爲倖存者。數據集來着https://www.kaggle.com/c/titanic,數據集會隨着代碼一塊兒提供給你們,你們能夠在下載頁面拿到,或者到羣中詢問。數據集包含兩個csv格式文件,data爲咱們接下來要使用的數據,test爲kaggle提供的測試集。接下來咱們就來執行咱們的代碼。
import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import GridSearchCV from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt
data = pd.read_csv(r"C:\work\learnbetter\micro-class\week 1 DT\data\data.csv",index_col = 0) data.head() data.info() #object屬於文本類型,並不屬於數值類型! #查看缺失值,爲預處理作準備 ''' <class 'pandas.core.frame.DataFrame'> Int64Index: 891 entries, 1 to 891 Data columns (total 11 columns): Survived 891 non-null int64 Pclass 891 non-null int64 Name 891 non-null object Sex 891 non-null object Age 714 non-null float64 SibSp 891 non-null int64 Parch 891 non-null int64 Ticket 891 non-null object Fare 891 non-null float64 Cabin 204 non-null object Embarked 889 non-null object dtypes: float64(2), int64(4), object(5) memory usage: 83.5+ KB '''
#篩選特徵 #刪除缺失值過多的列,和觀察判斷來講和預測的y沒有關係的列 data.drop(["Cabin","Name","Ticket"],inplace=True,axis=1)#inplace=True指的是覆蓋原表,False則會生成新表 #處理缺失值,對缺失值較多的列進行填補,有一些特徵只缺失一兩個值,能夠採起直接刪除記錄的方法 data["Age"] = data["Age"].fillna(data["Age"].mean()) data = data.dropna()#默認axis = 0 #將分類變量(如object類型)轉換爲數值型變量 #將二分類變量轉換爲數值型變量 #astype可以將一個pandas對象轉換爲某種類型,和apply(int(x))不一樣,astype能夠將文本類轉換爲數字,用這個方式能夠很便捷地將二分類特徵轉換爲0~1 data["Sex"] = (data["Sex"]== "male").astype("int")#.astype("int")將bool值轉換爲int類型 #將三分類變量轉換爲數值型變量 labels = data["Embarked"].unique().tolist()#tolist()將數組array變爲列表list data["Embarked"] = data["Embarked"].apply(lambda x: labels.index(x)) #查看處理後的數據集 data.head()
X = data.iloc[:,data.columns != "Survived"] y = data.iloc[:,data.columns == "Survived"] from sklearn.model_selection import train_test_split Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3) #修正測試集和訓練集的索引 for i in [Xtrain, Xtest, Ytrain, Ytest]: i.index = range(i.shape[0]) #查看分好的訓練集和測試集 Xtrain.head()
clf = DecisionTreeClassifier(random_state=25) clf = clf.fit(Xtrain, Ytrain) score_ = clf.score(Xtest, Ytest) score_ score = cross_val_score(clf,X,y,cv=10).mean()#使用交叉驗證 score
tr = [] te = [] for i in range(10): clf = DecisionTreeClassifier(random_state=25 ,max_depth=i+1 ,criterion="entropy"#嘗試調參,讓結果更好 ) clf = clf.fit(Xtrain, Ytrain) score_tr = clf.score(Xtrain,Ytrain)#訓練集分數 score_te = cross_val_score(clf,X,y,cv=10).mean()#測試集分數 tr.append(score_tr) te.append(score_te) print(max(te)) plt.plot(range(1,11),tr,color="red",label="train") plt.plot(range(1,11),te,color="blue",label="test") plt.xticks(range(1,11))#橫座標標尺,只顯示1-10。 plt.legend() plt.show()
結果:0.8177860061287026
注意:這裏爲何使用「entropy」?由於咱們注意到,在最大深度=3的時候,模型擬合不足,在訓練集和測試集上的表現接近,但卻都不是很是理想,只可以達到83%左右,因此咱們要使用entropy。
#網格搜索:可以幫助咱們同時調整多個參數的技術,枚舉技術 import numpy as np gini_thresholds = np.linspace(0,0.5,20)#基尼係數的邊界 #entropy_thresholds = np.linespace(0, 1, 50) #一串參數和這些參數對應的,咱們但願網格搜索來搜索的參數的取值範圍 parameters = {'splitter':('best','random') ,'criterion':("gini","entropy") ,"max_depth":[*range(1,10)] ,'min_samples_leaf':[*range(1,50,5)] ,'min_impurity_decrease':[*gini_thresholds] } clf = DecisionTreeClassifier(random_state=25)#實例化決策樹 GS = GridSearchCV(clf, parameters, cv=10)#實例化網格搜索,cv指的是交叉驗證 GS.fit(Xtrain,Ytrain) GS.best_params_#從咱們輸入的參數和參數取值的列表中,返回最佳組合 GS.best_score_#網格搜索後的模型的評判標準
1. 易於理解和解釋,由於樹木能夠畫出來被看見
2. 須要不多的數據準備。其餘不少算法一般都須要數據規範化,須要建立虛擬變量並刪除空值等。但請注意,sklearn中的決策樹模塊不支持對缺失值的處理。
3. 使用樹的成本(好比說,在預測數據的時候)是用於訓練樹的數據點的數量的對數,相比於其餘算法,這是一個很低的成本。
4. 可以同時處理數字和分類數據,既能夠作迴歸又能夠作分類。其餘技術一般專門用於分析僅具備一種變量類型的數據集。
5. 可以處理多輸出問題,即含有多個標籤的問題,注意與一個標籤中含有多種標籤分類的問題區別開
6. 是一個白盒模型,結果很容易可以被解釋。若是在模型中能夠觀察到給定的狀況,則能夠經過布爾邏輯輕鬆解釋條件。相反,在黑盒模型中(例如,在人工神經網絡中),結果可能更難以解釋。
7. 可使用統計測試驗證模型,這讓咱們能夠考慮模型的可靠性。
8. 即便其假設在某種程度上違反了生成數據的真實模型,也可以表現良好。
1. 決策樹學習者可能建立過於複雜的樹,這些樹不能很好地推廣數據。這稱爲過分擬合。修剪,設置葉節點所需的最小樣本數或設置樹的最大深度等機制是避免此問題所必需的,而這些參數的整合和調整對初學者來講會比較晦澀
2. 決策樹可能不穩定,數據中微小的變化可能致使生成徹底不一樣的樹,這個問題須要經過集成算法來解決。
3. 決策樹的學習是基於貪婪算法,它靠優化局部最優(每一個節點的最優)來試圖達到總體的最優,但這種作法不能保證返回全局最優決策樹。這個問題也能夠由集成算法來解決,在隨機森林中,特徵和樣本會在分枝過程當中被隨機採樣。
4. 有些概念很難學習,由於決策樹不容易表達它們,例如XOR,奇偶校驗或多路複用器問題。
5. 若是標籤中的某些類占主導地位,決策樹學習者會建立偏向主導類的樹。所以,建議在擬合決策樹以前平衡數據集。
咱們在紅酒數據集上畫出了一棵樹,而且展現了多個參數會對樹造成這樣的影響,接下來,咱們將在不一樣結構的數據集上測試一下決策樹的效果,讓你們更好地理解決策樹。
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_moons, make_circles, make_classification from sklearn.tree import DecisionTreeClassifier
咱們先從sklearn自帶的數據庫中生成三種類型的數據集:1)月亮型數據,2)環形數據,3)二分型數據
#make_classification庫生成隨機的二分型數據 X, y = make_classification(n_samples=100, #生成100個樣本 n_features=2, #包含2個特徵,即生成二維數據 n_redundant=0, #添加冗餘特徵0個 n_informative=2, #包含信息的特徵是2個 random_state=1, #隨機模式1 n_clusters_per_class=1 #每一個簇內包含的標籤類別有1個 ) #在這裏能夠查看一下X和y,其中X是100行帶有兩個2特徵的數據,y是二分類標籤 #也能夠畫出散點圖來觀察一下X中特徵的分佈 #plt.scatter(X[:,0],X[:,1]) #從圖上能夠看出,生成的二分型數據的兩個簇離彼此很遠,這樣不利於咱們測試分類器的效果,所以咱們使用np生成 # 隨機數組,經過讓已經生成的二分型數據點加減0~1之間的隨機數,使數據分佈變得更散更稀疏 #注意,這個過程只可以運行一次,由於屢次運行以後X會變得很是稀疏,兩個簇的數據會混合在一塊兒,分類器的效應會 # 繼續降低 rng = np.random.RandomState(2) #生成一種隨機模式 X += 2 * rng.uniform(size=X.shape) #加減0~1之間的隨機數 linearly_separable = (X, y) #生成了新的X,依然能夠畫散點圖來觀察一下特徵的分佈 #plt.scatter(X[:,0],X[:,1]) #用make_moons建立月亮型數據,make_circles建立環形數據,並將三組數據打包起來放在列表datasets中 datasets = [make_moons(noise=0.3, random_state=0), make_circles(noise=0.2, factor=0.5, random_state=1), linearly_separable]
#建立畫布,寬高比爲6*9 figure = plt.figure(figsize=(6, 9)) #設置用來安排圖像顯示位置的全局變量i i = 1 #開始迭代數據,對datasets中的數據進行for循環 for ds_index, ds in enumerate(datasets): #對X中的數據進行標準化處理,而後分訓練集和測試集 X, y = ds X = StandardScaler().fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4, random_state=42) #找出數據集中兩個特徵的最大值和最小值,讓最大值+0.5,最小值-0.5,創造一個比兩個特徵的區間自己更大 # 一點的區間 x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5 x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5 #用特徵向量生成網格數據,網格數據,其實就至關於座標軸上無數個點 #函數np.arange在給定的兩個數之間返回均勻間隔的值,0.2爲步長 #函數meshgrid用以生成網格數據,可以將兩個一維數組生成兩個二維矩陣。 #若是第一個數組是narray,維度是n,第二個參數是marray,維度是m。那麼生成的第一個二維數組是以 # narray爲行,m行的矩陣,而第二個二維數組是以marray的轉置爲列,n列的矩陣 #生成的網格數據,是用來繪製決策邊界的,由於繪製決策邊界的函數contourf要求輸入的兩個特徵都必須是二 # 維的 array1,array2 = np.meshgrid(np.arange(x1_min, x1_max, 0.2), np.arange(x2_min, x2_max, 0.2)) #接下來生成彩色畫布 #用ListedColormap爲畫布建立顏色,#FF0000正紅,#0000FF正藍 cm = plt.cm.RdBu cm_bright = ListedColormap(['#FF0000', '#0000FF']) #在畫布上加上一個子圖,數據爲len(datasets)行,2列,放在位置i上 ax = plt.subplot(len(datasets), 2, i) #到這裏爲止,已經生成了0~1之間的座標系3個了,接下來爲咱們的座標系放上標題 #咱們有三個座標系,但咱們只須要在第一個座標系上有標題,所以設定if ds_index==0這個條件 if ds_index == 0: ax.set_title("Input data") #將數據集的分佈放到咱們的座標系上 #先放訓練集 ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright,edgecolors='k') #放測試集 ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6,edgecolors='k') #爲圖設置座標軸的最大值和最小值,並設定沒有座標軸 ax.set_xlim(array1.min(), array1.max()) ax.set_ylim(array2.min(), array2.max()) ax.set_xticks(()) ax.set_yticks(()) #每次循環以後,改變i的取值讓圖每次位列不一樣的位置 i += 1 #至此爲止,數據集自己的圖像已經佈置完畢,運行以上的代碼,能夠看見三個已經處理好的數據集 #############################從這裏開始是決策樹模型########################## #迭代決策樹,首先用subplot增長子圖,subplot(行,列,索引)這樣的結構,並使用索引i定義圖的位置 #在這裏,len(datasets)其實就是3,2是兩列 #在函數最開始,咱們定義了i=1,而且在上邊創建數據集的圖像的時候,已經讓i+1,因此i在每次循環中的取值 # 是2,4,6 ax = plt.subplot(len(datasets),2,i) #決策樹的建模過程:實例化 → fit訓練 → score接口獲得預測的準確率 clf = DecisionTreeClassifier(max_depth=5) clf.fit(X_train, y_train) score = clf.score(X_test, y_test) #繪製決策邊界,爲此,咱們將爲網格中的每一個點指定一種顏色[x1_min,x1_max] x [x2_min,x2_max] #分類樹的接口,predict_proba,返回每個輸入的數據點所對應的標籤類機率 #類機率是數據點所在的葉節點中相同類的樣本數量/葉節點中的樣本總數量 #因爲決策樹在訓練的時候導入的訓練集X_train裏面包含兩個特徵,因此咱們在計算類機率的時候,也必須導入 # 結構相同的數組,便是說,必須有兩個特徵 #ravel()可以將一個多維數組轉換成一維數組 #np.c_是可以將兩個數組組合起來的函數 #在這裏,咱們先將兩個網格數據降維降維成一維數組,再將兩個數組連接變成含有兩個特徵的數據,再帶入決策 # 樹模型,生成的Z包含數據的索引和每一個樣本點對應的類機率,再切片,切出類機率 Z = clf.predict_proba(np.c_[array1.ravel(),array2.ravel()])[:, 1] #np.c_[np.array([1,2,3]), np.array([4,5,6])] #將返回的類機率做爲數據,放到contourf裏面繪製去繪製輪廓 Z = Z.reshape(array1.shape) ax.contourf(array1, array2, Z, cmap=cm, alpha=.8) #將數據集的分佈放到咱們的座標系上 # 將訓練集放到圖中去 ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors='k') # 將測試集放到圖中去 ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, edgecolors='k', alpha=0.6) #爲圖設置座標軸的最大值和最小值 ax.set_xlim(array1.min(), array1.max()) ax.set_ylim(array2.min(), array2.max()) #設定座標軸不顯示標尺也不顯示數字 ax.set_xticks(()) ax.set_yticks(()) #咱們有三個座標系,但咱們只須要在第一個座標系上有標題,所以設定if ds_index==0這個條件 if ds_index == 0: ax.set_title("Decision Tree") #寫在右下角的數字 ax.text(array1.max() - .3, array2.min() + .3, ('{:.1f}%'.format(score*100)), size=15, horizontalalignment='right') #讓i繼續加一 i += 1 plt.tight_layout() plt.show()
結果:
從圖上來看,每一條線都是決策樹在二維平面上畫出的一條決策邊界,每當決策樹分枝一次,就有一條線出現。當數據的維度更高的時候,這條決策邊界就會由線變成面,甚至變成咱們想象不出的多維圖形。
同時,很容易看得出,分類樹天生不擅長環形數據。每一個模型都有本身的決策上限,因此一個怎樣調整都沒法提高表現的可能性也是有的。當一個模型怎麼調整都不行的時候,咱們能夠選擇換其餘的模型使用,不要在一棵樹上吊死。順便一說,最擅長月亮型數據的是最近鄰算法,RBF支持向量機和高斯過程;最擅長環形數據的是最近鄰算法和高斯過程;最擅長對半分的數據的是樸素貝葉斯,神經網絡和隨機森林。