機器學習算法(六):基於決策樹的分類預測


一、決策樹的介紹

決策樹是一種常見的分類模型,在金融分控、醫療輔助診斷等諸多行業具有較為廣泛的應用。決策樹的核心思想是基於樹結構對數據進行划分,這種思想是人類處理問題時的本能方法。例如在婚戀市場中,女方通常會先看男方是否有房產,如果有房產再看是否有車產,如果有車產再看是否有穩定工作……最后得出是否要深入了解的判斷。

決策樹的主要優點:

  1. 具有很好的解釋性,模型可以生成可以理解的規則。
  2. 可以發現特征的重要程度。
  3. 模型的計算復雜度較低。

決策樹的主要缺點:

  1. 模型容易過擬合,需要采用減枝技術處理。
  2. 不能很好利用連續型特征
  3. 預測能力有限,無法達到其他強監督模型效果。
  4. 方差較高,數據分布的輕微改變很容易造成樹結構完全不同。
二、代碼流程

Part1 Demo實踐

  • Step1:庫函數導入
  • Step2:模型訓練
  • Step3:數據和模型可視化
  • Step4:模型預測

Part2 基於企鵝(penguins)數據集的決策樹分類實踐 

  • Step1:庫函數導入
  • Step2:數據讀取/載入
  • Step3:數據信息簡單查看
  • Step4:可視化描述
  • Step5:利用 決策樹模型 在二分類上 進行訓練和預測
  • Step6:利用 決策樹模型 在三分類(多分類)上 進行訓練和預測

2.1Demo實踐

Step1: 庫函數導入

##  基礎函數庫
import numpy as np 

## 導入畫圖庫
import matplotlib.pyplot as plt
import seaborn as sns

## 導入決策樹模型函數
from sklearn.tree import DecisionTreeClassifier from sklearn import tree

 

Step2: 訓練模型

##Demo演示LogisticRegression分類

## 構造數據集
x_fearures = np.array([[-1, -2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3, 2]])
y_label = np.array([0, 1, 0, 1, 0, 1])

## 調用決策樹模型
tree_clf = DecisionTreeClassifier()

## 用決策樹模型擬合構造的數據集
tree_clf = tree_clf.fit(x_fearures, y_label)

 

 

Step3: 數據和模型可視化(需要用到graphviz可視化庫)

