关于线性回归的详细介绍能够参见个人上一篇博文《线性回归:最小二乘法实现》。在《线性回归:最小二乘法实现》中我已经说明了线性回归模型创建的关键在于求解: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()
均方偏差:
代价曲线:
拟合曲线: