目錄python
本章內容算法
前面的章節給你們介紹了監督學習的分類部分,接下來幾章將會帶領同窗們翱翔浩瀚的迴歸海洋,注意此迴歸不是 Logistic 迴歸(Logistic 迴歸之因此取名爲這是由於歷史遺留問題)。具體是什麼,那就開始讓咱們來揭祕吧!
注意: 分類的目標變量是標稱型數據;迴歸的目標變量是連續性數據。api
# coding: 'utf-8' import os import numpy as np import matplotlib.pyplot as plt from path_settings import machine_learning_PATH data_set_path = os.path.join(machine_learning_PATH, '第八章/data-set') ex0_path = os.path.join(data_set_path, 'ex0.txt') ex1_path = os.path.join(data_set_path, 'ex1.txt') abalone_path = os.path.join(data_set_path, 'abalone.txt') def load_data_set(filename): # 文本第一行值全爲0的解釋:簡單說是由於兩個矩陣相乘一個矩陣的行和另外一個矩陣的列得相等,具體可查資料 num_feat = len(open(filename).readline().split('\t')) - 1 data_mat = [] label_mat = [] fr = open(filename) for line in fr.readlines(): line_arr = [] cur_line = line.strip().split('\t') for i in range(num_feat): line_arr.append(float(cur_line[i])) data_mat.append(line_arr) label_mat.append(float(cur_line[-1])) return data_mat, label_mat def stand_regres(x_arr, y_arr): x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) x_tx = x_mat.T * x_mat # 判斷矩陣是否爲奇異矩陣,即矩陣是否有逆矩陣 if np.linalg.det(x_tx) == 0: print("奇異矩陣沒有逆矩陣") return ws = x_tx.I * (x_mat.T * y_mat.T) # 求解未知矩陣 # ws = np.linalg.solve(x_tx,x_mat.T*y_mat.T) return x_mat, y_mat, ws def test_stand_regres(): x_arr, y_arr = load_data_set(ex0_path) _, _, ws = stand_regres(x_arr, y_arr) print(ws) if __name__ == '__main__': test_stand_regres()
def plot_stand_regres(x_mat, y_mat, ws): fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(x_mat[:, 1].flatten().A[0], y_mat.T[:, 0].flatten().A[0]) x_copy = x_mat.copy() x_copy.sort(0) y_hat = x_copy * ws ax.plot(x_copy[:, 1], y_hat) plt.show() def test_plot_stand_regres(): x_arr, y_arr = load_data_set(ex0_path) x_mat, y_mat, ws = stand_regres(x_arr, y_arr) plot_stand_regres(x_mat, y_mat, ws) # 判斷擬合效果 print(np.corrcoef((x_mat * ws).T, y_mat)) ''' [[1. 0.98647356] [0.98647356 1. ]] ''' if __name__ == '__main__': # test_stand_regres() test_plot_stand_regres()
局部加權線性迴歸求迴歸係數公式:\(\hat{w}=(X^TWX)^{-1}X^TWy\)
app
最經常使用的核——高斯核:\(w(i,i)=exp\left({\frac{|x^{(i)}-x|}{-2k^2}}\right)\)
機器學習
點 x 與 x(i)越近,w(i,i)將會越大,參數 k 決定了對附近的點賦予多大的權重。函數
def lwlr(test_point, x_arr, y_arr, k=1): """給樣本點增長權重,參數 k 控制衰減的速度""" x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) m = np.shape(x_mat)[0] # 建立對角權重矩陣。該矩陣對角線元素全爲1,其他元素全爲0 weights = np.mat(np.eye(m)) for j in range(m): diff_mat = test_point - x_mat[j, :] weights[j, j] = np.exp(diff_mat * diff_mat.T / (-2 * k ** 2)) x_tx = x_mat.T * (weights * x_mat) if np.linalg.det(x_tx) == 0: print("奇異矩陣沒有逆矩陣") return ws = x_tx.I * (x_mat.T * (weights * y_mat.T)) return test_point * ws def lwlr_test(test_arr, x_arr, y_arr, k=1): """使數據集中每一個點調用 lwlr 方法""" m = np.shape(test_arr)[0] y_hat = np.zeros(m) for i in range(m): y_hat[i] = lwlr(test_arr[i], x_arr, y_arr, k) return y_hat def test_lwlr_test(): x_arr, y_arr = load_data_set(ex0_path) y_hat = lwlr_test(x_arr, x_arr, y_arr, 0.003) print(y_hat) def plot_lwlr(x_sort, y_hat, str_ind, x_mat, y_mat): fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x_sort[:, 1], y_hat[str_ind]) ax.scatter(x_mat[:, 1].flatten().A[0], y_mat.T[:, 0].flatten().A[0], s=2, c='red') plt.show() def test_plot_lwlr(): x_arr, y_arr = load_data_set(ex0_path) x_mat = np.mat(x_arr) y_mat = np.mat(y_arr) y_hat = lwlr_test(x_arr, x_arr, y_arr, 0.01) str_ind = x_mat[:, 1].argsort(0) x_sort = x_mat[str_ind][:, 0, :] plot_lwlr(x_sort, y_hat, str_ind, x_mat, y_mat) if __name__ == '__main__': # test_stand_regres() # test_plot_stand_regres() # test_lwlr_test() test_plot_lwlr()
因爲看完《機器學習實戰》第八章中的局部加權線性迴歸後,敲完代碼以後只是知道它是這樣的,但不是很清楚內在的緣由。書中並無對其作過多解釋,百度也找不到一篇很好的文章來解釋 線性迴歸和局部加權線性迴歸 二者之間的區別。索性寫一寫本身對 線性迴歸和局部加權線性迴歸 的見解與感悟。也許仍是不那麼準確,但必定是清晰易懂的。學習
其中的平方偏差是咱們的在 x=x~i~ 上預測值與實際值的差值平方,而咱們須要作的任務就是找到一個最合適的 w 使得該差值平方最小。測試
再來講說咱們的局部加權線性迴歸(LWLR),它只是在線性迴歸的基礎上加了一個權重,而LWLR一般使用「核」(相似於自持向量機中的核)來對附近的點賦予更高的權重。所以它的公式變成:google
\(\sum_{i=1}^mW_i(y_i-x^T_iw)^2\)
spa
注意:W~i~ 是賦予 x~i~ 權重的矩陣,也能夠是向量。
通常咱們的 W~i~ 最經常使用的核是高斯核:\(w(i,i)=exp\left({\frac{|x^{(i)}-x|}{-2k^2}}\right)\)
注意:高斯核中的 x 爲新預測樣本的特徵數據即新的 x,它同 w 也是一個向量,參數 k 控制了權值變化的速率。
以上介紹了局部加權線性迴歸的理論,如今經過圖像咱們再來形象化的解釋局部加權線性迴歸。首先看看不一樣 k 下的參數 k 與權重的關係:
重點來了,我剛開始不明白的就是這裏,上面 兩個注意+圖片解釋 其實已經揭曉了答案
離 x 很近的樣本,權值接近1;而離 x 很遠的樣本,此時權值接近於0,這樣就在 x 局部構成線性迴歸,x 構成的線性迴歸依賴的事 x 周邊的點,而不相似於線性迴歸依賴訓練集中的全部數據。
上圖紅線是某個點 x 基於訓練集中全部數據使用線性迴歸作的結果,黑色直線使用 LWLR 作的結果,因爲在每一個數據都會重複局部加權的過程,而且不斷地每一個點的迴歸係數也在不斷的改變,所以它會很好的擬合數據集,進而消除了線性迴歸擬合很差的缺點。(有點相似極限或者求導或者微積分的思想,總之就是把一個大的物體切割成一大部分,而後對於每一部分進行計算)。
說到了LWLR的優勢,不得不說說它的缺點,上一段講到了訓練集中的每一個數據都會重複局部加權的過程,所以他的計算量是龐大的,而且他的迴歸係數是基於周圍的數據計算出來的,所以下次須要預測某個數據的分類時,須要再一次輸入全部的數據。即線性迴歸算法是參數學習算法,一旦擬合出合適的迴歸係數,對於以後的預測,不須要再使用原始訓練數據集;局部加權線性迴歸算法是非參數學習算法,每次進行預測都須要所有的訓練數據,沒法算出固定的迴歸係數。
最後看一看 線性迴歸和不一樣 k 值的局部加權線性迴歸 對相同數據集的結果。
上圖第一張圖使用的是 k=1 的LWLR(相似於線性迴歸),第二張圖使用的是 k=0.01 的LWLR,第三張圖使用的 k=0.003 的 LWLR。第一張圖明顯欠擬合,第二張圖很合適,第三張圖過擬合。