1. 程式人生 > >機器學習3-決策樹

機器學習3-決策樹

目錄

介紹

核心思想:相似的輸入必會產生相似的輸出。
個人總結:列舉法根據各個元素把所有情況列舉出來,生成樹狀圖。可以用來分類,也可以用來擬合線性。

基本原理

相似的輸入導致相似的輸出。
年齡:青年-1,中年-2,老年-3
學歷:專科-1,本科-2,碩士-3,博士-4
經驗:缺乏-1,一般-2,豐富-3,資深-4
性別:男-1,女-2
薪資:1-低,2-中,3-高,4-超高
年齡  學歷  工作經驗  性別 -> 薪資
1       1    1       2     5000     1
1       2    2       1     8000     2
2       3    3       2     10000    3
3            4       1     30000    4
...
------------------------------------------
1       2      2               1          ?
  
迴歸——平均 \ 結合特徵的相
分類——投票 / 似程度做加權
隨著子表的劃分,資訊熵越來越小,資訊量越來越大,
資料越來越有序。
     年齡1            年齡2            年齡3
    /  |   \      /    |   \       /   |    \
學歷1 學歷2 學歷3 學歷1 學歷2 學歷3 學歷1 學歷2 學歷3 
11123                2...                  3...
12211                2...                  3...
11221                2...                  3...

11... 12... 13... 14... 
11... 12... 13... 14...
11... 12... 13... 14...

依次選擇原始樣本矩陣中的每一列,構建相應特徵值相同的若干子表樹,在葉級子表中所有特徵值都是相同的,對於未知輸出的輸入,按照同樣的規則,歸屬到某個葉級子表,將該子表中各樣本的輸出按照取平均(迴歸)或者取投票(分類)的方法,計算預測輸出。

工程優化

  • 根據事先給定的條件,提前結束子表的劃分過程,藉以簡化決策樹的結構,縮短構建和搜尋的時間,在預測精度犧牲不大的前提下,提高模型效能。通常情況下,可以優先選擇使資訊熵減少量最大的特徵作為劃分子表的依據。

集合演算法

  1. 所謂集合演算法,亦稱集合弱學習方法,其核心思想就是,通過平均或者投票,將多個不同學習方法的結論加以綜合,給出一個相對可靠預測結果。所選擇的弱學習方法,在演算法或資料上應該具備足夠分散性,以體現相對不同的傾向性,這樣得出的綜合結論才能夠更加泛化。
  2. 基於決策樹的集合演算法,就是按照某種規則,構建多棵彼此不同的決策樹模型,分別給出針對未知樣本的預測結果,最後通過平均或投票得到相對綜合的結論。
  3. 根據構建多棵決策樹所依據的規則不同,基於決策樹的集合演算法可被分為以下幾種:
    • 自助聚合:從原始訓練樣本中,以有放回或無放回抽樣的方式,隨機選取部分樣本,構建一棵決策樹,重複以上過程,得到若干棵決策輸,以此弱化某些強勢樣本對預測結果的影響力,提高模型精度。
import sklearn.tree as st
model = st.DecisionTreeRegressor(max_depth=
4) model.fit(train_x, train_y)
    • 隨機森林:如果在自助聚合的基礎上,每次構建決策樹時,不但隨機選擇樣本(行),而且其特徵(列)也是隨機選擇的,則稱為隨機森林。
model = se.RandomForestRegressor(
    max_depth=10, n_estimators=1000,
    min_samples_split=2)
model.fit(train_x, train_y)

    • 正向激勵:首先為訓練樣本分配相等的權重,構建第一棵決策樹,用該決策樹對訓練樣本進行預測**,為預測錯誤的樣本提升權重,**再次構建下一棵決策樹,以此類推,得到針對每個樣本擁有不同權重的多棵決策樹。
model = se.AdaBoostRegressor(
    st.DecisionTreeRegressor(max_depth=4),n_estimators=400, random_state=7)
model.fit(train_x, train_y)
# 基於決策樹的正向激勵迴歸器給出的特徵重要性
fi_ab = model.feature_importances_

示例程式碼

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
#匯入機器學習自帶資料
import sklearn.datasets as sd
import sklearn.utils as su
import sklearn.tree as st
import sklearn.ensemble as se
import sklearn.metrics as sm
boston = sd.load_boston()
# 資料隨機
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:]
# 決策樹迴歸器
model = st.DecisionTreeRegressor(max_depth=4)
model.fit(train_x, train_y)
pred_test_y = model.predict(test_x)
print(sm.r2_score(test_y, pred_test_y))
# 基於決策樹的正向激勵迴歸器
model = se.AdaBoostRegressor(
    st.DecisionTreeRegressor(max_depth=4),
    # n_estimators 評估器,隨機種子random_state=7,為決策樹分配初始權重
    n_estimators=400, random_state=7)
model.fit(train_x, train_y)
pred_test_y = model.predict(test_x)
print(sm.r2_score(test_y, pred_test_y))

特徵重要性

決策樹模型,在確定劃分子表優先選擇特徵的過程中,需要根據最大熵減原則,確定劃分子表的依據,因此,作為學習模型的副產品,可以得到每個特徵對於輸出的影響力度,即特徵重要性:feature_importances_,該輸出與模型演算法有關。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.datasets as sd
import sklearn.utils as su
import sklearn.tree as st
import sklearn.ensemble as se
import matplotlib.pyplot as mp
boston = sd.load_boston()
feature_names = boston.feature_names
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:]
model = st.DecisionTreeRegressor(max_depth=4)
model.fit(train_x, train_y)
# 決策樹迴歸器給出的特徵重要性
fi_dt = model.feature_importances_
model = se.AdaBoostRegressor(
    st.DecisionTreeRegressor(max_depth=4),n_estimators=400, random_state=7)
model.fit(train_x, train_y)
# 基於決策樹的正向激勵迴歸器給出的特徵重要性
fi_ab = model.feature_importances_
mp.figure('Feature Importance', facecolor='lightgray')
mp.subplot(211)
mp.title('Decision Tree', fontsize=16)
mp.ylabel('Importance', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
sorted_indices = fi_dt.argsort()[::-1]
pos = np.arange(sorted_indices.size)
mp.bar(pos, fi_dt[sorted_indices],
       facecolor='deepskyblue', edgecolor='steelblue')
mp.xticks(pos, feature_names[sorted_indices],
          rotation=30)
mp.subplot(212)
mp.title('AdaBoost Decision Tree', fontsize=16)
mp.ylabel('Importance', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
sorted_indices = fi_ab.argsort()[::-1]
pos = np.arange(sorted_indices.size)
mp.bar(pos, fi_ab[sorted_indices],
       facecolor='lightcoral', edgecolor='indianred')
mp.xticks(pos, feature_names[sorted_indices],
          rotation=30)
mp.tight_layout()
mp.show()

學習模型關於特徵重要性的計算,除了與選擇的演算法有關以外,還與資料的採集粒度有關。
例子講解了按天和按小時統計共享單車使用量,得到影響因素柱狀圖。

import csv
import numpy as np
import sklearn.utils as su
import sklearn.ensemble as se
import sklearn.metrics as sm
import matplotlib.pyplot as mp
with open(r'C:\Users\Cs\Desktop\機器學習\ML\data\bike_day.csv', 'r') as f:
    reader = csv.reader(f)
    x, y = [], []
    for row in reader:
        x.append(row[2:13])
        y.append(row[-1])
fn_dy = np.array(x[0])
x = np.array(x[1:], dtype=float)
y = np.array(y[1:], dtype=float)
#su.shuffle:以一致的方式隨機陣列或稀疏矩陣
# 這是對集合進行隨機排列的便利別名。resample(*arrays, replace=False)
# random_state 隨機種子,隨機種子一樣保證每次輸出的隨機值一樣,便於驗證。(不設定每次隨機的值不一樣)
x, y = su.shuffle(x, y, random_state=7)
#0.9的訓練資料
#0.1的測試資料
train_size = int(len(x) * 0.9)
train_x, test_x, train_y, test_y = x[:train_size], x[train_size:],y[:train_size], y[train_size:]
# max_depth=10:最大深度為10,決策樹深度
# n_estimators=1000,最大估計量為1000,及最大使用的樣本數
# min_samples_split=2 每一節點最少子節點2,小於2會影響決策樹準確性,因為沒得選??
#RandomForestRegressor:隨機森林迴歸器
model = se.RandomForestRegressor(
    max_depth=10, n_estimators=1000,
    min_samples_split=2)
model.fit(train_x, train_y)
# 基於“天”資料集的特徵重要性
fi_dy = model.feature_importances_
pred_test_y = model.predict(test_x)
# 輸出r2值,判斷預測效果
print(sm.r2_score(test_y, pred_test_y))
with open(r'C:\Users\Cs\Desktop\機器學習\ML\data\bike_hour.csv', 'r') as f:
    reader = csv.reader(f)
    x, y = [], []
    for row in reader:
        x.append(row[2:13])
        y.append(row[-1])
fn_hr = np.array(x[0])
x = np.array(x[1:], dtype=float)
y = np.array(y[1:], dtype=float)
x, y = su.shuffle(x, y, random_state=7)
train_size = int(len(x) * 0.9)
train_x, test_x, train_y, test_y = \
    x[:train_size], x[train_size:], \
    y[:train_size], y[train_size:]
# 隨機森林迴歸器
model = se.RandomForestRegressor(
    max_depth=10, n_estimators=1000,
    min_samples_split=2)
model.fit(train_x, train_y)
# 基於“小時”資料集的特徵重要性
fi_hr = model.feature_importances_
pred_test_y = model.predict(test_x)
print(sm.r2_score(test_y, pred_test_y))


mp.figure('Bike', facecolor='lightgray')
mp.subplot(211)
mp.title('Day', fontsize=16)
mp.ylabel('Importance', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
sorted_indices = fi_dy.argsort()[::-1]
pos = np.arange(sorted_indices.size)
mp.bar(pos, fi_dy[sorted_indices],
       facecolor='deepskyblue', edgecolor='steelblue')
mp.xticks(pos, fn_dy[sorted_indices],
          rotation=30)
mp.subplot(212)
mp.title('Hour', fontsize=16)
mp.ylabel('Importance', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
sorted_indices = fi_hr.argsort()[::-1]
pos = np.arange(sorted_indices.size)
mp.bar(pos, fi_hr[sorted_indices],
       facecolor='lightcoral', edgecolor='indianred')
mp.xticks(pos, fn_hr[sorted_indices],
          rotation=30)
mp.tight_layout()
mp.show()

在這裡插入圖片描述