''' 決策樹: 基本算法原理: 核心思想:相似的輸入必會產生相似的輸出。例如預測某人薪資: 年齡:1-青年,2-中年,3-老年 學歷:1-本科,2-碩士,3-博士 經歷:1-出道,2-一般,3-老手,4-骨灰 性別:1-男性,2-女性 | 年齡 | 學歷 | 經歷 | 性別 | ==> | 薪資 | | ---- | ---- | ---- | ---- | ---- | -----------| | 1 | 1 | 1 | 1 | ==> | 6000(低) | | 2 | 1 | 3 | 1 | ==> | 10000(中) | | 3 | 3 | 4 | 1 | ==> | 50000(高) | | ... | ... | ... | ... | ==> | ... | | 1 | 3 | 2 | 2 | ==> | ? | 為了提高搜索效率,使用樹形數據結構處理樣本數據:先按照年齡分三棵子樹,再按照學歷往下分,知直到所有特征都分完 這樣便得到葉級子表,葉級子表中便保存了所有特征值完全相同的樣本。 首先從訓練樣本矩陣中選擇第一個特征進行子表划分,使每個子表中該特征的值全部相同, 然后再在每個子表中選擇下一個特征按照同樣的規則繼續划分更小的子表,不斷重復直到所有的特征全部使用完為止, 此時便得到葉級子表,其中所有樣本的特征值全部相同。對於待預測樣本,根據其每一個特征的值,選擇對應的子表, 逐一匹配,直到找到與之完全匹配的葉級子表,用該子表中樣本的輸出,通過平均(回歸)或者投票(分類)為待預測樣本提供輸出。 隨着子表的划分,信息熵(信息的混亂程度)越來越小,信息越來越純,數據越來越有序。 決策樹回歸器模型相關API: import sklearn.tree as st # 創建決策樹回歸器模型 決策樹的最大深度為4 model = st.DecisionTreeRegressor(max_depth=4) # 訓練模型 # train_x: 二維數組樣本數據 # train_y: 訓練集中對應每行樣本的結果 model.fit(train_x, train_y) # 測試模型 pred_test_y = model.predict(test_x) 決策樹模型優化: 1.工程優化:不必用盡所有的特征,葉級子表中允許混雜不同的特征值,以此降低決策樹的層數,在精度犧牲可接受的前提下, 提高模型的性能。通常情況下,可以優先選擇使信息熵減少量最大的特征作為划分子表的依據。 2.集合算法:根據多個不同模型給出的預測結果,利用平均(回歸)或者投票(分類)的方法,得出最終預測結果。基於決策樹的集合算法, 就是按照某種規則,構建多棵彼此不同的決策樹模型,分別給出針對未知樣本的預測結果, 最后通過平均或投票得到相對綜合的結論。---一棵樹片面,多棵樹綜合起來,泛化模型 1>正向激勵:首先為樣本矩陣中的樣本隨機分配初始權重,由此構建一棵帶有權重的決策樹, 在由該決策樹提供預測輸出時,通過加權平均或者加權投票的方式產生預測值。 將訓練樣本代入模型,預測其輸出,對那些預測值與實際值不同的樣本,提高其權重, 由此形成第二棵決策樹。重復以上過程,構建出不同權重的若干棵決策樹。---一棵樹片面,多棵樹綜合起來,泛化模型 正向激勵相關API: import sklearn.tree as st import sklearn.ensemble as se # 集合算法模塊 # model: 決策樹模型(一顆),即單棵決策樹模型 model = st.DecisionTreeRegressor(max_depth=4) # 自適應增強決策樹回歸模型 # n_estimators:構建400棵不同權重的決策樹(需要多少棵樹),訓練模型 model = se.AdaBoostRegressor(model, n_estimators=400, random_state=7) # 訓練模型 model.fit(train_x, train_y) # 測試模型 pred_test_y = model.predict(test_x) 特征重要性:作為決策樹模型訓練過程的副產品,根據每個特征划分子表前后的信息熵減少量就標志了該特征的重要程度, 此即為該特征重要性指標。訓練得到的模型對象提供了屬性:feature_importances_來存儲每個特征的重要性。 獲取樣本矩陣特征重要性屬性: model.fit(train_x, train_y) fi = model.feature_importances_ # 末尾帶有下划線表示,這些屬性都是訓練之后得到的副產品 案例:基於普通決策樹與正向激勵決策樹預測波士頓地區房屋價格。並獲取獲取兩個模型的特征重要性值,按照從大到小順序輸出繪圖。 ''' import numpy as np import matplotlib.pyplot as mp import sklearn.tree as st import sklearn.datasets as sd # sklearn提供的數據集 import sklearn.utils as su # 可以把數據集按照行進行打亂 import sklearn.metrics as sm import sklearn.ensemble as se # 加載波士頓房屋地區房屋價格 boston = sd.load_boston() # ['CRIM','ZN','INDUS','CHAS','NOX','RM','AGE','DIS','RAD','TAX','PTRATIO','B','LSTAT'] # ['犯罪率','住宅地比例','商業用地比例','是否靠河','空氣質量','房間數','房屋年限','距市中心的距離','路網密度','房產稅','師生比','黑人比例','低地位人口比例'] print(boston.feature_names) # 特征名 print(boston.data.shape) # 數據的輸入 print(boston.target.shape) # 數據的輸出 # 划分測試集與訓練集---二八分,80%用於訓練,20%用於測試 # random_state稱為隨機種子,若打亂時使用的隨機種子相同,則得到的結果相同 x, y = su.shuffle(boston.data, boston.target, random_state=7) # 按行打亂數據集 train_size = int(len(x) * 0.8) train_x, test_x, train_y, test_y = x[:train_size], x[train_size:], y[:train_size], y[train_size:] print(train_x.shape) print(test_x.shape) # 基於普通決策樹建模-->訓練模型-->測試模型-----單棵決策樹 model = st.DecisionTreeRegressor(max_depth=4) model.fit(train_x, train_y) pred_test_y = model.predict(test_x) # 獲取普通決策樹的特征重要性指標 dt_fi = model.feature_importances_ print(dt_fi) # 模型評估---單棵決策樹 print(sm.r2_score(test_y, pred_test_y)) print('=======================') # 基於正向激勵預測房屋價格 model = se.AdaBoostRegressor(model, n_estimators=400, random_state=7) model.fit(train_x, train_y) pred_test_y = model.predict(test_x) # 獲取正向激勵決策樹的特征重要性指標 ad_fi = model.feature_importances_ print(ad_fi) # 正向激勵的模型評分 print(sm.r2_score(test_y, pred_test_y)) # 繪制特征重要性圖像---特征重要性從高到底排序 mp.figure('Feature Importance', facecolor='lightgray') mp.rcParams['font.sans-serif'] = 'SimHei' mp.subplot(211) mp.title('Decision Tree FI') mp.ylabel('Feature Importance') mp.grid(linestyle=":") # 排序 # names = boston.feature_names names = np.array( ['犯罪率', '住宅地比例', '商業用地比例', '是否靠河', '空氣質量', '房間數', '房屋年限', '距市中心的距離', '路網密度', '房產稅', '師生比', '黑人比例', '低地位人口比例']) sorted_indexes = dt_fi.argsort()[::-1] # 下標排序,從大到小 x = np.arange(names.size) mp.bar(x, dt_fi[sorted_indexes], 0.7, color='dodgerblue', label='DTFI') mp.xticks(x, names[sorted_indexes]) # 設置x軸坐標 mp.tight_layout() mp.legend() mp.subplot(212) mp.title('AdaBoostRegressor FI') mp.ylabel('AdaBoostRegressor FI') mp.grid(linestyle=":") # 排序 # names = boston.feature_names names = np.array( ['犯罪率', '住宅地比例', '商業用地比例', '是否靠河', '空氣質量', '房間數', '房屋年限', '距市中心的距離', '路網密度', '房產稅', '師生比', '黑人比例', '低地位人口比例']) sorted_indexes = ad_fi.argsort()[::-1] # 下標排序,從大到小 x = np.arange(names.size) mp.bar(x, ad_fi[sorted_indexes], 0.7, color='orangered', label='ABRFI') mp.xticks(x, names[sorted_indexes]) # 設置x軸坐標 mp.tight_layout() mp.legend() mp.show() 輸出結果: ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT'] (506, 13) (506,) (404, 13) (102, 13) [0.03856422 0. 0. 0. 0.02908806 0.62280298 0. 0.10473383 0. 0. 0.00460542 0. 0.20020548] 0.8202560889408634 ======================= [0.03339581 0.00287794 0.00810414 0.00099482 0.0463733 0.27796803 0.00884059 0.11267449 0.02459319 0.05455562 0.05567394 0.0194009 0.35454723] 0.9068598725149652