回歸演算法之線性回歸
起步
線性回歸是利用數理統計和歸回分析,來確定兩種或兩種以上變數間相互依賴的定量關係的一種統計分析方法。與之前的分類問題( Classification
)不一樣的是,分類問題的結果是離散型的;而回歸問題中的結果是數值型的。
描述數據特徵
數理統計中,常用的描述數據特徵的有:
均值( mean ):
又稱平均數或平均值,是計算樣本中算術平均數:
中位數( median )
將數據中的各個數值按照大小順序排列,居於中間位置的變數。
眾數( mode )
數據中出現次數最多的數。
方差( variance )
這是一種描述離散程度的衡量方式:
標準差 (standard deviation)
將方差開方就能得到標準差。
簡單線性回歸
簡單線性回歸( Simple Linear Regression
)包含一個自變數 x 和一個因變數 y ,也就是一元線性回歸。被用來描述因變數(y)和自變數(X)以及偏差(error)之間關係的方程叫做回歸模型,這個模型是:
其中偏差 ε 滿足正態分布的。因此它的期望值是 0 。ε的方差(variance)對於所有的自變數 x 是一樣的。
因此式子也可以寫成:
其中,β0 是回歸線的截距,β1 是回歸線的斜率,E(y) 是在一個給定 x 值下 y 的期望值(均值)。
假設我們的估值函數(注意,是估計函數):
β 和 b 有什麼關係呢?
β0 是表示回歸方程中真實的值,而 b0 是對 β0 的估值,通過訓練能讓 b0 趨近於 β0 。從而提高估值函數準確度。
如何練處適合簡單線性回歸模型的最佳回歸線?
尋找的回歸方程,是與真實值的離散程度最小的:
這就類似於高中學的最小二乘法了,利用那時候學到的公式套上去就能得到該方程了:
最小二乘法的推導過程可以查看維基,寫得非常清楚:https://zh.wikipedia.org/wiki/最小二乘法
對應的python代碼:
class SimpleLinearRegression(object):n """n 簡單線性回歸方程,即一元線性回歸,只有一個自變數,估值函數為: y = b0 + b1 * xn """n def __init__(self):n self.b0 = 0n self.b1 = 0n def fit(self, x: list, y: list):n n = len(x)n x_mean = sum(x) / nn y_mean = sum(y) / nn dinominator = 0n numerator = 0n for xi, yi in zip(x, y):n numerator += (xi - x_mean) * (yi - y_mean)n dinominator += (xi - x_mean) ** 2n self.b1 = numerator / dinominatorn self.b0 = y_mean - self.b1 * x_meannn def pridict(self, x):n return self.b0 + self.b1 * xn
多元線性回歸
當自變數有多個時,回歸模型就變成了:
估值函數的自變數也變多:
令矩陣:
函數可以寫成:
有訓練數據:
損失函數( cost function
),尋找的目標函數應該讓損失函數儘可能小,這個損失函數為:
目的就是求解出一個使得代價函數最小的 B。
梯度下降求解估值函數
梯度下降演算法是一種求局部最優解的方法,這部分演算法可以查看https://www.cnblogs.com/pinard/p/5970503.html 了解下,這裡不展開。B 由多個元素組成,對於損失函數可以求偏導如下:
更新B:
其中 α 表示學習率,決定了在梯度下降迭代的過程中,每一步沿梯度負方向前進的長度。
最小二乘法求解估值函數
多元多項式的情況一樣可以利用最小二乘法來進行求解,將 m
條數據都帶入估值函數可以得到線性方程組:
向量化表示:
因為要使:
的值最小,則係數矩陣中,各個參數的偏導的值都會0,因此可以得到 n 個等式:
得到正規方程組:
寫成矩陣表示為:
解得:
有的解法會把矩陣 X 的轉置寫成 X
,我比較習慣用上標 T 表示。
對應的python代碼:
import numpy as npnclass MyLinearRegression(object):n def __init__(self):n self.b = []nn def fit(self, x: list, y: list):n # 為每條訓練數據前都添加 1,作為 b0 的係數n point_num, future_num = np.shape(x)n tmpx = np.ones(shape=(point_num, future_num + 1))n tmpx[:,1 :] = xnn x_mat = np.mat(tmpx)n y_mat = np.mat(y).Tn xT = x_mat.Tn self.b = (xT * x_mat).I * xT * y_matnn def predict(self, x):n return np.mat([1] + x) * self.bn
具體的實現居然這麼幾行就搞定了,數學化簡真的是很有必要的。
測試
將我們書寫的代碼與 sklearn
的進行對比看看:
# coding: utf-8nfrom sklearn import linear_modelnnx = [n [100.0, 4.0],n [50.0, 3.0],n [100.0, 4.0],n [100.0, 2.0],n [50.0, 2.0],n [80.0, 2.0],n [75.0, 3.0],n [65.0, 4.0],n [90.0, 3.0],n [90.0, 2.0]n]nny = [9.3, 4.8, 8.9, 6.5, 4.2, 6.2, 7.4, 6.0, 7.6, 6.1]nntest_row = [50, 3]nlinear = MyLinearRegression()nlinear.fit(x, y)nprint(linear.predict(test_row)) # [[ 4.95830457]]nnsk = linear_model.LinearRegression()nsk.fit(x, y)nprint(sk.predict([test_row])) # [ 4.95830457]n
看,能和機器學習庫的結果一模一樣,真是開心無比。
總結
在線性回歸方程的求解中,因為梯度下降求得是局部最優解,且係數需要隨機初始化,因此一般解法是採用最小二乘法。最小二乘法中,如果兩個訓練數據一致,那麼訓練出來的模型也會一模一樣。
推薦閱讀:
※如何簡明地解釋「線性回歸」「貝葉斯定理」「假設檢驗」這些術語?
※機器學習筆記9 —— 過擬合和正則化
※請問為何「E(XY)=E(X)E(Y)」或者「相關係數=0」等價於「變數之間沒有線性關係」?有沒有幾何解釋呢?
※【預測演算法】01. 線性回歸原理及R語言實現
※線性回歸建模中殘差異方差性的分析和處理