機器學習 - 算法模型 - 迴歸問題

線性迴歸

輸入		輸出
0.5      5.0
0.6      5.5
0.8      6.0
1.1      6.8
1.4      7.0
...
y = f(x)

預測函數:y = w0+w1x
x: 輸入
y: 輸出
w0和w1: 模型參數

所謂模型訓練,就是根據已知的x和y,找到最佳的模型參數w0 和 w1,儘可能精確地描述出輸入和輸出的關係。

5.0 = w0 + w1 × 0.5
5.5 = w0 + w1 × 0.6

單樣本誤差:

根據預測函數求出輸入爲x時的預測值:y’ = w0 + w1x,單樣本誤差爲1/2(y’ - y)2

總樣本誤差:

把所有單樣本誤差相加即是總樣本誤差:1/2 Σ(y’ - y)2

損失函數:

loss = 1/2 Σ(w0 + w1x - y)2

所以損失函數就是總樣本誤差關於模型參數的函數,該函數屬於三維數學模型,即需要找到一組w0 w1使得loss取極小值。

梯度下降:
案例:畫圖模擬梯度下降的過程

  1. 整理訓練集數據,自定義梯度下降算法規則,求出w0 , w1 ,繪製迴歸線。
import numpy as np
import matplotlib.pyplot as mp
train_x = np.array([0.5, 0.6, 0.8, 1.1, 1.4])
train_y = np.array([5.0, 5.5, 6.0, 6.8, 7.0])
test_x = np.array([0.45, 0.55, 1.0, 1.3, 1.5])
test_y = np.array([4.8, 5.3, 6.4, 6.9, 7.3])

times = 1000	# 定義梯度下降次數
lrate = 0.01	# 記錄每次梯度下降參數變化率
epoches = []	# 記錄每次梯度下降的索引
w0, w1, losses = [1], [1], []
for i in range(1, times + 1):
    epoches.append(i)
    # 每次下降後的損失函數值
    loss = (((w0[-1] + w1[-1] * train_x) - train_y) ** 2).sum() / 2
    losses.append(loss)
    # d0 = 此時對w0求偏導數的函數值(w1爲常量) --> 此處的斜率值
    d0 = ((w0[-1] + w1[-1] * train_x) - train_y).sum()
    # d1 = 此時對w1求偏導數的函數值(w0爲常量) --> 此處的斜率值
    d1 = (((w0[-1] + w1[-1] * train_x) - train_y) * train_x).sum()
    print('{:4}> w0={:.8f}, w1={:.8f}, loss={:.8f}'.format(epoches[-1], w0[-1], w1[-1], losses[-1]))
    # 更新w0,w1(用w0的偏導數更新w0, 用w1...)  w0=w0-lrate*d0 
    w0.append(w0[-1] - lrate * d0)
    w1.append(w1[-1] - lrate * d1)

# w0[-1] 和 w1[-1] 爲1000次梯度下降後的最終 w0,w1 值
# 
pred_test_y = w0[-1] + w1[-1] * test_x
# 畫圖
mp.figure('Linear Regression', facecolor='lightgray')
mp.title('Linear Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(train_x, train_y, marker='s', c='dodgerblue', alpha=0.5, s=80, label='Training')
mp.scatter(test_x, test_y, marker='D', c='orangered', alpha=0.5, s=60, label='Testing')
mp.scatter(test_x, pred_test_y, c='orangered', alpha=0.5, s=80, label='Predicted')
mp.plot(test_x, pred_test_y, '--', c='limegreen', label='Regression', linewidth=1)
mp.legend()
mp.show()
  1. 繪製隨着每次梯度下降,w0,w1,loss的變化曲線。
w0 = w0[:-1]
w1 = w1[:-1]

mp.figure('Training Progress', facecolor='lightgray')
mp.subplot(311)
mp.title('Training Progress', fontsize=20)
mp.ylabel('w0', fontsize=14)
mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, w0, c='dodgerblue', label='w0')
mp.legend()
mp.subplot(312)
mp.ylabel('w1', fontsize=14)
mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, w1, c='limegreen', label='w1')
mp.legend()

