決策樹(Decision Trees)

決策樹(Decision Tree)屬於監督式學習,用於分類問題。將資料輸入樹狀結構從樹根開始,由上到下走訪節點,每個節點放入條件判斷,根據條件判斷決定要走往的分支,最後會走到一個葉節點,該節點不能往下走,該節點就是該輸入所屬分類。

5-1 決策樹的運作過程

決策樹的節點分成根節點、內部節點、葉節點三種。根節點為最上層的節點,所有判斷都從此節點開始,根節點與內部節點放入條件判斷,根據輸入值與條件判斷決定走往哪一個分支,最後會走到一個葉節點為該輸入所屬分類。以下為學期成績是否及格範例,學期成績根據「期末考成績」、「期中考成績」與「作業成績」決定是否及格,根節點為「期末考成績」,2個內部節點為「期中考成績」與「作業成績」,4個葉節點為3個「過關」與1個「當了」,輸入的學生成績就可以經由此決策樹,判斷學生是「過關」,還是「當了」。

5-2 使用sklearn實作決策樹

使用sklearn實作決策樹,將每筆訓練資料輸入決策樹模型就可計算出決策樹的結構,決策樹的結構由根節點與內部節點的條件判斷與葉節點的所屬類別組成,接著使用測試資料評估此模型。使用sklearn實作決策樹的步驟如下。

(1)輸入資料

train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.3, random_state=42)

(2)建立與訓練模型

model = DecisionTreeClassifier(criterion="entropy", max_leaf_nodes=5)

model.fit(train_X, train_y)

(3)使用模型進行預測

pred_y = model.predict(test_X)

(4)使用正確率與混淆矩陣比較目標值與預測值的差異

pred_y = model.predict(test_X)

print("正確率為", metrics.accuracy_score(test_y, pred_y))

cm = confusion_matrix(test_y, pred_y)

print(cm)

5-3 決策樹模型實作範例

5-3-1 使用決策樹分類病人用藥

(5-3-1使用決策樹分類病人用藥.ipynb)

使用病人的生理特徵,例如:年齡、血壓、性別、膽固醇等,預估病人用藥。本範例測資來自於Kaggle網站,可以從以下網址下載drug200.csv。

https://www.kaggle.com/prathamtripathi/drug-classification

Step1)匯入資料

匯入本範例所需函式庫,與匯入drug200.csv到DataFrame。

程式說明

第1到7行:匯入函式庫。

第8行:讀取drug200.csv轉換成DataFrame儲存到變數df。

第9行:使用函式head顯示變數df的前五筆資料。

Step2)檢查資料

檢查資料是否有空值,顯示資料筆數、欄位名稱、第一筆資料與第一筆資料的目標值。

程式說明

第1行:使用函式isnull檢查資料是否有空值,如果欄位有空值就會回傳True,轉換成數值1,加總結果就會是空值個數。

第2到4行:使用shape顯示資料的筆數,屬性dtypes顯示每個欄位的資料型別,函式keys顯示欄位名稱。

第5到6行:iloc顯示指定範圍的資料內容,使用[]顯示指定欄位的資料內容。

Step3)整理資料

字串資料轉換成數值才能進入機器學習模型進行訓練與預測,將本範例輸入資料的欄位Sex、BP、Cholesterol與Drug為字串資料,需經由LabelEncoder轉換成數值才能輸入機器學習模型。

程式說明

第1到4行:使用np.unique不重複取出資料集df欄位Sex、BP、Cholesterol、Drug的可能值。

第5行:變數df2參考到df。

第6到8行:變數LE_sex為LabelEncoder物件,將字串轉換成數字,變數LE_sex負責轉換F與M,將資料集df2的欄位Sex的F與M轉換成數字0與1。

第9到11行:變數LE_bp為LabelEncoder物件,將字串轉換成數字,變數LE_bp負責轉換NORMAL、HIGH、LOW,將資料集df2的欄位BP的NORMAL、HIGH、LOW轉換成數字0與2。

第12到14行:變數LE_cho為LabelEncoder物件,將字串轉換成數字,變數LE_cho負責轉換NORMAL、HIGH,將資料集df2的欄位Cholesterol的NORMAL、HIGH轉換成數字0與1。

第15行:使用函式head顯示變數df2的前五筆資料。

Step4)製作訓練資料與測試資料

準備機器學習模型的訓練資料與測試資料。

程式說明

第1到2行:設定變數y為資料集df2欄位Drug,設定變數X為資料集df2移除欄位Drug。

第3行:使用函式train_test_split,以變數X為獨立變數,變數y為相依變數,隨機挑選出訓練集與測試集,原始資料的百分之70為訓練集,剩餘百分之30為測試集,設定random_state為42。

第4到5行:使用shape顯示訓練資料與測試資料的筆數。

Step5)建立與訓練模型

使用DecisionTreeClassifier建立模型與訓練模型。

程式說明

第1行:建立決策樹模型,設定決策樹的標準為entropy,設定決策樹的最大葉節點個數為5。

第2行:輸入訓練資料到模型進行訓練。

Step6)評估模型

輸入測試資料到模型進行預測,並計算正確率與混淆矩陣。

程式說明

第1到2行:以test_X為輸入,使用函式predict進行預測,變數pred_y參考到此結果,使用函式metrics.accuracy_score計算test_y與pred_y的正確率。

第3到4行:使用混淆矩陣分析test_y與pred_y,發現有6個輸入辨別錯誤。

