sklearn中的決策樹
一、sklearn中的決策樹模組:sklearn.tree
1、sklearn中決策樹的類都在‘tree’這個模組之下。這個模組 總共包含五個類:
2、sklearn的基本建模流程
3、下面對sklearn.tree這個模組之下的決策樹類進行逐個說明:
3.1、分類樹:tree.DecisionTreeClassifier()
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)
重要引數:
(1)criterion:
Criterion這個引數正是用來決定不純度的計算方法的。sklearn提供了兩種選擇:
1)輸入”entropy“,使用資訊熵(Entropy)
2)輸入”gini“,使用基尼係數(Gini Impurity)
(2)random_state & splitter:
random_state用來設定分枝中的隨機模式的引數,預設為None,設定的話,是為了保證每次隨機生成的數是一致的(即使是隨機的);
如果不設定,那麼每次生成的隨機數都是不同的,也就是說決策樹其實是隨機的(可以通過多執行幾次score測試下)。
splitter也是用來控制決策樹中的隨機選項的,有兩種輸入值:
1)輸入”best",決策樹在分枝時雖然隨機,但是還是會優先選擇更重要的特徵進行分枝。重要性可以通過屬性feature_importances_檢視。
2)輸入“random",決策樹在分枝時會更加隨機,樹會因為含有更多的不必要資訊而更深更大,並因這些不必要資訊而降低對訓練集的擬合。這也是防止過擬合的一種方式。
當你預測到你的模型會過擬合,用這兩個引數來幫助你降低樹建成之後過擬合的可能性。當然,樹一旦建成,我們依然是使用剪枝引數來防止過擬合。
(3)剪枝引數:
註釋:不加限制時,決策樹會生長到沒有更多的特徵可用為止,但這樣往往會造成過擬合,既訓練集上表現很好,測試集上表現卻很差。因此為了讓模型有更好的泛化性,我們需要
對決策樹進行剪枝。
1)剪枝引數1:max_depth
目的:限制樹的最大深度,超過設定深度的樹枝全部剪掉。在高緯度低樣本量時非常有效,決策樹每多生長一層,對樣本的需求量會增加一倍。所以限制樹的深度有利於防止過擬合。
建議:實際使用時,建議從=3開始嘗試,看看擬合的效果在決定是否增加深度。
2)剪枝引數2:min_samples_leaf & min_samples_split
min_samples_leaf : 該引數限定,一個節點在分枝後的每個子節點都必須包含至少min_samples_leaf個訓練樣本,否則分支就不會發生。
建議:該引數設定的太小會引起過擬合,太大會阻止模型學習資料,一般搭配max_depth使用。
min_samples_split : 該引數限定,一個節點必須包含至少min_samples_split個訓練樣本,這個節點才允許被分枝,否則分支就不會發生。
3)剪枝引數3:max_features & min_impurity_decrease
max_features : 該引數限定,分枝時需考慮的特徵個數,超過限制個數的特徵都會被捨棄。該引數是用來限制高緯度資料的過擬合的剪枝引數。
min_impurity_decrease : 該引數限定資訊增益的大小,資訊增益小於設定數值的分枝不會發生。為0.19版本中更新的功能,0.19版本之前使用的時min_impurity_split。
4)確定最優的剪枝引數的時候,可以採取如下方式:
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()
(4)目標權重引數:
1)class_weight & min_weight_fraction_leaf
class_weight :
該引數預設為None,表示自動給資料集中所有標籤相同的權重
該引數為‘blanced’時,每個類別的權重為該類別樣本數的倒數。個人覺得懲罰項就用樣本量的倒數未嘗不可,因為乘以樣本量都是1,相當於'balanced'這裡是多乘以了一個常數.
也可手動輸入權重,程式碼舉例如下:
import numpy as np
y = [0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,2] #標籤值,一共16個樣本
from sklearn.utils.class_weight import compute_class_weight
class_weight = {0:1,1:3,2:5} # {class_label_1:weight_1, class_label_2:weight_2, class_label_3:weight_3}
classes = np.array([0, 1, 2]) #標籤類別
weight = compute_class_weight(class_weight, classes, y)
print(weight) # 輸出:[1. 3. 5.],也就是字典中設定的值
min_weight_fraction_leaf : 有了權重之後,樣本量就不再是單純地記錄數目,而是受輸入的權重影響了,因此這時候剪枝,就需要搭配min_weight_fraction_leaf這個基於權重的剪枝引數來使用。
附::tree.DecisionTreeClassifier中的重要屬性與介面如下:
#對資料進行擬合
clf.fit(Xtrain,Ytrain)
#求得測試集的準確率
clf.score(Xtest,Ytest)
#apply返回每個測試樣本所在的葉子節點的索引
clf.apply(Xtest)
#predict返回每個測試樣本的分類/迴歸結果
clf.predict(Xtest)
總結:分類樹需要掌握的八個引數,一個屬性,四個介面:
八個引數:Criterion,兩個隨機性相關的引數(random_state,splitter),五個剪枝引數(max_depth,
min_samples_split,min_samples_leaf,max_feature,min_impurity_decrease)
一個屬性(該引數用於檢視哪個特徵對預測結果貢獻最大):feature_importances_
四個介面:fit,score,apply,predict
3.2、tree.DecisionTreeRegressor
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這樣的引數。
3.2.1重要引數屬性及介面:
(1)criterion:
1)輸入‘mse’ : 使用均方誤差。mse的公式如下:
其中N是樣本數量,i是每一個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤。MSE的本質是樣本真實資料與迴歸結果的差異。
2)輸入‘friedman_mse’ : 使用費爾德曼均方誤差。
3)輸入‘mae’ : 使用絕對平均誤差MAE(mean absolute error)
(2)重要屬性:最重要的依然是feature_importances_
(3)重要介面:依然是apply,fit,pridect,score最核心。
3.2.2 介面score
迴歸樹的介面score返回的是R平方,並不是MSE。R平方被定義如下:
其中u是殘差平方和(MSE*N),v是總平方和,N是樣本數量,i是每一個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤,y帽是真實數值標籤
的平均數。R平方可以為正也可為負,當模型的殘差平方和遠遠大於模型的總平方和,模型非常糟糕,R平方就會為負,而均方誤差永遠為正。但在sklearn中,
雖然均方誤差永遠為正,但是sklearn當中使用軍方誤差作為評判標準時,卻是計算的‘負均方誤差’,這是因為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()
regressor = DecisionTreeRegressor(random_state=0)
cross_val_score(regressor, boston.data, boston.target, cv=10,
scoring = "neg_mean_squared_error")
3.3、tree.export_graphviz()
目的:繪圖專用,將生成的決策樹轉化為dot格式,方便視覺化。
例項:
例1:
feature_name = ['酒精','蘋果酸','灰','灰的鹼性','鎂','總酚','類黃酮','非黃烷類酚類','花青素','顏色強度','色調','od280/od315稀釋葡萄酒','脯氨酸']
import graphviz
dot_data = tree.export_graphviz(clf
,feature_names= feature_name
,class_names=["琴酒","雪莉","貝爾摩德"] # 標籤名字
,filled=True # 到底填不填充顏色,顏色越深,代表不純度越低,且葉子節點的每個顏色代表一個類別。
,rounded=True # 框的形狀
,out_file=None
)
graph = graphviz.Source(dot_data) # 將我們畫的樹給匯出來
graph
例2:
dot_data = tree.export_graphviz(clf
,out_file=None,
,feature_names=iris.feature_names
,class_names=iris.target_names
,filled=True
,rounded=True
,special_characters=True
)
graph = graphviz.Source(dot_data)
graph
其中,out_file為dot輸出的目錄;
feature_names為特徵的名字;
class_names為標籤的名字;
filled=True,到底填補填充顏色,顏色越深,代表不純度越低,且葉子節點的每個顏色代表一個類別。
rounded=True,為框的形狀。
高隨機版本的分類樹和迴歸樹暫時先不記筆記。