## 可視化構造的數據樣本點
plt.figure()
plt.scatter(x_fearures[:,0],x_fearures[:,1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')
plt.show()

 

## 本段代碼實際效果為本地生成PDF可視化文檔,在體驗過程中可以不運行,可能無法正常展示結果;
## 代碼生成的可視化結果會截圖展示實際效果
!pip install graphviz 
import graphviz
dot_data = tree.export_graphviz(tree_clf, out_file=None)
graph = graphviz.Source(dot_data)
graph.render("pengunis")
## 'pengunis.pdf'  目前環境問題,還不能展示

 

 Step4:模型預測

## 創建新樣本
x_fearures_new1 = np.array([[0, -1]])
x_fearures_new2 = np.array([[2, 1]])
## 在訓練集和測試集上分布利用訓練好的模型進行預測
y_label_new1_predict = tree_clf.predict(x_fearures_new1)
y_label_new2_predict = tree_clf.predict(x_fearures_new2)
print('The New point 1 predict class:\n',y_label_new1_predict)
print('The New point 2 predict class:\n',y_label_new2_predict)
# The New point 1 predict class:
 # [1]
# The New point 2 predict class:
 # [0]

 

 

 全部代碼如下(已折疊):

# -*- coding: utf-8 -*-
"""
Created on Tue Aug 11 10:12:48 2020

@author: Admin
"""

#Step1: 庫函數導入
##  基礎函數庫
import numpy as np 

## 導入畫圖庫
import matplotlib.pyplot as plt
import seaborn as sns

## 導入決策樹模型函數
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree


#Step2: 訓練模型
##Demo演示LogisticRegression分類

## 構造數據集
x_fearures = np.array([[-1, -2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3, 2]])
y_label = np.array([0, 1, 0, 1, 0, 1])

## 調用決策樹模型
tree_clf = DecisionTreeClassifier()

## 用決策樹模型擬合構造的數據集
tree_clf = tree_clf.fit(x_fearures, y_label)


#Step3: 數據和模型可視化(需要用到graphviz可視化庫)
## 可視化構造的數據樣本點
plt.figure()
plt.scatter(x_fearures[:,0],x_fearures[:,1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')
plt.show()

## 本段代碼實際效果為本地生成PDF可視化文檔,在體驗過程中可以不運行,可能無法正常展示結果;
## 代碼生成的可視化結果會截圖展示實際效果
#!pip install graphviz   已經有啦的就不需要安裝了
import graphviz
dot_data = tree.export_graphviz(tree_clf, out_file=None)
graph = graphviz.Source(dot_data)
graph.render("pengunis")
## 'pengunis.pdf'


#Step4:模型預測
## 創建新樣本
x_fearures_new1 = np.array([[0, -1]])
x_fearures_new2 = np.array([[2, 1]])
## 在訓練集和測試集上分布利用訓練好的模型進行預測
y_label_new1_predict = tree_clf.predict(x_fearures_new1)
y_label_new2_predict = tree_clf.predict(x_fearures_new2)
print('The New point 1 predict class:\n',y_label_new1_predict)
print('The New point 2 predict class:\n',y_label_new2_predict)
# The New point 1 predict class:
 # [1]
# The New point 2 predict class:
 # [0]
View Code

 

2.2基於企鵝(penguins)數據集的決策樹分類實踐 

在實踐的最開始,我們首先需要導入一些基礎的函數庫包括:numpy (Python進行科學計算的基礎軟件包),pandas(pandas是一種快速,強大,靈活且易於使用的開源數據分析和處理工具),matplotlib和seaborn繪圖。

數據是在阿里雲上面跑的,我沒有企鵝的數據https://tianchi.aliyun.com/notebook-ai/notebookEdit?notebookLabId=108107&version=0&sceneId=bb2fe211e5e94017840ce42cc31fe621&env=prod

 

Step1:函數庫導入

 

##  基礎函數庫
import numpy as np 
import pandas as pd

## 繪圖函數庫
import matplotlib.pyplot as plt
import seaborn as sns

 

本次我們選擇企鵝數據(palmerpenguins)進行方法的嘗試訓練,該數據集一共包含8個變量,其中7個特征變量,1個目標分類變量。共有150個樣本,目標變量為 企鵝的類別 其都屬於企鵝類的三個亞屬,分別是(Adélie, Chinstrap and Gentoo)。包含的三種種企鵝的七個特征,分別是所在島嶼,嘴巴長度,嘴巴深度,腳蹼長度,身體體積,性別以及年齡。

 

Step2:數據讀取/載入

 

## 我們利用Pandas自帶的read_csv函數讀取並轉化為DataFrame格式

data = pd.read_csv('datalab/531811/Datawhale/penguins_raw.csv')
## 為了方便我們僅選取四個簡單的特征,有興趣的同學可以研究下其他特征的含義以及使用方法
data = data[['Species','Culmen Length (mm)','Culmen Depth (mm)',
            'Flipper Length (mm)','Body Mass (g)']]

 

Step3:數據信息簡單查看
## 利用.info()查看數據的整體信息
data.info()
## <class 'pandas.core.frame.DataFrame'>
## RangeIndex: 344 entries, 0 to 343
## Data columns (total 5 columns):
## Species                344 non-null object
## Culmen Length (mm)     342 non-null float64
## Culmen Depth (mm)      342 non-null float64
## Flipper Length (mm)    342 non-null float64
## Body Mass (g)          342 non-null float64
## dtypes: float64(4), object(1)
## memory usage: 13.6+ KB
## 進行簡單的數據查看,我們可以利用 .head() 頭部.tail()尾部
data.head()
Species Culmen Length (mm) Culmen Depth (mm) Flipper Length (mm) Body Mass (g)
0 Adelie Penguin (Pygoscelis adeliae) 39.1 18.7 181.0 3750.0
1 Adelie Penguin (Pygoscelis adeliae) 39.5 17.4 186.0 3800.0
2 Adelie Penguin (Pygoscelis adeliae) 40.3 18.0 195.0 3250.0
3 Adelie Penguin (Pygoscelis adeliae) NaN NaN NaN NaN
4 Adelie Penguin (Pygoscelis adeliae) 36.7 19.3 193.0 3450.0

 

 這里我們發現數據集中存在NaN,一般的我們認為NaN在數據集中代表了缺失值,可能是數據采集或處理時產生的一種錯誤。這里我們采用-1將缺失值進行填補,還有其他例如“中位數填補、平均數填補”的缺失值處理方法有興趣的同學也可以嘗試

data = data.fillna(-1)
data.tail()
Species Culmen Length (mm) Culmen Depth (mm) Flipper Length (mm) Body Mass (g)
339 Chinstrap penguin (Pygoscelis antarctica) 55.8 19.8 207.0 4000.0
340 Chinstrap penguin (Pygoscelis antarctica) 43.5 18.1 202.0 3400.0
341 Chinstrap penguin (Pygoscelis antarctica) 49.6 18.2 193.0 3775.0
342 Chinstrap penguin (Pygoscelis antarctica) 50.8 19.0 210.0 4100.0
343 Chinstrap penguin (Pygoscelis antarctica) 50.2 18.7 198.0 3775.0

 

## 其對應的類別標簽為'Adelie Penguin', 'Gentoo penguin', 'Chinstrap penguin'三種不同企鵝的類別。
data['Species'].unique()
## array(['Adelie Penguin (Pygoscelis adeliae)',
##       'Gentoo penguin (Pygoscelis papua)',
##       'Chinstrap penguin (Pygoscelis antarctica)'], dtype=object)
## 利用value_counts函數查看每個類別數量
pd.Series(data['Species']).value_counts()
## Adelie Penguin (Pygoscelis adeliae)          152
## Gentoo penguin (Pygoscelis papua)            124
## Chinstrap penguin (Pygoscelis antarctica)     68
## Name: Species, dtype: int64
## 對於特征進行一些統計描述
data.describe()

 

Culmen Length (mm) Culmen Depth (mm) Flipper Length (mm) Body Mass (g)
count 344.000000 344.000000 344.000000 344.000000
mean 43.660756 17.045640 199.741279 4177.319767
std 6.428957 2.405614 20.806759 861.263227
min -1.000000 -1.000000 -1.000000 -1.000000
25% 39.200000 15.500000 190.000000 3550.000000
50% 44.250000 17.300000 197.000000 4025.000000
75% 48.500000 18.700000 213.000000 4750.000000
max 59.600000 21.500000 231.000000 6300.000000

 

 Step4:可視化描述
## 特征與標簽組合的散點可視化
sns.pairplot(data=data, diag_kind='hist', hue= 'Species')
plt.show()

 

 從上圖可以發現,在2D情況下不同的特征組合對於不同類別的企鵝的散點分布,以及大概的區分能力。

'''為了方便我們將標簽轉化為數字
       'Adelie Penguin (Pygoscelis adeliae)'        ------0
       'Gentoo penguin (Pygoscelis papua)'          ------1
       'Chinstrap penguin (Pygoscelis antarctica)   ------2 '''

def trans(x):
    if x == data['Species'].unique()[0]:
        return 0
    if x == data['Species'].unique()[1]:
        return 1
    if x == data['Species'].unique()[2]:
        return 2

data['Species'] = data['Species'].apply(trans)
for col in data.columns:
    if col != 'Species':
        sns.boxplot(x='Species', y=col, saturation=0.5, palette='pastel', data=data)
        plt.title(col)
        plt.show()

 

 

 

 利用箱型圖我們也可以得到不同類別在不同特征上的分布差異情況。

 

# 選取其前三個特征繪制三維散點圖
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

data_class0 = data[data['Species']==0].values
data_class1 = data[data['Species']==1].values
data_class2 = data[data['Species']==2].values
# 'setosa'(0), 'versicolor'(1), 'virginica'(2)
ax.scatter(data_class0[:,0], data_class0[:,1], data_class0[:,2],label=data['Species'].unique()[0])
ax.scatter(data_class1[:,0], data_class1[:,1], data_class1[:,2],label=data['Species'].unique()[1])
ax.scatter(data_class2[:,0], data_class2[:,1], data_class2[:,2],label=data['Species'].unique()[2])
plt.legend()

plt.show()

 

 Step5:利用 決策樹模型 在二分類上 進行訓練和預測
## 為了正確評估模型性能,將數據划分為訓練集和測試集,並在訓練集上訓練模型,在測試集上驗證模型性能。
from sklearn.model_selection import train_test_split

## 選擇其類別為0和1的樣本 (不包括類別為2的樣本)
data_target_part = data[data['Species'].isin([0,1])][['Species']]
data_features_part = data[data['Species'].isin([0,1])][['Culmen Length (mm)','Culmen Depth (mm)',
            'Flipper Length (mm)','Body Mass (g)']]

## 測試集大小為20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(data_features_part, data_target_part, test_size = 0.2, random_state = 2020)
## 從sklearn中導入決策樹模型
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
## 定義 決策樹模型 
clf = DecisionTreeClassifier(criterion='entropy')
## 在訓練集上訓練決策樹模型
clf.fit(x_train, y_train)
## DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
##            max_features=None, max_leaf_nodes=None,
##            min_impurity_decrease=0.0, min_impurity_split=None,
##            min_samples_leaf=1, min_samples_split=2,
##            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
##            splitter='best')
## 可視化
## 本段代碼實際效果為本地生成PDF可視化文檔,在體驗過程中可以不運行,可能無法正常展示結果;
## 代碼生成的可視化結果會截圖展示實際效果
import graphviz
dot_data = tree.export_graphviz(clf, out_file=None)
graph = graphviz.Source(dot_data)
graph.render("penguins")
## 'penguins.pdf'

 

 

## 在訓練集和測試集上分布利用訓練好的模型進行預測
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
from sklearn import metrics
## 利用accuracy(准確度)【預測正確的樣本數目占總預測樣本數目的比例】評估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))
## 查看混淆矩陣 (預測值和真實值的各類情況統計矩陣)
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)
# 利用熱力圖對於結果進行可視化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()
## The accuracy of the Logistic Regression is: 0.9954545454545455
## The accuracy of the Logistic Regression is: 1.0
## The confusion matrix result:
## [[31  0]
## [ 0 25]]

 

 

 我們可以發現其准確度為1,代表所有的樣本都預測正確了

 

Step6:利用 決策樹模型 在三分類(多分類)上 進行訓練和預測
## 測試集大小為20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(data[['Culmen Length (mm)','Culmen Depth (mm)',
            'Flipper Length (mm)','Body Mass (g)']], data[['Species']], test_size = 0.2, random_state = 2020)
