決策樹模型以及python實現

參考:菜菜的sklearn課堂

決策樹是一個非常常見並且優秀的機器學習算法,它易於理解、可解釋性強,其可作爲分類算法,也可用於迴歸模型。

一、什麼是決策樹?

決策樹,顧名思義就是一個類似於流程圖的樹型結構。一個決策樹由根結點、分支和葉結點構成。樹的最高層節點稱爲根結點,是整個決策樹的開始。與根結點相連的不同分支,對應這個屬性的不同取值,根據不同的回答轉向相應的分支,在新到達的結點處做同樣的分支判斷,持續這一過程直到到達某個葉結點。在決策樹中,每個內部結點表示一個測試,該結點的每個分支表示該測試的一個結果,每個葉結點表示一個類別。

在這裏插入圖片描述
來源

決策樹是有監督學習中的一種算法,並且是一種基本的分類與迴歸的方法。也就是說,決策樹有兩種:分類樹和迴歸樹。

分類樹

分類決策樹學習本質:從訓練數據集中歸納出一組分類規則。

決策樹的核心問題

  1. 如何找出正確的特徵來進行提問,即如何分枝
  2. 樹生長到什麼時候應該停下

用來衡量分枝質量的指標不純度,分類樹的不純度用基尼係數或信息熵來衡量,迴歸
樹的不純度用MSE均方誤差來衡量。每次分枝時,決策樹對所有的特徵進行不純度計算,選取不純度最低的特徵進行分枝,分枝後,又再對被分枝的不同取值下,計算每個特徵的不純度,繼續選取不純度最低的特徵進行分枝。

每分枝一層,樹整體的不純度會越來越小,決策樹追求的是最小不純度。因此,決策樹會一致分枝,直到沒有更多的特徵可用,或整體的不純度指標已經最優,決策樹就會停止生長。

二、主要的算法

建立決策樹的關鍵,即在當前狀態下選擇哪個屬性作爲分類依據。根據不同的目標函數,建立決策樹主要有以下三種算法。

算法 核心
ID3 信息熵
C4.5 信息增益比
CART 基尼係數

2.1 ID3算法

ID3是決策樹學習算法中最具有影響和最爲典型的算法,它的基本思想是,利用信息熵的原理,選擇信息增益最大的屬性作爲分類屬性。

ID3 算法流程圖
在這裏插入圖片描述

熵(信息量):在信息論中,是接收的每條信息中包含的信息的平均量。表示隨機變量不確定性的度量。熵越大,隨機變量的不確定性就越大

隨機變量X的熵定義爲:
H(X)=i=1npilogpi H\left( X \right) =-\sum_{i=1}^n{p_i\log p_i}
熵一就分類而言,所有成員都屬於一類,熵爲零;不同類別數目相等,則熵等於1;類別數目不等,則熵介於0~1之間。

熵(信息量)隨概率p變化的曲線如下圖:

在這裏插入圖片描述

可知,當 p=0 或 p=1 時,H=0,隨機變量完全沒有不確定性,即是完全確定的。

條件熵:條件熵H(YX)H\left( Y|X \right)表示在已知隨機變量 X 的條件下隨機變量 Y 的不確定性。
H(YX)=i=1npiH(YX=xi) , pi=P(X=xi) , i=1,2,,n H\left( Y|X \right) =\sum_{i=1}^n{p_iH\left( Y|X=x_i \right)}\ ,\ p_i=P\left( X=x_i \right) \ ,\ i=1,2,\cdots ,n

信息增益:信息增益表示得知特徵 X 的信息而使得類Y的信息不確定性減少的程度。

特徵 A 對訓練數據集 D 的信息增益g(D,A)g\left( D,A \right),定義爲集合 D 的經驗熵 H(D)H\left( D \right) 與特徵A給定條件下D的經驗條件熵 H(D|A) 之差。

g(D,A)=H(D)H(DA) g\left( D,A \right) =H\left( D \right) -H\left( D|A \right)

根據信息增益準則的特徵選擇方法是:對訓練數據集(或子集D),計算其每個特徵的信息增益,並比較它們的大小,選擇信息增益最大的特徵。

2.2 C4.5 算法

C4.5算法是ID3算法的改進,它繼承了ID3算法的優點並對ID3算法進行了改進和補充。

C4.5算法採用信息增益比作爲選擇分支屬性的標準,克服了ID3算法中信息增益選擇屬性時偏向選擇取值多的屬性的不足,並能夠完成對連續屬性離散化的處理,還能夠對不完整數據進行處理。

信息增益比:

特徵 A 對訓練數據集 D 的信息增益比 gR(D,A)g_R\left( D,A \right) 定義爲其信息增益 g(D,A)g\left( D,A \right) 與訓練數據集 D 關於特徵 A 的值的熵 HA(D)H_A\left( D \right) 之比,即

gR(D,A)=g(D,A)HA(D) g_R\left( D,A \right) =\frac{g\left( D,A \right)}{H_A\left( D \right)}

2.3 CART 算法

ID3 和 C4.5 雖然在對訓練樣本集的學習中可以儘可能多地挖掘信息,但是其生成的決策樹分支、規模都比較大,CART 算法的二分法可以簡化決策樹的規模,提高生成決策樹的效率。

熵模型擁有大量耗時的對數運算,基尼指數在簡化模型的同時還保留了熵模型的優點。基尼指數代表了模型的不純度,基尼係數越小,不純度越低,特徵越好。這和信息增益(率)正好相反。

基尼指數反映了從數據集中隨機抽取兩個樣本,其類別標記不一致的概率。因此基尼指數越小,則數據集純度越高。基尼指數偏向於特徵值較多的特徵,類似信息增益。基尼指數可以用來度量任何不均勻分佈,是介於 0~1 之間的數,0 是完全相等,1 是完全不相等。

三、過度擬合

如果決策樹對訓練樣本的特徵描述得“過於精確”,無法實現對新樣本的合理分析,所以此時它不是一棵分析新數據的最佳決策樹。一棵完全決策樹能非常準確地反映訓練數據的特徵,但因失去了一般代表性而無法用於對新數據的分類或預測,這種現象一般稱爲“過擬合”。

3.1 產生過度擬合數據問題的原因有哪些 ?

原因1:樣本問題
(1) 樣本里的噪音數據干擾過大,大到模型過分記住了噪音特徵,反而忽略了真實的輸入輸出間的關係;

(2) 樣本抽取錯誤,包括(但不限於)樣本數量太小,抽樣方法錯誤,抽樣時沒有足夠正確考慮業務場景或業務特點等等,導致抽出的樣本數據不能有效足夠代表業務邏輯或業務場景;

(3) 建模時使用了樣本中太多無關的輸入變量。

原因2:構建決策樹的方法問題

在決策樹模型搭建中,使用的算法對於決策樹的生長沒有合理的限制和修剪,決策樹的自由生長有可能每片葉子裏只包含單純的事件數據或非事件數據。

3.2 如何解決過度擬合數據問題 ?

針對原因1的解決方法:

合理、有效地抽樣,用相對能夠反映業務邏輯的訓練集去產生決策樹;

針對原因2的主要解決方法:

剪枝:提前停止樹的增長或對已經生長的樹按照一定的規則進行後剪枝。

決策樹生成算法對於訓練集是很準確的,但是會造成過度擬合,所以需要通過剪枝來提高泛化能力。剪枝思路:就是在決策樹對訓練數據的預測誤差和樹複雜度之間找到一個balance。

四、分類決策樹模型python實現

4.1 sklearn的基本建模流程

在這裏插入圖片描述
在這裏插入圖片描述

from sklearn import tree #導入需要的模塊
clf = tree.DecisionTreeClassifier()   #實例化
clf = clf.fit(X_train,y_train) #用訓練集數據訓練模型
result = clf.score(X_test,y_test) #導入測試集,從接口中調用需要的信息

4.2 決策樹的基本流程

決策樹構建過程可以概括爲3個步驟:特徵選擇、決策樹的生成和決策樹的剪枝。
在這裏插入圖片描述

4.3 安裝和配置graphviz

進入官網 Graphviz - Graph Visualization Software

https://graphviz.gitlab.io/_pages/Download/Download_windows.html

在這裏插入圖片描述
下載完畢後雙擊msi文件,開始進行安裝:
在這裏插入圖片描述
在這裏插入圖片描述

設置環境變量
在這裏插入圖片描述
在這裏插入圖片描述
配置完成後,進入cmd運行如下命令:

dot -version

如果顯示出相應的graphviz信息,則配置就是完成了
在這裏插入圖片描述
安裝到python

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple graphviz

4.4 分類決策樹參數

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參數

Criterion這個參數正是用來決定不純度的計算方法的。sklearn提供了兩種選擇:

  • 輸入”entropy“,使用信息熵
  • 輸入”gini“,使用基尼係數

爲了要將表格轉化爲一棵樹,決策樹需要找出最佳節點和最佳的分枝方法,對分類樹來,衡量這個“最佳”的指標叫做“不純度”,不純度越低,決策樹對訓練集的擬合越好

