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
就是信息增益, 迴歸模型可以選擇mse
或mae
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
圓形矩形顯示)