欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

线性回归模型算法原理及Python实现

发布时间:2023/12/19 python 32 豆豆
生活随笔 收集整理的这篇文章主要介绍了 线性回归模型算法原理及Python实现 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

文章内容主要来自Aurelien Geron《Hands-on Machine Learning withi Scikit-Learn&TensorFlow》

目录

线性回归方程

参数求解方法一:标准方程

手动求解线性回归方程

使用sklearn计算线性回归方程

参数求解方法二:梯度下降

学习率

梯度下降陷阱

梯度下降特征缩放问题

批量梯度下降(batch gradient descent)

随机梯度下降方法(Stochastic Gradient Descent,SGD)

Python手动实现随机梯度下降

使用sk-learn 实现随机梯度下降

小批量梯度下降(mini batch)

线性回归求解方法比较


线性回归方程

线性回归模型的一般表达式:

转换为向量表达形式为:

训练线性回归模型,主要是得到一组向量,使得均方误差MSE(成本函数)最小

参数求解方法一:标准方程

MSE为凸函数,有唯一最优解(最小值),为了求解,可以令MSE对求偏导数为0,得到解:

手动求解线性回归方程

现在我们来使用标准方程计算:

import numpy as npX = 2 * np.random.rand(100, 1) # 生存100 X 1维向量(均匀分布随机数) y = 4 + 3 * X + np.random.randn(100, 1) # 生存100 X 1维向量(正态分布随机数)# 使用np.linalg中对inv()求逆矩阵,使用dot()方法计算矩阵对内积 X_b = np.c_[np.ones((100, 1)), X] # add x0 = 1 to each instance # X_b为X加上一个常数项 theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)>>>theta_best array([[4.21509616],[2.77011339]])我们期待的是theta_0=4, theta_1=3,得到 theta_0=3.865,theta_1=3.139, 非常接近,噪音的存在使得其不可能还原为原函数可以 使用theta进行预测X_new = np.array([[0], [2]]) # X取0,2进行预测y X_new_b = np.c_[np.ones((2, 1)), X_new] # add x0 = 1 to each instance y_predict = X_new_b.dot(theta_best) y_predict array([[4.21509616],[9.75532293]])

绘制模型的预测结果:

plt.plot(X_new, y_predict, "r-") plt.plot(X, y, "b.") plt.axis([0, 2, 0, 15]) plt.show()

使用sklearn计算线性回归方程

>>>from sklearn.linear_model import LinearRegression >>>lin_reg = LinearRegression() >>>lin_reg.fit(X, y) >>>lin_reg.intercept_, lin_reg.coef_ # 线性回归方程参数 (array([4.21509616]), array([[2.77011339]]))>>>lin_reg.predict(X_new) array([[4.21509616],[9.75532293]])

标准方程求解的问题

标准方程求解需要求解逆矩阵,但并不是所有的矩阵都有逆矩阵,比如奇异矩阵,矩阵不可逆,其原因主要有两个方面:

1. 部分特征线性相关,这种情况下,可以考虑删除部分冗余特征

2. 特征数量大于样本数量(这种情况不一定会导致矩阵不可逆,但肯能会导致不可逆)

对于矩阵不可逆的情况,可以用“伪逆矩阵” 替代“逆矩阵”,通常可以得到解的结果。

参数求解方法二:梯度下降

梯度下降是一种非常通用的优化算法,能够为大范围的问题找到最优解。梯度下降的中心思想就是迭代地调整参数从而使得成本函数最小化。

具体的来说,首先使用一个随机的值(这称为随机初始化),然后逐步改进,每次踏出一小步,每一步都尝试降低一点成本函数,直到算法收敛出一个最小值

学习率

梯度下降的一个重要参数是每一步的步长,取决于学习率。如果学习率太低,算法需要经过大量的迭代才能收敛,这将耗费很长的时间,如果学习率太高,可能会越过山谷到达山的另一边,甚至可能比之前的起点还要高,会导致算法发散。

梯度下降陷阱

并不是所有的成本函数都是一个凸函数(形状看起来像个碗),可能是不规则形状如图,这样随机梯度下降方法存在两个主要挑战:

1. 如果随机初始化算法从左侧起步,容易收敛到局部最小值而非全局最小值;

2. 如果算法从右侧起步,那么需要经过很长都时间才能越过整片高原,如果停下来太早,将达不到全局最小。

