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