Step7)調整決策樹的max_leaf_nodes找出最高正確率

使用迴圈設定函式DecisionTreeClassifier的參數max_leaf_nodes由2到9每次遞增1,找出最高正確率。

程式說明

第1到5行:定義函式tree,輸入參數num,建立決策樹模型,設定決策樹的標準為entropy,設定決策樹的最大葉節點個數為num(第2行) ,輸入訓練資料到模型進行訓練(第3行)。使用函式predict進行預測,以test_X為輸入,變數pred_y參考到此結果 (第4行),使用函式metrics.accuracy_score計算test_y與pred_y的正確率(第5行)。

第6到7行:使用for迴圈,迴圈變數i由2到9,每次遞增1,將迴圈變數i代入函式tree,使用迴圈變數i每次設定決策樹的最大葉節點個數,再進行訓練模型與評估模型,找出正確率最高的最大葉節點個數。

Step8)繪製決策樹

繪製決策樹圖形,本範例需要安裝函式庫pydotplus,使用指令「pip install pydotplus」進行安裝。

程式說明

第1到5行:匯入函式庫。

第6行:建立決策樹模型,設定決策樹的標準為entropy,設定決策樹的最大葉節點個數為6。

第7行:輸入訓練資料到模型進行訓練。

第8行:使用函式predict進行預測,以test_X為輸入,變數pred_y參考到此結果。

第9行:設定變數io為StringIO。

第10行:設定filename為「決策樹.png」。

第11行:設定column_names為 ['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K']。

第12行:使用函式export_graphviz匯出決策樹圖到變數io 。

第13行:使用函式graph_from_dot_data從變數io載入圖片到變數gra。

第14行:使用函式write_png將變數gra的圖片寫到檔案filename。

第15行:使用函式imread讀取圖片檔案filename到變數img。

第16到17行:設定物件fig的圖片大小為寬度100像素,高度200像素,顯示img到螢幕上。

5-3-2 使用隨機森林分類病人用藥

(5-3-2使用隨機森林分類病人用藥.ipynb)

每次隨機挑選部分輸入資料建立多個決策樹,這些決策樹組成隨機森林,將測試資料輸入隨機森林產生預測結果,統計所有預測結果出現最多次的類別,就是最終預測結果,使用「三個臭皮匠勝過一個諸葛亮」的概念,眾人投票產生預估結果。

使用病人的生理特徵,例如:年齡、血壓、性別、膽固醇等,輸入隨機森林預估病人用藥,本範例測資來自於Kaggle網站,可以從以下網址下載drug200.csv。

https://www.kaggle.com/prathamtripathi/drug-classification

Step1)匯入資料

匯入drug200.csv到DataFrame。

程式說明

第1到6行:匯入函式庫。

第7行:讀取drug200.csv轉換成DataFrame儲存到變數df。

第8行:使用函式head顯示變數df的前五筆資料。

Step2)檢查資料

在前一範例已經檢查過資料,就不再重複。

Step3)整理資料

字串資料轉換成數值才能進入機器學習模型進行訓練與預測,將本範例輸入資料的欄位Sex、BP、Cholesterol與Drug為字串資料,需經由LabelEncoder轉換成數值才能輸入機器學習模型。

程式說明

第1行:變數df2參考到df。

第2到4行:變數LE_sex為LabelEncoder物件,將字串轉換成數字,變數LE_sex負責轉換F與M,將資料集df2的欄位Sex的F與M轉換成數字0與1。

第5到7行:變數LE_bp為LabelEncoder物件,將字串轉換成數字,變數LE_bp負責轉換NORMAL、HIGH、LOW,將資料集df2的欄位BP的NORMAL、HIGH、LOW轉換成數字0與2。

第8到10行:變數LE_cho為LabelEncoder物件,將字串轉換成數字,變數LE_cho負責轉換NORMAL、HIGH,將資料集df2的欄位Cholesterol的NORMAL、HIGH轉換成數字0與1。

第11到13行:變數LE_drug為LabelEncoder物件,將字串轉換成數字,變數LE_drug負責轉換drugA、drugB、drugC、drugX、DrugY,將資料集df2的欄位Drug的drugA、drugB、drugC、drugX、DrugY轉換成數字0與4。

第14行:使用函式head顯示變數df2的前五筆資料。

製作訓練集與測試集資料。

程式說明

第1到2行:設定變數y為資料集df2欄位Drug,設定變數X為資料集df2移除欄位Drug。

第3行:使用函式train_test_split,以變數X為獨立變數,變數y為相依變數,隨機挑選出訓練集與測試集,原始資料的百分之70為訓練集,剩餘百分之30為測試集,設定random_state為42。

第4到5行:使用shape顯示訓練資料與測試資料的筆數。

Step4)建立與訓練模型

使用RandomForestRegressor建立模型與訓練模型。

程式說明

第1行:建立隨機森林模型,設定隨機森林的random_state為42。

第2行:輸入訓練資料到模型進行訓練。

Step5)評估模型

輸入測試資料到模型進行預測,並計算模型的平均絕對誤差(Mean Absolute Error)。

程式說明

第1行:以test_X為輸入,使用函式predict進行預測,變數pred_y參考到此結果。

第2到3行:顯示陣列pred_y與test_y的前10個元素。

第4行:使用函式metrics.mean_absolute_error計算test_y與pred_y的平均絕對誤差(Mean Absolute Error),並將結果顯示在螢幕上。