线性回归算法梳理


我想从一个链进行讲述:

一. 机器学习:

因为我们是把我们人类的“经验”以数据的形式来存储,所以我们想着能不能让机器从这些数据进行学习,归纳中我们人类中的经验来进行推理。简称机器学习。
工程化定义:假设用P来评估计算机程序在某任务类T上的性能,若一个程序通过利用经验E在T中任务上获得了性能改善,则我们就说关于T和P,该程序对E进行了学习。
人话就是:我们想让机器从我们这些人类的经验进行学习来帮我们解决一些任务,解决这些问题都会有一个评价指标,作为机器完成这个任务的好坏。
其中机器学习所研究的主要内容,是关于在计算机上从数据中产生“模型”的算法,也就是学习“算法”。也就是说我们研究这些算法如何让机器更好地从数据中进行学习。

监督学习、无监督学习的定义:
工程化定义:上面的经验数据是否有任务对应的标记信息,有标记信息的是监督学习、没有是无监督学习。
人话就是:就是上面的数据,是有否任务对应的正确答案,例如一个与世隔绝的人在你面前,他一点都没见过这个世界,你想训练他适应社会,你想让他把你班同学分男、女两类。如果你和他说哪些是男同学哪些是女同学就是监督学习;如果没有和他说,让他凭自己的看到的感觉来分,那就是无监督学习。

泛化能力,过拟合,欠拟合:
工程化定义:学得模型适用于新样本的能力,成为“泛化”能力。如果学得的能力在训练集的效果很好,测试集很差,是过拟合。如果学到的能力连在训练集的效果都很差的,是欠拟合
人话就是:接上面的例子,就是那个人学习完你和他说的男女分类任务之后,分辨不是你班同学的其他人的性别的能力,如果发现他分辨出你班同学的性别的能力很好,但是分辨其他人性别的能力,那就是过拟合;如果发现连你们同学性别都分辨不出来,那就是欠拟合

偏差:所有可能的训练数据集训练出的所有模型的输出的平均值与真实模型的输出值之间的差异,即刻画了学习算法本身的拟合能力;
方差:不同的训练数据集训练出的模型输出值之间的差异,即刻画了数据扰动所造成的影响。

偏差、方差与过拟合、欠拟合的关系:
欠拟合:模型不能适配训练样本,有一个很大的偏差。
过拟合:模型很好的适配训练样本,但在测试集上表现很糟,有一个很大的方差。

过拟合的解决方法:增加数据;简化模型(选择更加简单的算法、减少使用的参数或特征数量、对模型正则化);减少训练数据中的噪声。也就是减少方差
欠拟合的解决方法:寻找更好的具有代表性的特征;使用更多的的特征。也就是减少偏差。

在机器学习里,通常我们不能将所有的训练数据放到模型里面,否则我将没有多余的数据来评估这个模型的好坏。
有几种解决方法:

  • 设置验证集,这是最常见的做法。就是把模型分成训练集和测试集,一般按照7:3来划分。我们用训练集来训练,用测试集来评估模型。
    可是存在两个弊端,
    1.最终模型与参数的选取将极大程度依赖于你对训练集和测试集的划分方法。为啥,我们可以看这一张图:
    在这里插入图片描述
    右边是十种不同的训练集和测试集划分方法得到的test MSE曲线,可以看到在不同的划分方法下,test MSE的变动是很大的,而且对应的最有degree也不一样。所以如果我们的训练集和测试集的划分方法不够好,很有可能无法选择到最好的模型与参数。
    2.只用了部分数据进行模型的训练,无法充分利用数据。

所以提出了交叉验证
其中有一个K-fold Cross Validation,就是用多个数据作为测试集,其他的数据都作为训练集,具体的数目由K来决定。比如,如果K=5,那么我们利用五折交叉验证步骤就是:

  1. 将所有数据集分成五分
  2. 2.不重复地每次取一份做测试集,用其他四份做训练集来训练模型,之后计算该模型在测试集上MSEiMSE_i
  3. 将5次的MSEiMSE_i取平均值得到最后的MSE
    通过交叉验证技术,可以不需要单独的验证集实现模型比较(用于模型选择和调整超参数),节省宝贵的训练数据。

二.线性回归的原理

按照维基百科的定义:
线性回归是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。这种函数是一个或多个称为回归系数的模型参数的线性组合。只有一个自变量的情况成为简单回归,大于一个自变量情况的叫做多元回归。

三.线性回归损失函数、代价函数、目标函数

损失函数公式:
L(θ)=yif(xi)L(\theta) = |y_i - f(x_i)|一般针对单个样本 i
线性回归的损失函数:
(wi,bi)=argmin(yiwxib)2(w^*_i, b^*_i) = argmin(y_i - wx_i - b)^2

代价函数公式:L(θ)=1/Ni=1Nyif(xi)L(\theta)=1/N *\sum_{i=1}^N|y_i - f(x_i)|一般针对总体
线性回归的代价函数:(w,b)=argmin(1/(2N)i=1N(yiwxib))(w^*, b^*) = argmin(1/(2*N) *\sum_{i=1}^N(y_i - wx_i -b))

目标函数公式:L(θ)=1/Ni=1Nyif(xi)+L(\theta)=1/N *\sum_{i=1}^N|y_i - f(x_i)| + 正则化项
线性回归目标函数公式:(w,b)=1/(2N)i=1N(yif(xi))2+λi=1N(θj2)(w^*, b^*) = 1/(2*N) *\sum_{i=1}^N(y_i - f(x_i))^2 + \lambda\sum_{i=1}^N(\theta_j^2)
可能会奇怪正式的式子是绝对值,线性回归会用上平方和常数1/2,为了方便偏微分计算所以进行了优化,而且不影响我们找到模型的最佳w和b。

四优化方法:

1.梯度下降法
目标函数L(θ)L(\theta)关于参数θ\theta的梯度将是目标函数上升最快的方向。对于最小化优化问题,只需要将参数沿着梯度相反的方向迈一步,就可以实现目标函数的下降,其中有一个学习率α\alpha,他决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大。
公式:
θ=θα1NθL(θ)\theta = \theta - \alpha \frac{1}{N} \nabla _{\theta}L(\theta)
θL(θ)=df(θ)θ\nabla _{\theta}L(\theta) = \frac{df(\theta)}{\theta}
通过这样不断优化得到最佳的w和b。

2.牛顿法
牛顿法不仅可以用来求解函数的极值问题,还可以用来求解方程的根,二者在本质上是一个问题,因为求解函数极值的思路是寻找导数为0的点。
和梯度下降法一样,牛顿法也是寻找导数为0的点,同样是一种迭代法,核心思想是在某点处用二次函数来近似目标函数,得到导数为0的方程,求解该方程,从而得到下一个迭代的点,通过这样反复迭代,直到达到导数为0的点处(因为是用二次函数近似,因此可能会有误差)。
我们先进一元函数的情况,然后推广到多元函数。
一元函数的情况
根据一元函数的泰勒展开公式,我们对目标函数在x0x_0(随机选取或者某种方法确定)点处做泰勒展开,有:
f(x)=f(x0)+f(x0)(xx0)+12f(x0)(xx0)2+...+1n!fn(x0)(xx0)n...f(x) = f(x_0) +f^{\prime}(x_0)(x-x_0) + \frac{1}{2}f^{\prime \prime}(x_0)(x-x_0)^2 +...+\frac{1}{n!}f^{n}(x_0)(x-x_0)^n...
忽略2次以上的项则有:
f(x)=f(x0)+f(x0)(xx0)+12f(x0)(xx0)2f(x) = f(x_0) +f^{\prime}(x_0)(x-x_0) + \frac{1}{2}f^{\prime \prime}(x_0)(x-x_0)^2
然后我们在x0x_0点处,要以它为基础,找到导数为0的点,即导数为0。对上面等式两边同时求导,并令导数为0,可以得到下面的方程:
f(x)=f(x0)+f(x0)(xx0)=0f^{\prime}(x) = f^{\prime}(x_0) +f^{\prime \prime}(x_0)(x-x_0) =0
可以解得:
x=x0f(x0)f(x0)x = x_0 - \frac{f^{\prime}(x_0) }{f^{\prime \prime}(x_0) }
这样我们就得到了下一点的位置,从而走到x1x_1.。接下来重复这个过程,直到到达导数为0的点,由此得到牛顿法的迭代公式:
xt+1=xtf(xt)f(xt)x_{t+1} = x_t - \frac{f^{\prime}(x_t) }{f^{\prime \prime}(x_t) }
总结:初始迭代点x0x_0,反复用上面的公式进行迭代,直到达到导数为0的点或者达到最佳迭代次数。

二元函数的情况
下面的讲解需要对Hessian的概念有着先验的了解。
根据多元函数的泰勒展开公式,我们对目标函数在x0x_0点处做泰勒展开,有:
f(x)=f(x0)+f(x0)T(xx0)+12(xx0)T2f(x0)(xx0)+ο((xx0)2)f(x) = f(x_0) + \nabla f(x_0)^T(x-x_0) + \frac{1}{2}(x-x_0)^T \nabla ^2f(x_0)(x - x_0) + \omicron((x-x_0)^2)
忽略二次及以上的项,并对上式两边同时求梯度,得到函数的导数(梯度向量)为:
(x)=f(x0)+2f(x0)(xx0)\nabla (x) = \nabla f(x_0) + \nabla ^2f(x_0)(x-x_0)
其中2f(x0)\nabla ^2f(x_0)即为Hessian矩阵,在后面我们写成H。令函数梯度为0,则有:
f(x0)+2f(x0)(xx0)=0x=x0(2f(x0))1f(x0)\nabla f(x_0) + \nabla ^2f(x_0)(x-x_0) = 0 \Longrightarrow x=x_0-(\nabla ^2 f(x_0))^{-1}\nabla f(x_0)
这是一个线性方程组的解。如果将梯度向量简写为g,上面的公式可以简写为:
x=x0H1gx = x_0-H^{-1}g
从初始点x0x_0开始,反复计算函数在x0x_0处的Hessian矩阵和梯度向量,然后用下述公式进行迭代:
xk+1=xkHk1gkx_{k+1} = x_k-H^{-1}_kg_k
最终会到达函数的驻点处。其中H1g-H^{-1}g称为牛顿方向。迭代终止的条件是梯度的模接近于0,然后函数值下降小于指定阈值。

2.拟牛顿法
牛顿法在每次迭代时需要计算出Hessian矩阵,然后求解一个以该矩阵为系数矩阵的线性方程组,这非常耗时,另外Hessian矩阵可能不可逆。为此提出了一些改进的方法,典型的代表是拟牛顿法(Quasi-Newton).
拟牛顿法的思想是不计算目标函数的Hessian矩阵然后求逆矩阵,而是通过其他手段得到Hessian矩阵或其逆矩阵的近似矩阵。具体做法是构造一个近似Hessian矩阵或其逆矩阵的正定对称矩阵,用该矩阵进行牛顿法的迭代。将函数在xk+1x_{k+1}点出进行泰勒展开,忽略二次以上的项,有:
f(x) f(xk+1)+f(xk+1)T(xxk+1)+12(xxk+1)T2f(xk+1)(xxk+1)f(x) \approx\ f(x_{k+1})+\nabla f(x_{k+1})^{T}(x-x_{k+1}) +\frac{1}{2}(x-x_{k+1})^T \nabla ^2f(x_{k+1})(x-x_{k+1})
对上式两边同时去梯度,有:
f(x) f(xk+1)+2f(xk+1)(xxk+1)\nabla f(x) \approx\ \nabla f(x_{k+1})+\nabla ^2f(x_{k+1})(x-x_{k+1})
X=XkX = X_k,有:
f(xk+1)f(xk) 2f(xk+1)(xk+1xk)\nabla f(x_{k+1}) - \nabla f(x_{k}) \approx\ \nabla ^2f(x_{k+1})(x_{k+1}-x_{k})
这可以简写为:
gk+1gk Hk+1(xk+1xk)g_{k+1} - g_{k} \approx\ H_{k+1}(x_{k+1} - x_{k})
如果令:
sk=xk+1xks_k = x_{k+1} - x_{k}
yk=gk+1gky_k = g_{k+1} - g_{k}
上式可以简写为:
yk=Hk+1sky_k = H_{k+1}s_k
即:
sk Hk+11yks_k \approx\ H^{-1}_{k+1} y_{k}
根据此条件,构造出了多种拟牛顿法,典型的有DFP算法、BFGS算法、L-BFGS算法等,在这里我们重点介绍BFGS算法。下图列出了常用的拟牛顿法的迭代公式:
在这里插入图片描述
BFGS算法是它的四个发明人Broyden,Fletcher,Goldfarb和Shanno名字首字母的简写。算法的思想是构造Hessian矩阵的近似矩阵:
Bk HkB_k \approx\ H_k
并迭代更新这个矩阵:
Bk+1=Bk+ΔBkB_{k+1} = B_{k} + \Delta B_k
该矩阵的初始值B0B_0为单位阵l。这样,要解决的问题就是每次的修正矩阵ΔBk\Delta B_k的构造。其计算公式为:
ΔBk=αuuT+βvvT\Delta B_{k} = \alpha uu^T+ \beta vv^{T}
其中:
u=yku = y_k
v=Bkskv = B_k s_k
α=1ykTsk\alpha = \frac{1}{y_k^T s_k}
β=1skTBksk\beta = - \frac{1}{s_k^T B_k s_k}
因此有
ΔBk=ykykTykTskBkskskTBkskTBksk\Delta B_k = \frac{y_k y_k^T}{y_k^T s_k} - \frac{B_ks_ks_k^TB_k}{s^T_kB_ks_k}
因此算的的完整流程为:
1.给定的优化变量的初始值x0x_0和精度阈值ε\varepsilon,令B0=I,K=0B_0 = I, K=0
2.确定搜索方向dk=Bk1gkd_k = -B_k^{-1}g_k
3.搜索得到步长λk\lambda _k,令Sk=λkdk,Xk+1=Xk+SkS_k = \lambda _kd_k, X_{k+1} = X_{k} + S_k
4.如果gk+1<ε||g_{k+1}|| < \varepsilon,则迭代结束
5.计算Yk=gk+1gkY_k = g_{k+1} - g_{k}
6.计算Bk+1=Bk+YkykTYkYSkBkSkSkTBkSkTBkxSkB_{k+1} = B_{k} + \frac{Y_ky_k^T}{Y_k^YS_k}-\frac{B_kS_kS_k^TB_k}{S_k^TB_kxS_k}
7.令K=K+1,返回步骤2
每一步迭代需要计算nxn的矩阵DkD_k,当n很大时,存储改矩阵非常损耗内存。为此提出了改进方法L-BFGS,其思想是不存完整的矩阵DkD_k,只存储向量SkS_kYkY_k

