決策樹算法應用及結果解讀

引言

本文是我寫的人工智能系列的第 8 篇文章,文末有前面 7 篇文章的鏈接,推薦你閱讀、分享和交流。

1. 決策樹算法簡介

決策樹是一種應用非常廣泛的算法,比如語音識別、人臉識別、醫療診斷、模式識別等。

決策樹算法既可以解決分類問題(對應的目標值是類別型的數據),也能解決迴歸問題(輸出結果也可以是連續的數值)。

相比其他算法,決策樹有一個非常明顯的優勢,就是可以很直觀地進行可視化,分類規則好理解,讓非專業的人也容易看明白。

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

決策樹算法應用及結果解讀

下面我們以 sklearn 中的葡萄酒數據集為例,給定一些數據指標,比如酒精度等,利用決策樹算法,可以判斷出葡萄酒的類別。

2. 加載數據

為了方便利用圖形進行可視化演示,我們只選取其中 2 個特徵:第 1 個特徵(酒精度)和第 7 個特徵(黃酮量),並繪製出 3 類葡萄酒相應的散點圖。

<code>import numpy as npimport matplotlib.pyplot as pltfrom 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()/<code>
決策樹算法應用及結果解讀

在上面的散點圖中,顏色代表葡萄酒的類別,橫軸代表酒精度,縱軸代表黃酮量。

3. 調用算法

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

<code>from sklearn.model_selection import train_test_splitfrom 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))/<code>
<code>訓練得分:0.9172932330827067測試得分:0.8666666666666667/<code>

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

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

假如設置 max_depth = 1 0,那麼雖然算法的評分變高了,但是決策樹變得過於複雜,就會出現過擬合的問題。

關於模型複雜度的問題討論,可以參考:模型越複雜越好嗎?

4. 決策邊界

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

<code>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()/<code>
決策樹算法應用及結果解讀

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

5. 樹形圖

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

<code># 導入相關庫,需要先安裝 graphviz 和 pydotplus,並在電腦中 Graphviz 軟件import pydotplusfrom sklearn.tree import export_graphvizfrom IPython.display import Imagefrom 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())/<code>
決策樹算法應用及結果解讀

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。

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

小結

本文介紹了決策樹算法的應用,以葡萄酒數據集為例,演示了決策樹算法的實現過程,繪製了直觀易懂的決策邊界和樹形圖,並對決策結果做了詳細解讀。

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

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


分享到:


相關文章: