[机器学习与scikit-learn-15]:算法-决策树-分类问题代码详解
作者主頁(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文網(wǎng)址:
目錄
第1章 scikit-learn對決策樹的支持
1.1 決策樹的基本原理
1.2 決策樹的核心問題
1.3?sklearn中的決策樹
1.4?sklearn實現(xiàn)決策樹的三步驟
第2章 代碼實現(xiàn)示例
2.1?DecisionTreeClassifier類接口
2.2 構(gòu)建數(shù)據(jù)集
2.3 構(gòu)建模型并訓(xùn)練模型
2.4 顯示訓(xùn)練好決策樹
2.5 剪枝?
2.6 精修參數(shù)max_features & min_impurity_decrease
2.7?確認(rèn)最優(yōu)的剪枝參數(shù)
第1章 scikit-learn對決策樹的支持
1.1 決策樹的基本原理
https://blog.csdn.net/HiWangWenBing/article/details/123340741
在這個決策過程中,我們一直在對記錄的特征進(jìn)行提問。
最初的問題所在的地方叫做根節(jié)點,
在得到結(jié)論前的每一個問題都是中間節(jié)點,
而得到的每一個結(jié)論(動物的類別)都叫做葉子節(jié)點。
關(guān)鍵概念:節(jié)點
根節(jié)點:沒有進(jìn)邊,有出邊。包含最初的,針對特征的提問。
中間節(jié)點:既有進(jìn)邊也有出邊,進(jìn)邊只有一條,出邊可以有很多條。都是針對特征的提問。
葉子節(jié)點:有進(jìn)邊,沒有出邊,每個葉子節(jié)點都是一個類別標(biāo)簽。
*子節(jié)點和父節(jié)點:在兩個相連的節(jié)點中,更接近根節(jié)點的是父節(jié)點,另一個是子節(jié)點。
1.2 決策樹的核心問題
決策樹算法的核心是要解決兩個問題:
1)如何從數(shù)據(jù)表中找出最佳根節(jié)點、最佳分枝、葉子節(jié)點?
2)如何讓決策樹停止生長,防止過擬合?
幾乎所有決策樹有關(guān)的模型調(diào)整方法,都圍繞這兩個問題展開。
1.3?sklearn中的決策樹
?本文重點關(guān)注:分類決策樹tree.DecisionTreeClassifier和tree.export_graphviz。
1.4?sklearn實現(xiàn)決策樹的三步驟
第2章 代碼實現(xiàn)示例
2.1?DecisionTreeClassifier類接口
DecisionTreeClassifier(criterion='entropy', min_samples_leaf=3) 類為創(chuàng)建一個決策樹模型,
其類的參數(shù)含義如下所示:
- criterion:判決依據(jù),gini或者entropy,前者是基尼系數(shù),后者是信息熵。這兩種差別不大,信息上的最大值為1,而激勵系數(shù)最大值為0.5.
- splitter:?best or random,前者是在所有特征中找最好的切分點,后者是在部分特征中,默認(rèn)的”best”適合樣本量不大的時候,而如果樣本數(shù)據(jù)量非常大,此時決策樹構(gòu)建推薦”random” 。
- max_features:None(所有),log2,sqrt,N ?特征小于50的時候一般使用所有的特征。
- max_depth:? int or None, optional (default=None) 設(shè)置決策隨機(jī)森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度為:5-20之間。
- min_samples_split:設(shè)置結(jié)點的最小樣本數(shù)量,當(dāng)樣本數(shù)量可能小于此值時,結(jié)點將不會在劃分。
- min_samples_leaf: 這個值限制了葉子節(jié)點包含的最少的樣本數(shù),如果某葉子節(jié)點數(shù)目小于樣本數(shù),則會和兄弟節(jié)點一起被剪枝,并合并到上一層節(jié)點中。防止過擬合。葉子節(jié)點包含的樣本數(shù)少,表明該判斷分支,只能判斷出極少的樣本,不具備普遍性, 葉子節(jié)點中,包含的樣本數(shù)越多,則泛化能力越強(qiáng),普遍性越強(qiáng)。
- min_weight_fraction_leaf: 這個值限制了葉子節(jié)點所有樣本權(quán)重和的最小值,如果小于這個值,則會和兄弟節(jié)點一起被剪枝默認(rèn)是0,就是不考慮權(quán)重問題。
- max_leaf_nodes: 通過限制最大葉子節(jié)點數(shù),可以防止過擬合,默認(rèn)是"None”,即不限制最大的葉子節(jié)點數(shù)。
- class_weight: 指定樣本各類別的的權(quán)重,主要是為了防止訓(xùn)練集某些類別的樣本過多導(dǎo)致訓(xùn)練的決策樹過于偏向這些類別。這里可以自己指定各個樣本的權(quán)重,如果使用“balanced”,則算法會自己計算權(quán)重,樣本量少的類別所對應(yīng)的樣本權(quán)重會高。
- min_impurity_split: 這個值限制了決策樹的增長,如果某節(jié)點的不純度(基尼系數(shù),信息增益,均方差,絕對差)小于這個閾值則該節(jié)點不再生成子節(jié)點。即為葉子節(jié)點 。即沒有必要使得不純度得到0,只要不純度小于某個門限即可。
2.2 構(gòu)建數(shù)據(jù)集
from sklearn import tree from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split# 加載內(nèi)置數(shù)據(jù)集 wine = load_wine() print("\n數(shù)據(jù)形狀: 178個樣本,13列特征\n",wine.data.shape) print("\n分類標(biāo)簽名:\n",wine.target)# 顯示數(shù)據(jù)集表格 import pandas as pdpd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)print("\n特征名:\n", wine.feature_names) print("\n分類標(biāo)簽名:\n",wine.target_names)# 分割數(shù)據(jù)集 Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3) print("\n訓(xùn)練集:", Xtrain.shape) print("\n測試集:", Xtest.shape) 數(shù)據(jù)形狀: 178個樣本,13列特征(178, 13)分類標(biāo)簽名:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]特征名:['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']分類標(biāo)簽名:['class_0' 'class_1' 'class_2']訓(xùn)練集: (124, 13)測試集: (54, 13)2.3 構(gòu)建模型并訓(xùn)練模型
# 構(gòu)建模型對象 #DecisionTreeObj = tree.DecisionTreeClassifier(criterion="entropy", random_state=30, splitter="random") DecisionTreeObj = tree.DecisionTreeClassifier(criterion="entropy", random_state=30, splitter="random")# 用數(shù)據(jù)集訓(xùn)練模型,生成決策樹 DecisionTreeObj = DecisionTreeObj.fit(Xtrain, Ytrain)# 評估模型:預(yù)測的準(zhǔn)確度 score = DecisionTreeObj.score(Xtest, Ytest) print("測試集打分:",score)score = DecisionTreeObj.score(Xtrain, Ytrain) print("訓(xùn)練集打分:",score) 測試集打分: 0.9629629629629629 訓(xùn)練集打分: 1.0在訓(xùn)練集上,準(zhǔn)確率100%。
2.4 顯示訓(xùn)練好決策樹
# 展現(xiàn)決策樹 # conda install graphviz import graphvizfeature_name = ['酒精','蘋果酸','灰','灰的堿性','鎂','總酚','類黃酮','非黃烷類酚類','花青素','顏色強(qiáng)度','色調(diào)','稀釋葡萄酒','脯氨酸'] print("特征名稱:", feature_name) print("特征個數(shù):", len(feature_name))dot_data = tree.export_graphviz(DecisionTreeObj,out_file = None, feature_names = feature_name, class_names = ["分類1","分類2","分類3"] #用來替代'class_0' 'class_1' 'class_2', filled=True # 填充顏色, rounded=True # 圓角圖形) graph = graphviz.Source(dot_data) graph 特征名稱: ['酒精', '蘋果酸', '灰', '灰的堿性', '鎂', '總酚', '類黃酮', '非黃烷類酚類', '花青素', '顏色強(qiáng)度', '色調(diào)', '稀釋葡萄酒', '脯氨酸'] 特征個數(shù): 132.5 剪枝?
在不加限制的情況下,一棵決策樹會生長到衡量不純度的指標(biāo)最優(yōu),或者沒有更多的特征可用為止。這樣的決策樹往往會過擬合,這就是說,它會在訓(xùn)練集上表現(xiàn)很好,在測試集上卻表現(xiàn)糟糕。我們收集的樣本數(shù)據(jù)不可能和整體的狀況完全一致,因此當(dāng)一棵決策樹對訓(xùn)練數(shù)據(jù)有了過于優(yōu)秀的解釋性,它找出的規(guī)則必然包含了訓(xùn)練樣本中的噪聲,并使它對未知數(shù)據(jù)的擬合程度不足。
為了讓決策樹有更好的泛化性,我們要對決策樹進(jìn)行剪枝。剪枝策略對決策樹的影響巨大,正確的剪枝策略是優(yōu)化決策樹算法的核心。sklearn為我們提供了不同的剪枝策略:
(1)max_depth
限制樹的最大深度,超過設(shè)定深度的樹枝全部剪掉這是用得最廣泛的剪枝參數(shù),在高維度低樣本量時非常有效。
決策樹多生長一層,對樣本量的需求會增加一倍,所以限制樹深度能夠有效地限制過擬合。
在集成算法中也非常實用。
實際使用時,建議從=3開始嘗試,看看擬合的效果再決定是否增加設(shè)定深度。逐步增加層數(shù),訓(xùn)練后再測試集上檢驗,最后尋找最好的層數(shù)。
(2)min_samples_leaf
min_samples_leaf限定,一個節(jié)點在分枝后的每個子節(jié)點都必須包含至少min_samples_leaf個訓(xùn)練樣本,否則分枝就不會發(fā)生,或者,分枝會朝著滿足每個子節(jié)點都包含min_samples_leaf個樣本的方向去發(fā)生。
一般搭配max_depth使用,在回歸樹中有神奇的效果,可以讓模型變得更加平滑。
這個參數(shù)的數(shù)量設(shè)置得太小會引起過擬合,設(shè)置得太大就會阻止模型學(xué)習(xí)數(shù)據(jù)。
一般來說,建議從=5開始使用。如果葉節(jié)點中含有的樣本量變化很大,建議輸入浮點數(shù)作為樣本量的百分比來使用。同時,這個參數(shù)可以保證每個葉子的最小尺寸,可以在回歸問題
中避免低方差,過擬合的葉子節(jié)點出現(xiàn)。對于類別不多的分類問題,=1通常就是最佳選擇。
(3)min_samples_split
min_samples_split限定,一個節(jié)點必須要包含至少min_samples_split個訓(xùn)練樣本,這個節(jié)點才允許被分枝,否則分枝就不會發(fā)生。
min_samples_leaf限制的是子節(jié)點中樣本的個數(shù)。
min_samples_split限制的是當(dāng)前被分隔的節(jié)點中樣本的個數(shù)。
節(jié)點中樣本的個數(shù)越多,泛化能力越強(qiáng)!!!
DecisionTreeObj = tree.DecisionTreeClassifier(criterion="entropy",random_state=30,splitter="random",max_depth=3,min_samples_leaf=10,min_samples_split=10)DecisionTreeObj = DecisionTreeObj.fit(Xtrain, Ytrain)print("訓(xùn)練集分?jǐn)?shù):",DecisionTreeObj.score(Xtrain,Ytrain))print("測試集分?jǐn)?shù):",DecisionTreeObj.score(Xtest,Ytest))dot_data = tree.export_graphviz(DecisionTreeObj,feature_names= feature_name,class_names=["琴酒","雪莉","貝爾摩德"],filled=True,rounded=True) graph = graphviz.Source(dot_data)graph 訓(xùn)練集分?jǐn)?shù): 0.8709677419354839 測試集分?jǐn)?shù): 0.9259259259259259 訓(xùn)練集分?jǐn)?shù): 0.8709677419354839 測試集分?jǐn)?shù): 0.92592592592592592.6 精修參數(shù)max_features & min_impurity_decrease
一般max_depth使用,用作樹的”精修“。
max_features限制分枝時考慮的特征個數(shù),超過限制個數(shù)的特征都會被舍棄。和max_depth異曲同工,
max_features是用來限制高維度數(shù)據(jù)的過擬合的剪枝參數(shù),但其方法比較暴力,是直接限制可以使用的特征數(shù)量而強(qiáng)行使決策樹停下的參數(shù),在不知道決策樹中的各個特征的重要性的情況下,強(qiáng)行設(shè)定這個參數(shù)可能會導(dǎo)致模型學(xué)習(xí)不足。如果希望通過降維的方式防止過擬合,建議使用PCA,ICA或者特征選擇模塊中的降維算法。
min_impurity_decrease限制信息增益的大小,信息增益小于設(shè)定數(shù)值的分枝不會發(fā)生。這是在0.19版本中更新的功能,在0.19版本之前時使用min_impurity_split。
2.7?確認(rèn)最優(yōu)的剪枝參數(shù)
那具體怎么來確定每個參數(shù)填寫什么值呢?這時候,我們就要使用確定超參數(shù)的曲線來進(jìn)行判斷了,繼續(xù)使用我們已經(jīng)訓(xùn)練好的決策樹模型clf。超參數(shù)的學(xué)習(xí)曲線,是一條以超參數(shù)的取值為橫坐標(biāo),模型的度量指標(biāo)為縱坐標(biāo)的曲線,它是用來衡量不同超參數(shù)取值下模型的表現(xiàn)的線。在我們建好的決策樹里,我們的模型度量指標(biāo)就是score。
import matplotlib.pyplot as plt# 存放參數(shù)調(diào)優(yōu)后的打分值 test = []# 動態(tài)調(diào)參:max_depth 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() [0.46296296296296297, 0.9259259259259259, 0.9444444444444444, 0.9629629629629629, 0.9629629629629629, 0.9629629629629629, 0.9629629629629629, 0.9629629629629629, 0.9629629629629629, 0.9629629629629629]?從上圖可以看出:
當(dāng)max_depth變?yōu)?之后,模型的打分的分?jǐn)?shù)就不再進(jìn)一步增長,也就是說,max_depth>4后,以及對模型的優(yōu)化沒有優(yōu)化作用了。
備注:自動優(yōu)化其他參數(shù),也可以采用上述類似的方法。
2.8 目標(biāo)權(quán)重參數(shù):class_weight & min_weight_fraction_leaf
完成樣本標(biāo)簽平衡的參數(shù)。
樣本不平衡是指在一組數(shù)據(jù)集中,有一類樣本特征的樣本數(shù)量特別少,如標(biāo)簽的一類天生占有很大的比例。比如說,在銀行要判斷“一個辦了信用卡的人是否會違約”,就是是vs否(1%:99%)的比例。
這種分類狀況下,即便模型什么也不做,全把結(jié)果預(yù)測成“否”,正確率也能有99%。
因此我們要使用class_weight參數(shù)對樣本標(biāo)簽進(jìn)行一定的均衡,給少量的標(biāo)簽更多的權(quán)重,讓模型更偏向少數(shù)類,向捕獲少數(shù)類的方向建模。該參數(shù)默認(rèn)None,此模式表示自動給與數(shù)據(jù)集中的所有標(biāo)簽相同的權(quán)重。
有了權(quán)重之后,樣本量就不再是單純地記錄數(shù)目,而是受輸入的權(quán)重影響了,因此這時候剪枝,就需要搭配min_weight_fraction_leaf這個基于權(quán)重的剪枝參數(shù)來使用。另請注意,基于權(quán)重的剪枝參數(shù)(例如min_weight_fraction_leaf)將比不知道樣本權(quán)重的標(biāo)準(zhǔn)(比如min_samples_leaf)更少偏向主導(dǎo)類。如果樣本是加權(quán)的,則使用基于權(quán)重的預(yù)修剪標(biāo)準(zhǔn)來更容易優(yōu)化樹結(jié)構(gòu),這確保葉節(jié)點至少包含樣本權(quán)重的總和的一小部分。
2.9 其他重要的屬性與API
屬性是在模型訓(xùn)練之后,能夠調(diào)用查看的模型的各種性質(zhì)。對決策樹來說,最重要的是feature_importances_,能夠查看各個特征對模型的重要性。
sklearn中許多算法的接口都是相似的,比如說我們之前已經(jīng)用到的fit和score,幾乎對每個算法都可以使用。
除了這兩個接口之外,決策樹最常用的接口還有apply和predict。
apply中輸入測試集返回每個測試樣本所在的葉子節(jié)點的索引,
predict輸入測試集返回每個測試樣本的標(biāo)簽。返回的內(nèi)容一目了然并且非常容易,
另外,所有接口中要求輸入X_train和X_test的部分,輸入的特征矩陣必須至少是一個二維矩陣。
sklearn不接受任何一維矩陣作為特征矩陣被輸入。
如果你的數(shù)據(jù)的確只有一個特征,那必須用reshape(-1,1)來給矩陣增維;
如果你的數(shù)據(jù)只有一個特征和一個樣本,使用reshape(1,-1)來給你的數(shù)據(jù)增維。
#apply返回每個測試樣本在決策上中的位置 print("\n每個樣本在決策樹上的位置", clf.apply(Xtest))#predict返回每個測試樣本的預(yù)測結(jié)果 print("\n每個樣本的預(yù)測結(jié)果\n", clf.predict(Xtest))print("\n每個特征的重要程度:\n", clf.feature_importances_) 每個樣本在決策樹上的位置 [13 7 17 17 13 13 11 13 17 11 11 8 4 4 7 4 7 17 11 13 17 11 4 174 4 11 17 4 13 4 8 17 4 13 13 4 4 17 17 4 11 15 17 11 17 4 114 4 4 11 11 7]每個樣本的預(yù)測結(jié)果[1 2 0 0 1 1 1 1 0 1 1 1 2 2 2 2 2 0 1 1 0 1 2 0 2 2 1 0 2 1 2 1 0 2 1 1 22 0 0 2 1 1 0 1 0 2 1 2 2 2 1 1 2]每個特征的重要程度:[0.22216858 0. 0. 0.03661358 0.02534749 0.0.44666311 0. 0. 0. 0.07418021 0.146158320.0488687 ]作者主頁(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文網(wǎng)址:
總結(jié)
以上是生活随笔為你收集整理的[机器学习与scikit-learn-15]:算法-决策树-分类问题代码详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [初级理论]给老婆做测试培训-02
- 下一篇: 模拟T1数字number