五 线性回归的评估指标:

对模型的泛化性能进行评估,不仅需要有效可行的实验估计方法,还需要衡量模型泛化能力的评价标准,这就是评估指标。我们需要根据任务的需求来确定评价标准。
在预测任务中,给定样例集D={(x1,y1),(x2,y2),...,(xm,ym)(x_1,y_1),(x_2,y_2),...,(x_m,y_m)},其中yiy_i是示例xix_i的真实标记。要评估模型f的性能,就要把学习期预测结果f(x)与真实标记y进行比较。
回归任务最常用的性能度量是“均方误差”(mean squared error)
E(f;D)=1mi=1n(f(xi)yi)2E(f;D) = \frac{1}{m}\sum_{i=1}^n (f(x_i)-y_i)^2
更一般的,对于数据分布D和概率密度函数p( )p(\cdot\ ),均方误差课描述为:
E(f;D)=xD(f(x)y)2p(x)dxE(f;D) = \quad \int_{x \in D} (f(x)-y)^2p(x)dx
线性回归基本用上面的评估指标

六 sklearn参数详解:

一般我们通过这个方法来调度
sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=None)
参数解析:
fit_intercept:boolean,optional,default True
是否计算此模型的截距。如果设置为False,则不会在计算中使用截距(例如,预计数据已经居中)。
normalize : boolean, optional, default False
当fit_intercept设置为False时,将忽略此参数。如果为True,则回归量X将在回归之前通过减去平均值并除以l2范数来归一化。如果您希望标准化,请在使用normalize = False的估算器调用fit之前使用sklearn.preprocessing.StandardScaler。
copy_X : boolean, optional, default True
如果为True,则将复制X;否则,它可能会被覆盖。
n_jobs : int or None, optional (default=None)
用于计算的内核数。这只会为n_targets> 1和足够大的问题提供加速。除非在joblib.parallel_backend上下文中,否则表示1。 -1表示使用所有处理器。有关详细信息,请参阅词汇表。(这个是谷歌翻译,具体的意思个人认为是选择计算机的几核来加速)

属性:
coef_ : array, shape (n_features, ) or (n_targets, n_features)
线性回归问题的估计系数。如果在拟合(y 2D)期间传递多个目标,则这是二维数组的维度(n_targets,n_features),而如果仅传递一个目标,则这是长度n_features的一维数组。

方法:
fit(X, y[, sample_weight]) 拟合线性模型.
get_params([deep]) 为估算其器获得参数.
predict(X) 使用线性模型预测
score(X, y[, sample_weight]) 返回预测的确定系数R2R^2
set_params(**params) 设置估算器的参数。
参数:
X : 数组或稀疏矩阵,维度(n_samples,n_features);训练的时候是训练数据,预测的时候是预测数据
y:数组,维度(n_samples,n_targets) 标签值。如有必要,将被转换为X的dtype
sample_weight:numpy数组维度[n_samples] 每个样品的单独权重。
deep :boolean, optional 如果为True,将返回此估计器的参数幷包含作为估算器的子对象

参考文献:
https://zhuanlan.zhihu.com/p/24825503
https://zhuanlan.zhihu.com/p/38853908
《机器学习》(西瓜书)
《Hands-on Machine Learning with Scikit-Learn & Tensorflow》
2014年吴恩达机器学习课程
https://blog.csdn.net/u013709270/article/details/78667531
https://zhuanlan.zhihu.com/p/37588590
https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章