但线性回归模型但MSE是凸函数,也就是说不存在局部最小,只有全局最小,这对使用梯度下降求解线性回归方程非常有保障。

梯度下降特征缩放问题

如果不同特征对尺寸差别巨大,可能会造成收敛对时间大大增加。比如右边训练集特征1比特征2小得多,梯度下降先是沿着全局最小对方向垂直前进,接下来是一段近乎平坦的长长的山谷,这段算法收敛需要大量时间。所以,在运用梯度下降时,需要保证所有特征值比例都差不多(可使用scikit-learn的StandardScaler)

批量梯度下降(batch gradient descent)

每一步计算梯度下降都使用完整的训练集X进行计算,这导致在训练集样本很大时变得很慢。

要实现梯度下降,需要计算模型关于参数成本函数的梯度,成本函数的偏导数:

也可以写出梯度向量的方式:

则每一个梯度的步长为:

其中η为学习率。

eta = 0.1 n_iterations = 1000 m = 100 theta = np.random.randn(2,1)for iteration in range(n_iterations):gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y) # 成本函数的梯度公式theta = theta - eta * gradients # theta与学习率关系公式>>>theta array([[4.21509616],[2.77011339]])

可以看出,比较容易求出来theta值。

不同学习率η,梯度下降前10步的线性回归函数(theta值)

说明:左图学习率低,需要较长时间;中图学习率合适,很快算法就收敛;由于学习率太大,算法发散,直接跳过来数据区域,并且离实际解越来越远。

随机梯度下降方法(Stochastic Gradient Descent,SGD)

当训练的数据集非常大时,为了克服批量梯度下降耗时非常长的缺点(因为需要使用全量数据进行训练),而采用每一步在训练中随机选择一个实例,并且仅基于该实例来计算梯度。这样计算速度快多了,另一方面,由于实例选择的随机性,他比批量下降要不规则得多。成本函数不再是缓慢下降直到抵达最小值,而是不断上上下下,不断接近最小值,但是即时达到了最小值,依旧会持续反弹,永远不会停止。因此,算法停下来参数值肯定是足够好但,但不是最优。

当成本函数不规则时,随机梯度但好处是可以逃离局部最优,但缺点永远定位不出最小值。要解决这个问题,有一个办法是逐步降低学习率,开始时,步长比较大(有助于快速进展和逃离局部最小),然后越来越小,让算法尽量靠近全局最小,这个过程也叫模拟退火,因为它类似于冶金时金属融化后慢慢冷却但退火过程。

下面这段代码使用一个简单的学习计划实现随机梯度下降:

Python手动实现随机梯度下降

# 手动随机梯度下降 m = len(X_b) n_epochs = 50 t0, t1 = 5, 50 # learning schedule hyperparametersdef learning_schedule(t):return t0 / (t + t1)theta = np.random.randn(2,1) # random initializationfor epoch in range(n_epochs):for i in range(m):#随机选出一个实例进行梯度计算random_index = np.random.randint(m)xi = X_b[random_index:random_index+1] yi = y[random_index:random_index+1]gradients = 2 * xi.T.dot(xi.dot(theta) - yi)eta = learning_schedule(epoch * m + i)theta = theta - eta * gradients >>>theta array([[4.21076011],[2.74856079]])

进行50轮迭代就可以得到不错的结果,而批量梯度下降要1000次。

使用sk-learn 实现随机梯度下降

from sklearn.linear_model import SGDRegressor sgd_reg = SGDRegressor(max_iter=50, tol=-np.infty, penalty=None, eta0=0.1, random_state=42) sgd_reg.fit(X, y.ravel())>>>sgd_reg.intercept_, sgd_reg.coef_ (array([4.16782089]), array([2.72603052]))

得到跟标准方程近似的解决方案

小批量梯度下降(mini batch)

介于批量梯度下降和随机梯度下降中间的方法,即每一步梯度的计算,既不是基于整个训练集,也不是基于单个实例,而是基于一小批随机的实例集。所以它速度比批量梯度快,且比随机梯度稳定,但也容易先入局部最优问题。

线性回归求解方法比较

m为样本数,n为特征数

标准方程梯度下降
需要设置参数如学习率不需要需要
需要很多次迭代不需要需要
特征数的影响n<1000时,一般采用标准方程n>10000时,一般采用梯度下降
样本数量的影响影响不大影响大,可以采用随机梯度和小批量梯度加快求解速度

总结

以上是生活随笔为你收集整理的线性回归模型算法原理及Python实现的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。