拓冰建站拓冰建站
首页 / 资讯中心 / 正文

线性回归全解析:从最小二乘到梯度下降与正则化

线性回归是很多人在模式识别与机器学习课程里遇到的第一个真正意义上的“模型”。别看它形式简单就是一条直线 (y wx b) 或者一个平面 (y w^T x)但如果你真的把线性回归吃透了后面几乎所有的模型——逻辑回归、SVM、神经网络——本质上都是在它的骨架上换损失函数、换结构、换优化策略。这也是为什么几乎所有《机器学习》教材周志华老师的西瓜书、吴恩达的课程都把它放在最开始讲。这篇文章我打算完全围绕“线性回归”这个主题把从模型假设、目标函数、闭式解推导、梯度下降到正则化和模型评估的完整链路梳理一遍。内容会尽量贴近我在实际写代码、做实验、以及复习备考时的一些经验和理解适合正在学《模式识别与机器学习》的本科生、准备西电/国科大等学校机器学习期末考试的同学以及刚入门机器学习、想搞清楚线性回归底层逻辑的自学者。看完你应该能回答这几个问题线性回归到底在优化什么正规方程和梯度下降分别适合什么场景L1和L2正则化到底该加哪个、什么时候加1. 先把“回归”这件事想清楚1.1 回归到底在解决什么问题在模式识别和机器学习里任务大致分两类分类和回归。分类的输出是离散的类别标签比如判断一封邮件是垃圾邮件还是正常邮件判断一部电影属于喜剧、动作还是科幻回归的输出是连续的实数值比如预测房价、预测气温、预测销售额。这里有个特别经典的例子在很多课程作业和考试题里都出现过我们已经有了一些电影的数据和分类比如根据电影的票房、评分、时长等特征去预测某部电影的评分这就是回归任务而电影《唐人街探案》的分类是未知如果我们要判断它属于哪种类型的影片那就是分类任务。很多同学在做这种题目时会混淆其实关键就看输出是连续的还是离散的。回归问题的核心是给定一组特征 (x)我们希望学习一个函数 (f(x))使得 (f(x)) 能够尽可能准确地预测真实的目标值 (y)。而线性回归就是对这个函数加了一个“线性”约束——(f(x)) 必须是特征的线性组合。1.2 线性假设模型的形式与含义线性回归的模型形式非常简洁[ y w_1 x_1 w_2 x_2 \cdots w_d x_d b ]如果写成向量形式就是[ y w^T x b ]其中 (w (w_1, w_2, ..., w_d)^T) 是权重向量(b) 是偏置项。为了方便推导通常把 (b) 吸收进 (w) 里即在特征向量 (x) 前面补一个常数1这样模型就变成[ y w^T x ]这里 (x) 的维度是 (d1)第一维固定为1。这个小技巧几乎在所有教材里都会用好处是后续推导正规方程时不需要单独处理偏置项写代码的时候也多注意一下直接统一成矩阵运算。为什么要做“线性假设”因为线性模型足够简单可解释性强。你能一眼看出每个特征对结果的影响方向和大小——(w_i) 为正说明特征 (x_i) 越大输出越大(w_i) 为负则相反。这在很多需要向业务方解释模型的场景里非常重要。而且线性模型的计算复杂度低即使数据量很大也能高效训练。但线性假设也有明显的局限如果数据本身的规律不是线性的线性回归的拟合效果就会很差。这时候有两条路一是做特征工程比如添加多项式特征多项式回归本质上是特征变换后的线性回归二是换更复杂的模型比如决策树或神经网络。但无论如何理解线性回归都是第一步。2. 损失函数与“为什么是最小二乘”2.1 从误差到平方误差模型定好了接下来要解决的核心问题是怎么衡量“预测得准不准”我们有一堆训练样本 ((x^{(i)}, y^{(i)}))模型对第 (i) 个样本的预测值是 (w^T x^{(i)})真实值是 (y^{(i)})。一个直观的想法是算误差 (y^{(i)} - w^T x^{(i)})把所有样本的误差加起来作为总损失。但直接求和有个问题正负误差会互相抵消。比如一个样本预测高了10另一个样本预测低了10误差之和是0但模型的预测其实并不准。解决办法有几个取绝对值即L1损失或者取平方即L2损失。线性回归经典的方案是平方误差目标函数写成[ J(w) \frac{1}{2} \sum_{i1}^{m} (y^{(i)} - w^T x^{(i)})^2 ]前面乘一个 (\frac{1}{2}) 纯粹是数学上的便利求导的时候平方项的2会被约掉。唯一的区别是平方误差对大的误差给予更大的惩罚误差为2时损失是4误差为4时损失是16这种非线性放大使得模型更倾向于避免出现大的偏差。2.2 从概率视角看最小二乘很多同学学到这里会问为什么偏偏用平方误差而不是四次方或者别的什么形式这背后其实有概率论的解释。假设真实的目标值 (y) 和特征 (x) 之间存在线性关系但观测过程中存在噪声 (\epsilon)[ y w^T x \epsilon ]再假设噪声 (\epsilon) 服从均值为0、方差为 (\sigma^2) 的高斯分布正态分布。那么给定 (x) 时 (y) 的条件概率就是[ p(y|x; w) \frac{1}{\sqrt{2\pi}\sigma} \exp\left(-\frac{(y - w^T x)^2}{2\sigma^2}\right) ]对于一组独立同分布的样本我们可以写出似然函数 (L(w) \prod_{i1}^{m} p(y^{(i)}|x^{(i)}; w))。取对数后最大化似然等价于最小化[ \sum_{i1}^{m} (y^{(i)} - w^T x^{(i)})^2 ]也就是说在“噪声服从高斯分布”的假设下最小化平方误差就是最大似然估计。这就是最小二乘法的概率依据。反过来想如果噪声服从拉普拉斯分布那么最大似然估计得到的就会是L1损失。这也引出了后面要讲的正则化的另一个角度L2损失对应高斯先验L1损失对应拉普拉斯先验。注意这里的高斯噪声假设不仅仅是数学上的技巧它其实说明了最小二乘的适用边界——当误差中存在大量离群点时最小二乘会因为这些极端值的存在而严重偏离因为平方项把大误差放大了。遇到这种情况要考虑用更鲁棒的损失函数比如Huber损失或者在数据预处理时做异常值剔除。3. 求解方式一闭式解与正规方程3.1 正规方程的推导过程对于线性回归的平方损失有一个非常优雅的性质它的最优解可以直接用矩阵运算求出来不需要迭代。这就是我们常说的正规方程Normal Equation。把所有训练样本按行堆叠成一个矩阵 (X)形状为 (m \times (d1))所有标签组成向量 (y)长度为 (m)。目标函数写成矩阵形式[ J(w) \frac{1}{2} (Xw - y)^T (Xw - y) ]对 (w) 求梯度[ \nabla_w J(w) X^T (Xw - y) ]令梯度为0得到[ X^T X w X^T y ]如果 (X^T X) 可逆则[ w (X^T X)^{-1} X^T y ]这就是正规方程的闭式解。整个过程就是解一个线性方程组一步到位不需要调节任何超参数比如学习率、迭代次数这是它最大的优势。我记得当年课上推导到这里的时候老师特别强调过这个解的形式非常干净它告诉我们在平方损失下线性回归的参数有唯一最优解。这一点和后面神经网络这种非凸优化问题形成鲜明对比——线性回归的损失函数是凸函数没有局部最优的困扰随便从哪儿开始优化都能收敛到全局最优。3.2 计算复杂度与不可逆问题虽然正规方程很完美但它在实际应用中会遇到两个问题。第一个问题是计算复杂度。需要计算 (X^T X)复杂度约 (O(md^2))然后求逆复杂度约 (O(d^3))。当特征维度 (d) 很大时比如 (d 10000)求逆运算会非常慢。而在很多实际问题中特征维度可能高达百万级比如文本数据经过独热编码后这时候正规方程就完全不现实了。第二个问题是 (X^T X) 可能不可逆。什么情况下会不可逆最常见的是特征之间存在多重共线性即某个特征可以用其他特征的线性组合表示。比如房价预测中同时使用了“房屋总面积”和“房屋总面积×楼层数”再除以“楼层数”这种冗余特征。另一个情况是样本数少于特征数(m d)这时候 (X^T X) 是奇异矩阵没有逆矩阵。遇到不可逆怎么办有几个思路一是用伪逆 (X^) 代替逆矩阵Python里numpy.linalg.pinv可以直接算二是做特征筛选或降维去掉冗余特征三是加正则化项。以岭回归Ridge Regression为例目标函数变成[ J(w) \frac{1}{2} \sum_{i1}^{m} (y^{(i)} - w^T x^{(i)})^2 \lambda |w|_2^2 ]对应的闭式解变成[ w (X^T X \lambda I)^{-1} X^T y ]由于 (\lambda I) 的加入即使 (X^T X) 是奇异的加上 (\lambda I) 之后通常也会变得可逆。这就是正则化的一个非常实际的作用保证解的存在性和稳定性。4. 求解方式二梯度下降4.1 批量、随机、小批量怎么选正规方程虽然优雅但在特征维度高、样本量大的场景下不实用。这时候就要用迭代方法梯度下降。核心思想非常直观——沿着损失函数下降最快的方向负梯度方向更新参数直到收敛。参数更新规则是[ w : w - \alpha \nabla_w J(w) ]其中 (\alpha) 是学习率。对于线性回归梯度就是[ \nabla_w J(w) X^T (Xw - y) ]梯度下降有三种常见变体它们的区别在于每次更新用多少样本计算梯度批量梯度下降Batch Gradient Descent每次更新都使用全部训练样本计算梯度。优点是方向准确、收敛稳定缺点是样本量巨大时每一步计算都非常慢。随机梯度下降Stochastic Gradient Descent, SGD每次只随机挑一个样本计算梯度并更新参数。优点是计算极快而且由于引入了随机性有机会跳出局部最优虽然线性回归没有局部最优问题缺点在于梯度噪声大收敛过程会来回震荡不容易精确收敛到最优点。小批量梯度下降Mini-batch Gradient Descent每次用一个小的样本子集比如32、64、128个样本计算梯度。这是实践中用得最多的方式兼顾了计算效率和收敛稳定性。可以说深度学习里的训练几乎都是小批量梯度下降或它的改进版如Adam在发挥作用。如果是在课程作业里做线性回归数据量不大我建议直接用批量梯度下降或者干脆直接用正规方程如果数据量到了几万条以上再考虑小批量梯度下降。毕竟作业和考试的重点是理解原理不是炫技。4.2 学习率、特征缩放与收敛判断梯度下降最让人头疼的超参数就是学习率 (\alpha)。学习率太大会导致参数在最优解附近来回震荡甚至发散学习率太小则收敛极慢可能要迭代上万次才能到最优解。我在调参的时候通常会先试一组经验值0.1、0.03、0.01、0.003、0.001。先看损失曲线的变化趋势。如果损失曲线上下剧烈震荡说明学习率偏大如果损失一直缓慢下降、形状像一条平缓的弧线可以适当加大学习率或者增加迭代次数。另外一个对梯度下降影响极大的操作是特征缩放Feature Scaling。如果说让我在所有线性回归实操技巧里只挑一个最值得强调的那一定是它。当不同特征的取值范围差异悬殊时比如一个特征范围是0到1另一个是10000到100000损失函数的等高线会变成狭长的椭圆梯度下降会沿狭窄方向来回震荡收敛非常慢。最常用的缩放方法是标准化Standardization[ x \frac{x - \mu}{\sigma} ]其中 (\mu) 是特征均值(\sigma) 是特征标准差。经过标准化后所有特征的均值变为0方差变为1。我在做任何线性模型包括岭回归、Lasso之前几乎都会先做这一步既加速收敛也让权重之间有了可比性。关于收敛判断两个常用策略设定固定迭代次数比如1000次跑完后观察损失曲线是否已经进入平台期。设定阈值当损失下降量小于某个值比如 (10^{-5})时停止。注意在使用梯度下降时要同时对特征做缩放、记录损失曲线、尝试多个学习率。这三个动作缺一个调试体验都会很痛苦。另外程序的随机数种子要固定否则复现结果时每次的结果可能都有微小差异。5. 正则化L1和L2到底什么时候加5.1 过拟合与偏差-方差的权衡正则化是机器学习里绕不开的话题。为什么需要正则化核心原因是防止过拟合。如果你的模型在训练集上表现很好但在新数据上表现很差这就是过拟合。过拟合的本质是模型过于复杂把训练数据里的噪声也当成规律学到了。在线性回归里过拟合通常表现为权重向量的某些分量特别大——因为模型试图用剧烈的曲线去穿过每一个训练点。偏差-方差权衡可以解释这个问题模型越复杂偏差越低拟合训练数据的潜力越大但方差越高对不同训练集的敏感度越高模型越简单方差低但偏差高。正则化就是在这个权衡中寻找平衡点通过限制权重的大小牺牲一点训练集上的表现换取更好的泛化能力。5.2 L2正则化Ridge为什么效果好L2正则化也叫岭回归Ridge Regression目标函数为[ J(w) \frac{1}{2} \sum_{i1}^{m} (y^{(i)} - w^T x^{(i)})^2 \lambda \sum_{j1}^{d} w_j^2 ]其中 (\lambda) 是正则化系数控制惩罚强度。L2惩罚的是权重的平方和它的效果是让所有权重都逐渐向0收缩但不会精确等于0。也就是说L2永远保留所有特征只是让每个特征的贡献度降低。从贝叶斯的角度看L2正则化等价于给权重 (w) 加上一个均值为0的高斯先验。从优化的角度看加入 (\lambda I) 之后即使原始矩阵奇异矩阵也会变得可逆数值稳定性大幅提升。这个特性在特征数量大于样本数量的时候特别有用。5.3 L1 vs L2到底选哪个L1正则化Lasso的目标函数为[ J(w) \frac{1}{2} \sum_{i1}^{m} (y^{(i)} - w^T x^{(i)})^2 \lambda \sum_{j1}^{d} |w_j| ]它与L2最大的区别在于L1会把一部分权重精确压缩到0。也就是说Lasso天然具有特征选择的功能——最终模型只保留少数重要特征其他特征权重为0。这在高维稀疏场景下非常有用。“什么情况加L1和L2损失”这个问题在热搜词里出现频率非常高可见是很多人的困惑。我根据自己的经验总结了几个判断标准如果主要目的是提高预测精度、缓解过拟合特征数量不太多优先用L2。因为L2计算方便可导、解稳定而且不会丢失特征信息。如果特征数量非常大且大部分特征可能是无关的希望得到一个稀疏模型权重大部分为0以方便解释用L1。但要注意L1在0点处不可导求解时通常需要专门的算法如坐标下降。如果既要稀疏又要稳定可以用Elastic Net它是L1和L2的加权组合[ \lambda (\rho |w|_1 (1-\rho) |w|_2^2) ] 这种方式在实际工业场景中也很常见。关于 (\lambda) 的选取通常的做法是交叉验证把训练数据分成若干折逐一尝试不同的 (\lambda)选择验证集误差最小的那个。我个人的习惯是让 (\lambda) 在对数尺度上从 (10^{-4}) 到 (10^2) 均匀取几十个值画出权重随 (\lambda) 变化的曲线岭迹图然后挑选一个 (\lambda)使权重趋于稳定而模型性能没有明显下降。提示在加正则化之前务必先做特征缩放。因为L1和L2惩罚的是权重的大小如果特征量纲不同权重本身就没有可比性正则化会产生偏差。6. 模型评估与典型问题排查6.1 R² 与均方误差怎么读训练完模型之后怎么判断模型好不好线性回归最常用的两个评估指标是MSE和R²。均方误差Mean Squared Error[ MSE \frac{1}{m} \sum_{i1}^{m} (y^{(i)} - \hat{y}^{(i)})^2 ]它的单位是目标变量的平方所以有时不好解读。这时候R²决定系数更直观[ R^2 1 - \frac{\sum_{i1}^{m} (y^{(i)} - \hat{y}^{(i)})^2}{\sum_{i1}^{m} (y^{(i)} - \bar{y})^2} ]R²的最大值是1表示模型完美拟合数据如果没有比“用均值预测”好多少R²会接近0如果模型表现很差R²甚至可能为负。比如预测电影评分时R²如果是0.85说明模型解释了85%的评分方差已经算不错了。但有一点我得提醒R²不是万能的。在线性回归中只要往模型里加特征R²就绝不会下降因为最小二乘总能找到一个新的权重组合至少不比原来的差。所以R²不能完全反映模型的泛化能力更可靠的做法是用在测试集上计算R²或者做交叉验证。6.2 实操中踩过的坑最后分享一些我在实际做题、写代码过程中踩过的坑每个都让人印象深刻。第一个坑忘记加偏置项。很多教材里的模型形式是 (y w^T x)默认 (x) 已经包含了常数1这一维。但实际编程时如果直接用原始特征矩阵算出来的线永远过原点拟合效果会差很多。检查方法很简单训练完后看一下模型在某个特征全为0的样本上的预测值是否合理。第二个坑特征范围差异极大导致梯度下降发散。我一开始做房价预测的时候没做特征缩放用批量梯度下降迭代1000次损失曲线不但没下降反而一路飙升。后来加了标准化几百步就收敛了。第三个坑数据泄漏。特征选择或特征缩放的参数比如均值和标准差如果是在全部数据上计算再划分训练集和测试集的话测试集的信息就泄露到训练过程里了会导致评估结果虚高。正确做法是先划分训练集和测试集然后只在训练集上计算均值和标准差再用同样的参数去变换测试集。第四个坑把回归和分类混淆。看到一个数据集就问任务是“预测还是分类”看它的标签是连续值还是离散值。在模式识别和机器学习的题目里明确任务类型比开会讨论模型重要得多——因为模型选错了后面全白费。第五个坑直接套用sklearn.linear_model.LinearRegression却不知道它在默认情况下使用最小二乘的SVD分解求解而不是梯度下降。这本身没有问题但如果数据里存在缺失值或极端异常值模型会变得非常脆弱。正规方程的闭式解虽然漂亮但它对异常值极其敏感实际使用中最好先做异常值处理。写在最后我到现在还记得第一次手动推导出线性回归正规方程时的感觉原来所谓“学习”一个模型本质上就是求解一个优化问题。线性回归是这条路上最简单也最坚实的一步它的框架可以延续到逻辑回归把输出经过sigmoid函数就会变成分类模型、可以扩展到核方法用核函数做特征变换、也是神经网络中单个神经元的基础结构。如果你正在备考《模式识别与机器学习》或者《机器学习》相关课程我的建议是不要只背公式一定要亲手推一遍正规方程再亲手用Python实现一遍批量梯度下降然后去 sklearn 里跑一遍对比结果。这个过程比刷十道题都有用。踩过那些坑之后你会发现自己对线性回归的理解会有一个质的提升。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门