天天看點

決策樹分類算法解析

1. 決策樹算法簡介

決策樹算法既可以解決分類問題(對應的目标值是類别型的資料),也能解決回歸問題(輸出結果也可以是連續的數值)。相比其他算法,決策樹有一個非常明顯的優勢,就是可以很直覺地進行可視化,分類規則好了解,讓非專業的人也容易看明白。

比如某個周末,你根據天氣等情況決定是否出門,如果降雨就不出門,否則看是否有霧霾……這個決策的過程,可以畫成這樣一顆樹形圖:

決策樹分類算法解析

下面我們以 sklearn 中的葡萄酒資料集為例,給定一些資料名額,比如酒精度等,利用決策樹算法,可以判斷出葡萄酒的類别。

2. 加載資料

為了友善利用圖形進行可視化示範,我們隻選取其中 2 個特征:第 1 個特征(酒精度)和第 7 個特征(黃酮量),并繪制出 3 類葡萄酒相應的散點圖。

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
 
# 加載葡萄酒的資料集
wine = datasets.load_wine()
 
# 為了友善可視化,隻選取 2 個特征
X = wine.data[:, [0, 6]]
y = wine.target
 
# 繪制散點圖
plt.scatter(X[y==0, 0], X[y==0, 1])
plt.scatter(X[y==1, 0], X[y==1, 1])
plt.scatter(X[y==2, 0], X[y==2, 1])
plt.show()
           
決策樹分類算法解析

3. 調用算法

和調用其他算法的方法一樣,我們先把資料集拆分為訓練集和測試集,然後指定相關參數,這裡我們指定決策樹的最大深度等于 2,并對算法進行評分

from sklearn.model_selection import train_test_split
from sklearn import tree
 
# 拆分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
 
# 調用決策樹分類算法
dtc = tree.DecisionTreeClassifier(max_depth=2)
dtc.fit(X_train, y_train)
 
# 算法評分
print('訓練得分:', dtc.score(X_train, y_train))
print('測試得分:', dtc.score(X_test, y_test))
           
訓練得分:0.9172932330827067
測試得分:0.8666666666666667
           

從上面的結果可以看出,決策樹算法的訓練得分和測試得分都還不錯。

假如設定 max_depth = 1,那麼算法評分很低,就會出現欠拟合的問題。

假如設定 max_depth = 10,那麼雖然算法的評分變高了,但是決策樹變得過于複雜,就會出現過拟合的問題。

4. 決策邊界

為了更加直覺地看到算法的分類效果,我們定義一個繪制決策邊界的函數,畫出分類的邊界線。

from matplotlib.colors import ListedColormap
 
# 定義繪制決策邊界的函數
def plot_decision_boundary(model, axis):
    
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1,1)
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]
    
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    
    plt.contourf(x0, x1, zz, cmap=custom_cmap)
    
# 繪制決策邊界
plot_decision_boundary(dtc, axis=[11, 15, 0, 6])
plt.scatter(X[y==0, 0], X[y==0, 1])
plt.scatter(X[y==1, 0], X[y==1, 1])
plt.scatter(X[y==2, 0], X[y==2, 1])
plt.show()
           
決策樹分類算法解析

從圖中也可以直覺地看出,大部分資料點的分類是基本準确的,這也說明決策樹算法的效果還不錯。

5. 樹形圖

為了能夠更加直覺地了解決策樹算法,我們可以用樹形圖來展示算法的結果。

# 導入相關庫,需要先安裝 graphviz 和 pydotplus,并在電腦中 Graphviz 軟體
import pydotplus
from sklearn.tree import export_graphviz
from IPython.display import Image
from io import StringIO
 
# 将對象寫入記憶體中
dot_data = StringIO()
 
# 生成決策樹結構
tree.export_graphviz(dtc, class_names=wine.target_names,
                     feature_names=[wine.feature_names[0], wine.feature_names[6]],
                     rounded=True, filled=True, out_file = dot_data)
 
# 生成樹形圖并展示出來
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
           
決策樹分類算法解析

6. 結果解讀

從上面的樹形圖來看,在葡萄酒資料的訓練集中,有 133 個資料,劃分為 3 個類别,數量分别是 43、50、40 個,對應的标簽分别是 class_0、class_1、class_2,其中 class_1 的數量最多,是以最上面的根節點認為,類别為 class_1 的可能性最大,Gini 系數為 0.664,它是利用下面的公式計算出來的:

1 - (43/133)**2 - (50/133)**2 - (40/133)**2

在決策樹算法中,Gini 系數代表樣本的不确定性。當每個類别的數量越趨近于平均值,Gini 系數就越大,也就越不确定。

比如扔硬币的遊戲,在一般情況下,正反兩面的機率都是 50%,此時 Gini 系數等于 0.5,你猜中的機率也是 50%;假如你對硬币做了手腳,把兩面都變成正面圖案,此時Gini 系數等于 0, 也就是說,不确定性為 0,你能明确地知道肯定是正面。

在上面葡萄酒的例子中,當黃酮量 <= 1.575 時,有 49 個樣本,3 個類别的數量分别是 0、9、40 個,其中 class_2 的數量最多,Gini 系數為 0.3,比上面的節點要低,說明分類結果變得更加确定。當酒精量 > 12.41 時,有 39 個樣本,3 個類别的數量分别是 0、2、37個,Gini 系數為 0.097,此時分類結果變得更加确定為 class_2。

樹形圖中其他節點的結果含義類似,在此不再贅述。

小結

本文介紹了決策樹算法的應用,以葡萄酒資料集為例,示範了決策樹算法的實作過程,繪制了直覺易懂的決策邊界和樹形圖,并對決策結果做了詳細解讀。

雖然決策樹算法有很多優點,比如高效、易懂,但是也有它的不足之處,比如當參數設定不當時,很容易出現過拟合的問題。

為了避免決策樹算法出現過拟合的問題,可以使用「內建學習」的方法,融合多種不同的算法,也就是俗話講的「三個臭皮匠,賽過諸葛亮」。

繼續閱讀