關於線性迴歸的詳細介紹能夠參見個人上一篇博文《線性迴歸:最小二乘法實現》。在《線性迴歸:最小二乘法實現》中我已經說明了線性迴歸模型創建的關鍵在於求解:html
這裏再介紹另外一種求解算法:梯度降低法。python
假設有如下問題:算法
經過泰勒一階展開則有:函數
圖示以下:測試
這裏的\(w-w_0\)表示了移動的步長和方向,那麼能夠有\(w-w_0=\eta\gamma\),\(\eta\)爲實數,表示移動的步長,\(\gamma\)爲一個單位向量,表示步長移動的方向。\(f(w_0)+(w-w_0)∇f(w_0)\)則是\(f(w)\)在\(w\)處的鄰近估計,此處要求\(\eta\)較小,不然將致使估計的精確度下降。
梯度降低算法的目的是讓優化函數\(f(w)\)儘快到達全局最小值,因此便有了第一個條件:優化
因爲\(\eta\)是一個大於0的常數,因此能夠暫不考慮。那麼就須要知足\(\eta\gamma∇f(w_0)≤0\)而且儘量小。又有:spa
因此想要使\(\eta\gamma∇f(w_0)≤0\)而且儘量小則須要知足條件:code
換句話說,也就是要求單位向量\(\gamma\)和\(∇f(w_0)\)方向徹底相反,因此即可以獲得如下結論:orm
將\(condition3\)帶入\(w-w_0=\eta\gamma\),則有:htm
因爲\(\eta\)和\(|∇f(w_0)|\)都是大於0的實數,因此能夠合併爲新的\(\eta^*=\frac{\eta}{|∇f(w_0)|}\),再對等式進行移項即可以獲得:
\(condition5\)即是梯度降低算法中\(f(w)\)的參數\(w\)的更新公式。同時這也解釋了爲何須要以梯度的反方向來更新權重。
下面就用梯度降低算法來對線性迴歸模型進行優化。這裏將線性迴歸模型的代價函數E寫爲以下形式(方便運算):
對其求導:
由前面的\(condition5\)能夠獲得權重的更新公式:\(w^*=w+\Delta w\),此處的\(\Delta w=-\eta∇f(w_0)\)。因此最終能夠獲得權重的更新公式爲:
由以前推導出的更新公式能夠實現出如下擬合算法:
def _gradient_descent(self, X, y): for i in range(max_iter): delta = y - self._linear_func(X) self.W[0] += self.eta * sum(delta) / X.shape[0] # 第一列所有爲1 self.W[1:] += self.eta * (delta @ X) / X.shape[0]
導入波士頓數據集進行測試:
if __name__ == "__main__": from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler boston = datasets.load_boston() X = boston.data y = boston.target scaler = MinMaxScaler().fit(X) X = scaler.transform(X) X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, test_size=0.3) lr = LinearRegression().fit(X_train, y_train) y_pred = lr.predict(X_test) from sklearn.metrics import mean_squared_error print(mean_squared_error(y_test, y_pred)) plt.figure() plt.plot(range(len(y_test)), y_test) plt.plot(range(len(y_pred)), y_pred) plt.legend(["test", "pred"]) plt.show()
均方偏差:
代價曲線:
擬合曲線: