【機器學習(11)】決策樹模型:CART分類及迴歸樹可視化

1. 決策樹模型

1) 概念: 基於樹形結構來擬合自變量與因變量之間的關係

2) 劃分算法: 選擇最佳劃分特徵及特徵中最佳劃分點位置的算法(三大類別)

        ID3: 信息增益判斷;
        C4.5: 信息增益率判斷;
        CART: GINI係數判斷

3) CART基尼係數法算法流程:

        ①迭代計算每個特徵的每個二分切點gini係數

        ②選取gini最小的特徵及對應切分點爲最佳分裂點

        ③進行一次樣本劃分

        ④對劃分後的兩部分樣本重複上述迭代過程,逐步向下分裂

        ⑤所有樣本被分到葉節點中

        ⑥結束

4) 樹模型是否越分叉越多,結構越複雜越好?

        一般樹分叉越多,結構越複雜,在訓練集上表現其實會越好的,但是爲了防止過擬合,樹的分支和深度往往需要被限制的,這也就產生了剪枝策略(有點類似大學運籌中的分支定界法)

5) 剪枝策略
        目的:降低模型複雜度,防止過擬合
        預剪枝:在構建樹的過程中,先計算當前的分裂是否能帶來模型泛化能力的提升,如果不能,則不繼續生長
        後剪枝:讓算法生成一顆完整的決策樹之後,然後從最底層向上計算,如果對分裂點剪枝,模型的泛化能力提升,則進行剪枝

2. 代碼實現

2.1 加載數據和定義類型標籤及劃分數據集

這一部在之前的操作中已經多次重複了,這裏可以直接輸出

import pandas as pd
import matplotlib.pyplot as plt
import os
os.chdir(r'C:\Users\86177\Desktop')
# 樣例數據讀取
df = pd.read_excel('realestate_sample_preprocessed.xlsx')
# 根據共線性矩陣,保留與房價相關性最高的日間人口,將夜間人口和20-39歲夜間人口進行比例處理
def age_percent(row):
    if row['nightpop'] == 0:
        return 0
    else:
        return row['night20-39']/row['nightpop']
df['per_a20_39'] = df.apply(age_percent,axis=1)
df = df.drop(columns=['nightpop','night20-39'])
# 製作標籤變量
price_median = df['average_price'].median()
df['is_high'] = df['average_price'].map(lambda x: True if x>= price_median else False)
print(df['is_high'].value_counts())
# 數據集基本情況查看
print(df.shape)
print(df.dtypes)
# 劃分數據集
x = df[['complete_year','area', 'daypop', 'sub_kde',
       'bus_kde', 'kind_kde','per_a20_39']]
y = df['is_high']
print(x.shape)
print(y.shape)

–> 輸出的結果爲:

True     449
False    449
Name: is_high, dtype: int64

(898, 10)

id                 int64
complete_year      int64
average_price    float64
area             float64
daypop           float64
sub_kde          float64
bus_kde          float64
kind_kde         float64
per_a20_39       float64
is_high             bool
dtype: object

(898, 7)
(898,)

2.2 構建決策樹模型

由於選取的是類型標籤不是數值標籤,這裏導入的是決策樹分類器,如果要進行決策樹迴歸的話就導入下面註釋的語句代碼

from sklearn.tree import DecisionTreeClassifier
# 如果是迴歸問題,就要引入迴歸模型
#from sklearn.tree import DecisionTreeRegressor
# 建立模型
clf_tree = DecisionTreeClassifier(criterion='gini',
                                  splitter='best',
                                  max_depth=3,
                                  min_samples_split=2,
                                  min_samples_leaf=5,
                                  max_features=None,
                                  max_leaf_nodes=10,
                                  min_impurity_decrease=0.0,
                                  min_impurity_split=None,
                                  class_weight=None)
# 訓練決策樹模型
clf_tree.fit(x,y)
print(clf_tree)

–> 輸出的結果爲:

DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=3,
                       max_features=None, max_leaf_nodes=10,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=5, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, presort=False,
                       random_state=None, splitter='best')

2.3 決策樹參數講解

criterion:劃分算法 默認是gini,另外一種是entropy就是信息增益, 迴歸模型可以選擇msemae

splitter:兩個選擇,best(中小型數據)或者random(大數據)。

max_features:控制所搜的特徵數量(一般是默認,如果建模數據量過大,建議調整一下這個參數)

max_depth: 控制樹的深度(控制過擬合的重要參數,過擬合限制,欠擬合就增加深度)

min_samples_split: 任意節點樣本量達到多少的時候就不再分裂(推薦默認值,也是控制過擬合的,適用大數據)

min_samples_leaf:每一個葉子上最少的樣本數(控制最後一個葉節點的樣本量,一般提高這個值可以防止過擬合)

max_leaf_nodes:最大葉節點數量(切分數據集的最大的葉節點的數量,有個上界)

min_impurity_decrease: 切分點不純度最小減少程度(後剪枝的控制參數)

min_impurity_split: 切分點最小不純度(預剪枝的控制參數)

class_weight:指定樣本各類別的的權重(分類模型特有的,防止某個樣本的權重過大,導致決策樹過於偏向這個樣本特徵)

3. 運行結果可視化

import graphviz
import os
os.environ["PATH"] += os.pathsep + r'D:\Anaconda\graphviz-2.38\release\bin'
from IPython.display import Image  
import pydotplus
features = ['complete_year','area', 'daypop', 'sub_kde',
       'bus_kde', 'kind_kde','per_a20_39']
classes=['lower_price','higher_price']
# 定義圖像
from sklearn import tree
tree_graph_data = tree.export_graphviz(clf_tree,
                    feature_names=features,
                     class_names=classes,
                    filled=True,
                    rounded=True)
# 繪圖:
tree_graph = pydotplus.graph_from_dot_data(tree_graph_data)
Image(tree_graph.create_png())

–> 輸出的結果爲:(filled=True 顏色填充,rounded=True圓形矩形顯示)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章