在實際使用中,信息熵和基尼係數的效果基本相同

信息熵作爲指標時,決策樹的生長會更加“精細”,因此對於高維數據或者噪音很多的數,信息熵很容易過擬合

怎樣選取參數?

通常就使用基尼係數,數據維度很大,噪音很大時使用基尼係數維度低,數據比較清晰的時候,信息熵和基尼係數沒區別,當決策樹的擬合程度不夠的時候,使用信息熵。兩個都試試,不好就換另外一個

4.5 例1——鳶尾花數據

from sklearn.datasets import load_iris
from sklearn import tree
import graphviz
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)
dot_data = tree.export_graphviz(clf, out_file=None)
graph = graphviz.Source(dot_data)
graph.render("iris")

在這裏插入圖片描述在這裏插入圖片描述

4.6 例2——紅酒數據集

import pandas as pd
import graphviz
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
wine = load_wine()
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)

# 分訓練集和測試集
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
# 建立模型
clf = tree.DecisionTreeClassifier(criterion="entropy",
									random_state=30, # 設置分枝中的隨機模式的參數,默認None,在高維度時隨機性會表現更明顯
									splitter="random" # 控制決策樹中的隨機選項
									)
# 訓練
clf = clf.fit(Xtrain, Ytrain) 
#返回預測的準確度
score = clf.score(Xtest, Ytest) 
score  # 0.96

feature_name = ['酒精','蘋果酸','灰','灰的鹼性','鎂','總酚','類黃酮','非黃烷類酚類','花青素','顏色強度','色調','od280/od315稀釋葡萄酒','脯氨酸']
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

在這裏插入圖片描述

4.7 特徵重要性

[*zip(feature_name,clf.feature_importances_)]

# [('酒精', 0.05911575203482781),
#  ('蘋果酸', 0.0),
#  ('灰', 0.0),
#  ('灰的鹼性', 0.0),
#  ('鎂', 0.0),
#  ('總酚', 0.0),
#  ('類黃酮', 0.5140132157873617),
#  ('非黃烷類酚類', 0.0),
#  ('花青素', 0.0),
#  ('顏色強度', 0.27432826744953076),
#  ('色調', 0.0),
#  ('od280/od315稀釋葡萄酒', 0.0),
#  ('脯氨酸', 0.15254276472827968)]

4.8 剪枝參數

在不加限制的情況下,一棵決策樹會生長到衡量不純度的指標最優,或者沒有更多的特徵可用爲止。這樣的決策樹往往會過擬合,這就是說,它會在訓練集上表現很好,在測試集上卻表現糟糕。我們收集的樣本數據不可能和整體的狀況完全一致,因此當一棵決策樹對訓練數據有了過於優秀的解釋性,它找出的規則必然包含了訓練樣本中的噪聲,並使它對未知數據的擬合程度不足。

樹對訓練集的擬合程度如何?
score_train = clf.score(Xtrain, Ytrain)
score_train

# 1.0

爲了讓決策樹有更好的泛化性,我們要對決策樹進行剪枝。剪枝策略對決策樹的影響巨大,正確的剪枝策略是優化決策樹算法的核心。sklearn爲我們提供了不同的剪枝策略:

  • max_depth
    限制樹的最大深度,超過設定深度的樹枝全部剪掉
    決策樹多生長一層,對樣本量的需求會增加一倍,所以限制樹深度能夠有效地限制過擬合。實際使用時,建議從=3開始嘗試,看看擬合的效果再決定是否增加設定深度。

  • min_samples_leaf
    限定一個節點在分枝後的每個子節點都必須包含至少min_samples_leaf個訓練樣本,否則分枝就不會發生,或者,分枝會朝着滿足每個子節點都包含min_samples_leaf個樣本的方向去發生。一般搭配max_depth使用,在迴歸樹中有神奇的效果,可以讓模型變得更加平滑。一般來說,建議從=5開始使用。

  • min_samples_split
    限定,一個節點必須要包含至少min_samples_split個訓練樣本,這個節點才允許被分枝,否則分枝就不會發生。

調試

clf = tree.DecisionTreeClassifier(criterion="entropy",
                                  random_state=0,
                                  splitter="random",
                                  max_depth=5,
                                   # min_samples_leaf=10,
                                  # min_samples_split=10,
                                  )
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回預測的準確度
score  # 得分

0.9629629629629629
clf = tree.DecisionTreeClassifier(criterion="entropy",
                                  random_state=0,
                                  splitter="random",
                                  max_depth=5,
                                  min_samples_leaf=10,
                                  # min_samples_split=10,
                                  )
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回預測的準確度
score  # 得分

0.9259259259259259
clf = tree.DecisionTreeClassifier(criterion="entropy",
                                  random_state=0,
                                  splitter="random",
                                  max_depth=5,
                                  # min_samples_leaf=10,
                                  min_samples_split=10,
                                  )
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回預測的準確度
score  # 得分

0.9814814814814815
  • max_features
    限制分枝時考慮的特徵個數,超過限制個數的特徵都會被捨棄。用來限制高維度數據的過擬合的剪枝參數

  • min_impurity_decrease
    限制信息增益的大小,信息增益小於設定數值的分枝不會發生。

4.9 確認最優的剪枝參數

那具體怎麼來確定每個參數填寫什麼值呢?這時候,我們就要使用確定超參數的曲線來進行判斷了,繼續使用我們已經訓練好的決策樹模型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()

在這裏插入圖片描述
在 max_depth=4 時,得分最高

剪枝參數的默認值會讓樹無盡地生長,這些樹在某些數據集上可能非常巨大,對內存的消耗也非常巨大。所以如果你手中的數據集非常巨大,你已經預測到無論如何你都是要剪枝的,那提前設定這些參數來控制樹的複雜性和大小會比較好。

4.10 目標權重參數

  • class_weight
    使用class_weight參數對樣本標籤進行一定的均衡,給少量的標籤更多的權重,讓模型更偏向少數類,向捕獲少數類的方向建模。該參數默認None,此模式表示自動給
    與數據集中的所有標籤相同的權重。

  • min_weight_fraction_leaf
    有了權重之後,樣本量就不再是單純地記錄數目,而是受輸入的權重影響了,因此這時候剪枝,就需要搭配min_weight_fraction_leaf這個基於權重的剪枝參數來使用。

4.11 重要屬性和接口

#apply返回每個測試樣本所在的葉子節點的索引
clf.apply(Xtest)
Out[63]: 
array([2, 2, 6, 5, 5, 5, 5, 5, 6, 5, 6, 3, 2, 5, 6, 5, 2, 5, 3, 2, 2, 2,
       3, 6, 2, 6, 5, 6, 3, 6, 2, 2, 3, 5, 6, 6, 3, 3, 2, 5, 6, 5, 2, 5,
       5, 2, 6, 6, 3, 6, 3, 2, 6, 5], dtype=int64)

#predict返回每個測試樣本的分類/迴歸結果
clf.predict(Xtest)
Out[64]: 
array([2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 2, 0, 1, 2, 2, 2,
       1, 0, 2, 0, 0, 0, 1, 0, 2, 2, 1, 0, 0, 0, 1, 1, 2, 0, 0, 0, 2, 0,
       0, 2, 0, 0, 1, 0, 1, 2, 0, 0])

迴歸樹

幾乎所有參數、屬性及接口都和分類樹一模一樣。在迴歸樹中,沒有標籤分佈是否均衡的問題,因此沒有class_weight這樣的參數。

重要參數,屬性及接口

criterion

迴歸樹衡量分枝質量的指標,支持的標準有三種:

1)輸入"mse"使用均方誤差,父節點和葉子節點之間的均方誤差的差額將被用來作爲特徵選擇的標準,這種方法通過使用葉子節點的均值來最小化L2損失

mse就是樣本真實數據與迴歸結果的差異。在迴歸樹中,MSE不只是分枝質量衡量指標,也是最常用的衡量回歸樹迴歸質量的指標,當我們在使用交叉驗證,或者其他方式獲取迴歸樹的結果時,往往選擇均方誤差作爲評估(在分類樹中這個指標是score代表的預測準確率)。在迴歸中,我們追求的是,MSE越小越好。

迴歸樹的接口score返回的是R平方,並不是MSE

雖然均方誤差永遠爲正,但是sklearn當中使用均方誤差作爲評判標準時,卻是計算”負均方誤差“

2)輸入“friedman_mse”使用費爾德曼均方誤差,這種指標使用弗裏德曼針對潛在分枝中的問題改進後的均方誤差
3)輸入"mae"使用絕對平均誤差MAE(mean absolute error),這種指標使用葉節點的中值來最小化L1損失屬性中最重要的依然是feature_importances_,接口依然是apply, fit, predict, score最核心。

交叉驗證

是用來觀察模型的穩定性的一種方法,將數據劃分爲n份,依次使用其中一份作爲測試集,其他n-1份作爲訓練集,多次計算模型的精確性來評估模型的平均準確程度。訓練集和測試集的劃分會干擾模型的結果,因此用交叉驗證n次的結果求出的平均值,是對模型效果的一個更好的度量。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章