## 定義 決策樹模型 
clf = DecisionTreeClassifier()
# 在訓練集上訓練決策樹模型
clf.fit(x_train, y_train)
## DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
##            max_features=None, max_leaf_nodes=None,
##            min_impurity_decrease=0.0, min_impurity_split=None,
##            min_samples_leaf=1, min_samples_split=2,
##            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
##            splitter='best')
## 在訓練集和測試集上分布利用訓練好的模型進行預測
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
## 由於邏輯回歸模型是概率預測模型(前文介紹的 p = p(y=1|x,\theta)),所有我們可以利用 predict_proba 函數預測其概率
train_predict_proba = clf.predict_proba(x_train)
test_predict_proba = clf.predict_proba(x_test)
print('The test predict Probability of each class:\n',test_predict_proba)
## 其中第一列代表預測為0類的概率,第二列代表預測為1類的概率,第三列代表預測為2類的概率。
## 利用accuracy(准確度)【預測正確的樣本數目占總預測樣本數目的比例】評估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))
#  The test predict Probability of each class:
#    [[0. 0. 1.]
#    [0. 1. 0.]
#    [0. 1. 0.]
#    [1. 0. 0.]
#    …………
#    [0. 1. 0.]
#    [0. 0. 1.]
#    [1. 0. 0.]
#    [1. 0. 0.]]
#  The accuracy of the Logistic Regression is: 0.996363636364

#  The accuracy of the Logistic Regression is: 0.971014492754
## 查看混淆矩陣
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)

# 利用熱力圖對於結果進行可視化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

#    The confusion matrix result:
#    [[30  1  0]
#    [ 0 23  0]
#    [ 2  0 13]]

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM