一份你意想不到的決策樹學習指南!幾乎整合了現在所有決策樹知識,希望對大家的學習有所幫助。
介紹
你一生中沒有哪一天不需要做出決定。從早餐吃什麼到你感興趣的職業,你的生活都被決策所包圍。假設你想出去打球,出門前你會考慮哪些因素?今天會下雨嗎?外面會不會太熱?作為一名籃球愛好者,你都要被迫接受最後的決定。你從氣象部門的網站上查了過去幾天的數據,將這些數據與今天的天氣狀況進行比較,並預測這些條件對於籃球比賽來說是否完的。這就是決策樹解決實際問題的途徑。
在繼續使用決策樹的實際功能之前,您需要熟悉以下術語-
- 基尼不純度(Gini Impurity)
- 熵(Entropy)
基尼不純度與熵
舉例:有兩個人感到很無聊,所以他們決定玩一個遊戲。誰能最快找到的一根線,最好能夠恰好分離藍色和橙色點,誰就能贏得比賽,唯一的限制是直線必須與任何軸平行。
兩人都試了很多方法,找到了以下的線:
從圖片就可以很容易看出,喬的嘗試比山姆的嘗試要好得多,僅是通過直觀地顯示這些要點即可。 但是,當我們有兩種以上的顏色時,事情可能會變得瘋狂。 需要一個定量值來判斷分裂, 那就是基尼不純度出現的原因。 它討論了錯誤分類點的可能性。
沒聽懂嗎?
讓我們先假設條件,然後再進行分裂,即圖1。將點錯誤分類的概率是多少?
我們可以通過兩種方式對點進行錯誤分類。 首先,我們選擇一個藍點並將其分類為橙色。 其次,我們選擇一個橙色的點並將其分類為藍色。
以及
總概率= 0.25 + 0.25 = 0.5(開始時為基尼不純度)
數據中的任何分割都會將該區域分為兩個或更多部分。 最終的基尼不純度是通過將所有部分的加權和求出的。 基尼不純度越小,分離效果越好。
讓我們分析一下Joe的嘗試:
同樣,我們也可以分析Sam的嘗試:
兩次的嘗試均顯著降低了原始的基尼不純度,但是Joe進行了更好的拆分,因為基尼不純度的增益G(之前)-G(之後)對於他的拆分更大。
假設Y是一個隨機變量,其取值為{y 1,y 2,y 1,…。,y 1},那麼一種簡單的計算基尼不純度的方法是:
基尼不純度的性質
令Y取值y₊,y₋(兩個類)
情況一:
當100%的數據點屬於y₊時。 在這種情況下,系統的基尼不純度為:
情況二:
當50%的數據點屬於y₊時。 在這種情況下,系統的基尼不純度為:
情況三:
當0%的數據點屬於y₊時。 在這種情況下,系統的基尼雜質為:
基尼不純度w.r.t與y₊的關係圖將變為:
接下來,讓我們來說說熵。
簡單來說,熵就是數據的隨機性。 假設您前面有兩個盒子。 盒子1裝滿藍色球,盒子2裝滿不同顏色的球。
現在從每個盒子裡抽出一個球。你認為從盒子1中抽出的球的顏色最有可能是什麼?藍色,對吧?你能用從2號盒子抽出的球來預測同樣的結果嗎?我想不是。與盒子1不同,盒子2具有很多隨機性。恭喜,你已經明白了熵的含義!如果選擇熵作為度量標準,決策樹將以這樣一種方式拆分數據:每次拆分時,數據的隨機性都會不斷降低。
假設Y是一個隨機變量,取{Y₁,Yü,Y₃,…,Yₖ}的值,則系統的熵計算如下:
熵的性質
令Y取值y₊,y₋(兩個類)
情況一:
當99%的數據點屬於y₊時,系統的熵在這種情況下為:
情況二:
當50%的數據點屬於y₊時。 在這種情況下,系統的熵為:
情況三:
當1%的數據點屬於y₊時。 在這種情況下,系統的熵為:
H(y)w.r.t與y₊的關係圖將變為:
必須注意的是,當所有值發生的可能性相等時,熵變為最大值=1。
到現在為止,一直都還不錯。但是如何利用熵來分割數據呢?
與基尼增益類似,我們使用信息增益(I.G)來決定要分割的最佳特徵。
定義如下:
為什麼基尼雜質大於熵?
熵涉及對數計算,而基尼雜質涉及平方計算,計算成本較低,這就是Sklearn庫使用基尼雜質作為默認選擇標準來構建決策樹的原因。
然而,它們之間的差異被觀察到是很小的,我們可以繼續使用這兩個指標中的任何一個。
構建決策樹的步驟
- 決定要斷開/拆分數據的特徵:對於每個特徵,計算信息增益,並選擇信息增益最大的特徵。
- 繼續拆分數據
- 如果出現以下情況,請停止拆分數據:
a) 我們得到一個純節點,即只包含正或負數據點的節點,或者
b) 我們在一個節點上得到很少的點,或者
c) 我們到達樹的一定深度
一旦您建立了一個決策樹,對於一個查詢點,從根遍歷樹到適當的葉節點。如果葉節點是純節點,則預測查詢點對應的類標籤,否則執行多數表決。
分割分類特徵
假設我們的數據集是:
有兩個特徵, 如果只有一個特徵,我們沒有其他選擇。 但是,當我們具有多個特徵時,我們需要查看在拆分後提供最大信息增益的特徵。
從特徵F₁開始:
獲得的信息將是:
現在檢查特徵F2:
(IG)2獲得的信息將是:
由於IG2> IG1,我們將首先使用特徵F2分割數據。 注意,可以使用特徵F1進一步分解F2 = IND之後的節點。 最終的樹如下圖:
直觀
讓我們使用簡單的if-else條件重寫上述決策樹:
這只是你的決策樹。
在編程上,決策樹只不過是一系列if-else條件語句。
在幾何上,它是一組軸平行的超平面。
分割數值特徵
假設我們的數據集是:
- 按F₁的值排序
- 如果我們使用F₁取每一個值進行分割
你可以看到,每個節點中只有一個值,這會導致數據過擬合。
解決此問題的方法是定義一個閾值,然後將數據分為兩部分-一部分的值小於和等於閾值,另一部分的值大於該閾值。
如何確定閾值?
我們檢查每個可能的閾值的信息增益,並選擇使其最大化的值。在這裡,如果我們使用F₁=4.2分割數據,信息增益將是最大的。
具有多個類別的分類特徵
我們已經看到了如何處理分類和數字特徵。然而,當一個分類特性有許多分類時,事情會變得瘋狂。
假設我們有一個pin代碼特性,它可能有1000個pin代碼,當我們使用這個特性分割數據時,它將創建1000個子節點,每個節點都有很少的數據點,這將導致過度擬合。
一個技巧是將分類特徵轉換為數字特徵。
代替pin碼,我們可以有一個新功能:
所以,現在如果我們使用這個新特性分割數據,子節點將有足夠的點來避免過度擬合。
過擬合和欠擬合
當決策樹的深度越深,在底部節點出現的數據點就越少,如果這些數據點是離群點,那麼我們的模型就會過擬合。由於每次拆分都只是一個if-else條件語句,因此模型的可解釋性也會隨著樹的深度的增加而降低。
當樹太淺時,我們可能得不到任何純節點,純節點是隻有正或負點的節點。在這種情況下,我們必須進行多數表決才能得到結果。
那麼決策樹的深度應該是多少?
深度是一個超參數,必須使用交叉驗證數據集執行超參數調整以獲得最佳值。
訓練和測試時間複雜性
訓練時間複雜性:
在訓練階段會發生的情況是,對於數據集中的每個特徵(維度),我們將對數據進行排序(時間為O(n log n)),然後遍歷數據點以找到正確的閾值(時間為O( n)時間。 對於d維,總時間複雜度為:
訓練空間複雜性:
訓練決策樹時,我們需要的是通常以if-else條件存儲的節點。
因此,訓練空間的複雜性為:O(節點)
測試時間的複雜性為O(深度),因為我們必須從決策樹的根節點移動到葉節點。
測試空間的複雜性為O(節點)。
使用決策樹進行迴歸
當我們處理迴歸問題時,情況會發生變化。 這裡的輸出不再是一個類,而是一個實數值。
我們如何分割數據?
與分類時的熵或基尼不純度不同,我們將使用均方誤差(MSE)或中位數絕對偏差(MAD)來分割數據。 選擇分裂最多的MSE或MAD功能。
我們如何預測測試數據點的價值?
一旦到達葉節點,我們將獲取那裡已經存在的點的平均值/中位數,並預測其將成為給定測試數據點的輸出值。
真實案例
- 不平衡的數據集:建議通過上採樣或類權重來平衡數據集,因為這可能會影響熵值。
- 高維數據:隨著維數的增加,訓練的計算時間也增加。建議如果一個特徵具有多個類別,則應避免使用一鍵編碼,而應如上所述將其轉換為數字特徵。
- 多類別分類:決策樹自然可以擴展為處理多個類別。由於可以計算2類以上的熵或基尼雜質,因此也可以通過多數表決做出決定。
- 特徵交互:由於子節點的條件取決於父節點的條件,因此在遍歷路徑中一起出現的要素相互交互
- 離群值:如果樹很深,離群值會影響樹並使樹變得不穩定。
- 可解釋性:由於決策樹不過是if-else語句的集合,因此它是高度可解釋的。但是,隨著樹的深度增加,可解釋性降低。
- 功能重要性:信息獲取量高的那些功能很重要。如果一個功能不止一次用於分割,我們將使用歸因於該功能的信息增益的歸一化總和。
好處
- 不需要縮放或標準化數據
- 高解釋性,尤其是當維數較少時
- 在低延遲系統中有用
- 更少的超參數數量
- 適用於分類數據和數值數據
- 容易明白
侷限性
- 通常需要更多時間來訓練模型
- 當您具有高維數據時,可能不適合
- 過度擬合數據的可能性很高
- 數據的微小變化會導致決策樹結構的整體變化
- 樹越深越複雜
- 決策樹通常不具備其他分類或迴歸算法那樣的預測準確性
使用Python構建決策樹
<code>import
numpyas
npimport
pandasas
pdfrom
sklearn.datasetsimport
make_classificationimport
warningsfrom
sklearn.treeimport
plot_treeimport
matplotlib.pyplotas
pltfrom
sklearn.treeimport
DecisionTreeClassifierfrom
sklearn.model_selectionimport
train_test_splitfrom
sklearn.model_selectionimport
RandomizedSearchCVfrom
scipy.statsimport
randint warnings.filterwarnings('ignore'
) X, y = make_classification(n_samples=50
, n_features=3
, n_informative=3
,n_redundant=0
,n_classes=2
, weights=[0.6
], random_state=15
) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25
, random_state=15
,stratify=y) random_search = {"max_depth"
: list(range(2
,7
))+[None
],"min_samples_leaf"
: range(3
,10
),"min_samples_split"
:range(3
,10
),"criterion"
: ["gini"
,"entropy"
], } clf=DecisionTreeClassifier() model1 = RandomizedSearchCV(clf,param_distributions=random_search,cv=4
,random_state=15
,n_jobs=-1
,n_iter=2
,scoring="accuracy"
) model1.fit(X_train,y_train) m1=model1.best_estimator_ plt.figure(figsize=(8
,6
)) plot_tree(m1,feature_names=['f1'
,'f2'
,'f3'
],class_names=['0'
,'1'
],filled=True
);/<code>
感謝sci-kit學習庫的plot_tree函數,以可視化決策樹。 我們最終得出的決策樹:
參考文獻
--END--
歡迎大家關注我們的公眾號:為AI吶喊(weainahan)
找工作一定少不了項目實戰經驗,為了幫助更多缺少項目實戰的同學入門Python,我們在頭條上創建了一個專欄:《7小時快速掌握Pthon核心編程》,通過一個項目,快速掌握Python,歡迎大家點擊鏈接或者閱讀原文進行試看~