mp.subplot(313)
mp.xlabel('epoch', fontsize=14)
mp.ylabel('loss', fontsize=14)
mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, losses, c='orangered', label='loss')
mp.legend()
  1. 基於三維曲面繪製梯度下降過程中的每一個點。
import mpl_toolkits.mplot3d as axes3d

grid_w0, grid_w1 = np.meshgrid(
    np.linspace(0, 9, 500),
    np.linspace(0, 3.5, 500))

grid_loss = np.zeros_like(grid_w0)
for x, y in zip(train_x, train_y):
    grid_loss += ((grid_w0 + x*grid_w1 - y) ** 2) / 2

mp.figure('Loss Function')
ax = mp.gca(projection='3d')
mp.title('Loss Function', fontsize=20)
ax.set_xlabel('w0', fontsize=14)
ax.set_ylabel('w1', fontsize=14)
ax.set_zlabel('loss', fontsize=14)
ax.plot_surface(grid_w0, grid_w1, grid_loss, rstride=10, cstride=10, cmap='jet')
ax.plot(w0, w1, losses, 'o-', c='orangered', label='BGD')
mp.legend()
  1. 以等高線的方式繪製梯度下降的過程。
mp.figure('Batch Gradient Descent', facecolor='lightgray')
mp.title('Batch Gradient Descent', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.contourf(grid_w0, grid_w1, grid_loss, 10, cmap='jet')
cntr = mp.contour(grid_w0, grid_w1, grid_loss, 10,
                  colors='black', linewidths=0.5)
mp.clabel(cntr, inline_spacing=0.1, fmt='%.2f',
          fontsize=8)
mp.plot(w0, w1, 'o-', c='orangered', label='BGD')
mp.legend()
mp.show()

線性迴歸

線性迴歸相關API:

from sklearn import linear_model
# 創建線型迴歸模型
model = lm.LinearRegression()
# 訓練模型
# 輸入爲一個二維數組表示的樣本矩陣
# 輸出爲每個樣本最終的結果(一維數組)
model.fit(輸入, 輸出) # 通過梯度下降法計算模型參數
# 預測輸出  
# 輸入array是一個二維數組,每一行是一個樣本,每一列是一個特徵。
result = model.predict(array)

案例:基於線性迴歸訓練single.txt中的訓練樣本,使用模型預測測試樣本。

import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp
# 採集數據
# 4.94,4.37
# -1.58,1.7
# ...
x, y = np.loadtxt('../data/single.txt', delimiter=',', usecols=(0,1), unpack=True)
x = x.reshape(-1, 1)
# 創建模型
model = lm.LinearRegression()  # 線性迴歸
# 訓練模型
model.fit(x, y)
# 根據輸入預測輸出
pred_y = model.predict(x)
mp.figure('Linear Regression', facecolor='lightgray')
mp.title('Linear Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x, y, c='dodgerblue', alpha=0.75, s=60, label='Sample')
mp.plot(x, pred_y, c='orangered', label='Regression')
mp.legend()
mp.show()

評估訓練結果誤差(metrics)

線性迴歸模型訓練完畢後,可以利用測試集評估訓練結果誤差。sklearn.metrics提供了計算模型誤差的幾個常用算法:

import sklearn.metrics as sm

# 平均絕對值誤差:1/m∑|實際輸出-預測輸出|
sm.mean_absolute_error(y, pred_y)
# 平均平方誤差:SQRT(1/mΣ(實際輸出-預測輸出)^2)
sm.mean_squared_error(y, pred_y)
# 中位絕對值誤差:MEDIAN(|實際輸出-預測輸出|)
sm.median_absolute_error(y, pred_y)
# R2得分,(0,1]區間的分值。分數越高,誤差越小。
sm.r2_score(y, pred_y)

案例:在上一個案例中使用sm評估模型誤差。

# 平均絕對值誤差:1/m∑|實際輸出-預測輸出|
print(sm.mean_absolute_error(y, pred_y))
# 平均平方誤差:SQRT(1/mΣ(實際輸出-預測輸 出)^2)
print(sm.mean_squared_error(y, pred_y))
# 中位絕對值誤差:MEDIAN(|實際輸出-預測輸出|)
print(sm.median_absolute_error(y, pred_y))
# R2得分,(0,1]區間的分值。分數越高,誤差越小。
print(sm.r2_score(y, pred_y))

模型的保存和加載

模型訓練是一個耗時的過程,一個優秀的機器學習是非常寶貴的。可以模型保存到磁盤中,也可以在需要使用的時候從磁盤中重新加載模型即可。不需要重新訓練。

模型保存和加載相關API:

import pickle
pickle.dump(內存對象, 磁盤文件) # 保存模型
model = pickle.load(磁盤文件)  # 加載模型

案例:把訓練好的模型保存到磁盤中。

# 將訓練好的模型對象保存到磁盤文件中
with open('../../data/linear.pkl', 'wb') as f:
    pickle.dump(model, f)
    
# 從磁盤文件中加載模型對象
with open('../../data/linear.pkl', 'rb') as f:
    model = pickle.load(f)
# 根據輸入預測輸出
pred_y = model.predict(x)

嶺迴歸

普通線性迴歸模型使用基於梯度下降的最小二乘法,在最小化損失函數的前提下,尋找最優模型參數,於此過程中,包括少數異常樣本在內的全部訓練數據都會對最終模型參數造成程度相等的影響,異常值對模型所帶來影響無法在訓練過程中被識別出來。爲此,嶺迴歸在模型迭代過程所依據的損失函數中增加了正則項,以限制模型參數對異常樣本的匹配程度,進而提高模型面對多數正常樣本的擬合精度。

import sklearn.linear_model as lm
# 創建模型
model = lm.Ridge(正則強度,fit_intercept=是否訓練截距, max_iter=最大迭代次數)
# 訓練模型
# 輸入爲一個二維數組表示的樣本矩陣
# 輸出爲每個樣本最終的結果
model.fit(輸入, 輸出)
# 預測輸出  
# 輸入array是一個二維數組,每一行是一個樣本,每一列是一個特徵。
result = model.predict(array)

案例:加載abnormal.txt文件中的數據,基於嶺迴歸算法訓練迴歸模型。

import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp
# 採集數據
x, y = np.loadtxt('../data/single.txt', delimiter=',', usecols=(0,1), unpack=True)
x = x.reshape(-1, 1)
# 創建線性迴歸模型
model = lm.LinearRegression() 
# 訓練模型
model.fit(x, y)
# 根據輸入預測輸出
pred_y1 = model.predict(x)
# 創建嶺迴歸模型
model = lm.Ridge(150, fit_intercept=True, max_iter=10000) 
# 訓練模型
model.fit(x, y)
# 根據輸入預測輸出
pred_y2 = model.predict(x)

mp.figure('Linear & Ridge', facecolor='lightgray')
mp.title('Linear & Ridge', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x, y, c='dodgerblue', alpha=0.75,
           s=60, label='Sample')
sorted_indices = x.T[0].argsort()
mp.plot(x[sorted_indices], pred_y1[sorted_indices],
        c='orangered', label='Linear')
mp.plot(x[sorted_indices], pred_y2[sorted_indices],
        c='limegreen', label='Ridge')
mp.legend()
mp.show()

多項式迴歸

若希望迴歸模型更好的擬合訓練樣本數據,可以使用多項式迴歸器。

一元多項式迴歸

y=w0 + w1 x + w2 x2 + w3 x3 + … + wd xd

將高次項看做對一次項特徵的擴展得到:

y=w0 + w1 x1 + w2 x2 + w3 x3 + … + wd xd

那麼一元多項式迴歸即可以看做爲多元線性迴歸,可以使用LinearRegression模型對樣本數據進行模型訓練。

所以一元多項式迴歸的實現需要兩個步驟:

  1. 將一元多項式迴歸問題轉換爲多元線性迴歸問題(只需給出多項式最高次數即可)。
  2. 將1步驟得到多項式的結果中 w1 w2 … 當做樣本特徵,交給線性迴歸器訓練多元線性模型。

使用sklearn提供的數據管線實現兩個步驟的順序執行:

import sklearn.pipeline as pl
import sklearn.preprocessing as sp
import sklearn.linear_model as lm

model = pl.make_pipeline(
    sp.PolynomialFeatures(10),  # 多項式特徵擴展器
    lm.LinearRegression())      # 線性迴歸器

案例:

import numpy as np
import sklearn.pipeline as pl
import sklearn.preprocessing as sp
import sklearn.linear_model as lm
import sklearn.metrics as sm
import matplotlib.pyplot as mp
# 採集數據
x, y = np.loadtxt('../data/single.txt', delimiter=',', usecols=(0,1), unpack=True)
x = x.reshape(-1, 1)
# 創建模型(管線)
model = pl.make_pipeline(
    sp.PolynomialFeatures(10),  # 多項式特徵擴展器
    lm.LinearRegression())      # 線性迴歸器
# 訓練模型
model.fit(x, y)
# 根據輸入預測輸出
pred_y = model.predict(x)
test_x = np.linspace(x.min(), x.max(), 1000).reshape(-1, 1)
pred_test_y = model.predict(test_x)
mp.figure('Polynomial Regression', facecolor='lightgray')
mp.title('Polynomial Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x, y, c='dodgerblue', alpha=0.75, s=60, label='Sample')
mp.plot(test_x, pred_test_y, c='orangered', label='Regression')
mp.legend()
mp.show()

過於簡單的模型,無論對於訓練數據還是測試數據都無法給出足夠高的預測精度,這種現象叫做欠擬合。

過於複雜的模型,對於訓練數據可以得到較高的預測精度,但對於測試數據通常精度較低,這種現象叫做過擬合。

一個性能可以接受的學習模型應該對訓練數據和測試數據都有接近的預測精度,而且精度不能太低。

訓練集R2   測試集R2
0.3        0.4        欠擬合:過於簡單,無法反映數據的規則
0.9        0.2        過擬合:過於複雜,太特殊,缺乏一般性
0.7        0.6        可接受:複雜度適中,既反映數據的規則,同時又不失一般性

決策樹

基本算法原理

核心思想:相似的輸入必會產生相似的輸出。例如預測某人薪資:

年齡: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 ==> ?

爲了提高搜索效率,使用樹形數據結構處理樣本數據:
=1{123=2{123=3{123 年齡=1\left\{ \begin{aligned} 學歷1 \\ 學歷2 \\ 學歷3 \\ \end{aligned} \right. \quad\quad 年齡=2\left\{ \begin{aligned} 學歷1 \\ 學歷2 \\ 學歷3 \\ \end{aligned} \right. \quad\quad 年齡=3\left\{ \begin{aligned} 學歷1 \\ 學歷2 \\ 學歷3 \\ \end{aligned} \right.
首先從訓練樣本矩陣中選擇第一個特徵進行子表劃分,使每個子表中該特徵的值全部相同,然後再在每個子表中選擇下一個特徵按照同樣的規則繼續劃分更小的子表,不斷重複直到所有的特徵全部使用完爲止,此時便得到葉級子表,其中所有樣本的特徵值全部相同。對於待預測樣本,根據其每一個特徵的值,選擇對應的子表,逐一匹配,直到找到與之完全匹配的葉級子表,用該子表中樣本的輸出,通過平均(迴歸)或者投票(分類)爲待預測樣本提供輸出。

隨着子表的劃分,信息熵(信息的混亂程度)越來越小,信息越來越純,數據越來越有序。

決策樹迴歸器模型相關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. 讀取數據,打斷原始數據集。 劃分訓練集和測試集。
import sklearn.datasets as sd
import sklearn.utils as su
# 加載波士頓地區房價數據集
boston = sd.load_boston()
print(boston.feature_names)
# |CRIM|ZN|INDUS|CHAS|NOX|RM|AGE|DIS|RAD|TAX|PTRATIO|B|LSTAT|
# 犯罪率|住宅用地比例|商業用地比例|是否靠河|空氣質量|房間數|年限|距中心區距離|路網密度|房產稅|師生比|黑人比例|低地位人口比例|
# 打亂原始數據集的輸入和輸出
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:]
  1. 創建決策樹迴歸器模型,使用訓練集訓練模型。使用測試集測試模型。
import sklearn.tree as st
import sklearn.metrics as sm

# 創建決策樹迴歸模型
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))

工程優化

不必用盡所有的特徵,葉級子表中允許混雜不同的特徵值,以此降低決策樹的層數,在精度犧牲可接受的前提下,提高模型的性能。通常情況下,可以優先選擇使信息熵減少量最大的特徵作爲劃分子表的依據。

集合算法

根據多個不同模型給出的預測結果,利用平均(迴歸)或者投票(分類)的方法,得出最終預測結果。

基於決策樹的集合算法,就是按照某種規則,構建多棵彼此不同的決策樹模型,分別給出針對未知樣本的預測結果,最後通過平均或投票得到相對綜合的結論。

正向激勵

首先爲樣本矩陣中的樣本隨機分配初始權重,由此構建一棵帶有權重的決策樹,在由該決策樹提供預測輸出時,通過加權平均或者加權投票的方式產生預測值。將訓練樣本代入模型,預測其輸出,對那些預測值與實際值不同的樣本,提高其權重,由此形成第二棵決策樹。重複以上過程,構建出不同權重的若干棵決策樹。

正向激勵相關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)

案例:基於正向激勵訓練預測波士頓地區房屋價格的模型。

# 創建基於決策樹的正向激勵迴歸器模型
model = se.AdaBoostRegressor(
	st.DecisionTreeRegressor(max_depth=4), 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_來存儲每個特徵的重要性。

獲取樣本矩陣特徵重要性屬性:

model.fit(train_x, train_y)
fi = model.feature_importances_

案例:獲取普通決策樹與正向激勵決策樹訓練的兩個模型的特徵重要性值,按照從大到小順序輸出繪圖。

import matplotlib.pyplot as mp

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()
自助聚合

每次從總樣本矩陣中以有放回抽樣的方式隨機抽取部分樣本構建決策樹,這樣形成多棵包含不同訓練樣本的決策樹,以削弱某些強勢樣本對模型預測結果的影響,提高模型的泛化特性。

隨機森林

在自助聚合的基礎上,每次構建決策樹模型時,不僅隨機選擇部分樣本,而且還隨機選擇部分特徵,這樣的集合算法,不僅規避了強勢樣本對預測結果的影響,而且也削弱了強勢特徵的影響,使模型的預測能力更加泛化。

隨機森林相關API:

import sklearn.ensemble as se
# 隨機森林迴歸模型	(屬於集合算法的一種)
# max_depth:決策樹最大深度10
# n_estimators:構建1000棵決策樹,訓練模型
# min_samples_split: 子表中最小樣本數 若小於這個數字,則不再繼續向下拆分
model = se.RandomForestRegressor(max_depth=10, n_estimators=1000, min_samples_split=2)

案例:分析共享單車的需求,從而判斷如何進行共享單車的投放。

import numpy as np
import sklearn.utils as su
import sklearn.ensemble as se
import sklearn.metrics as sm
import matplotlib.pyplot as mp

data = np.loadtxt('../data/bike_day.csv', unpack=False, dtype='U20', delimiter=',')
day_headers = data[0, 2:13]
x = np.array(data[1:, 2:13], dtype=float)
y = np.array(data[1:, -1], dtype=float)

x, y = su.shuffle(x, y, random_state=7)
print(x.shape, y.shape)
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_dy = model.feature_importances_
pred_test_y = model.predict(test_x)
print(sm.r2_score(test_y, pred_test_y))

data = np.loadtxt('../data/bike_hour.csv', unpack=False, dtype='U20', delimiter=',')
hour_headers = data[0, 2:13]
x = np.array(data[1:, 2:13], dtype=float)
y = np.array(data[1:, -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, day_headers[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, hour_headers[sorted_indices], rotation=30)
mp.tight_layout()
mp.show()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章