☰
回归作业深度拆解:线性模型、梯度下降与数据标准化的工程实践
2026/10/15 1:06:38 网站建设 项目流程

1. 作业拆解:Regression到底想让你练什么

1.1 回归任务的第一性原理

回归任务的本质是给定一组特征,预测一个连续数值。分类问题输出离散标签,而回归输出的是有量纲的实数。这个区别听起来简单,但决定了后面所有的评估方式。举一个更直白的例子:分类关心“这张照片里有没有猫”,回归关心“明天某观测站的污染物浓度是多少”。同样是监督学习,一个回答“是什么”,一个回答“是多少”,损失函数和评价指标也由此完全不同。

为了让新手尽快建立直觉,可以想象一个人的体重预测场景:输入身高、年龄、每周运动时长,预测体重。这里的输出是一个连续数值,预测得准不准要用绝对误差来衡量。回归任务与分类任务的核心差别就是输出空间的性质,这个认知会影响后面每一个设计决策。

课程作业通常会给出一张表格数据,特征列包含温度、湿度、风速、气压,以及过去几个小时的浓度记录,目标列是当前小时的浓度。要在这类表格上建立模型,不能只调用现成算法,而要亲自动手准备训练数据、搭建模型、计算误差、更新参数。这门课把回归放在第一课,目的很明确:用最简单的问题,把完整流程走通。

1.2 三个隐藏考点

第一个考点:把数学公式落成矩阵运算。如果只会写 y = w*x + b,然后一个特征一个特征地循环更新,特征数量一旦变大,代码会又慢又容易出错。使用矩阵表达后,一次前向传播就是一两次矩阵乘法,梯度公式也更清晰。这个基本功会在后续更复杂的模型中被反复使用。

第二个考点:只靠训练集调好模型,而不是靠参考答案。作业环境下最常见的做法是反复提交测试集,用测试分数反过来调参数。这样做看似高效,实际上模型会逐步记住测试集上的表现,最终分数虚高。正确做法是划出验证集,只在验证集上尝试超参数,最后用测试集做一次“期末考试”。

第三个考点:理解超参数的作用。学习率太大模型发散,太小收敛慢;迭代次数太多过拟合,太少欠拟合;正则项权重过大把参数压得过于保守。这些概念在后面的课程中会一直出现。作业一的价值就是让你通过一个简单线性模型,把这些坑亲手踩一遍。

2. 方法选型与原理落地:为什么线性模型反而是最佳起点

2.1 线性回归的矩阵表达

回归模型的选择其实很多,但作业第一课通常建议从线性回归开始。核心模型写成 y_hat = X @ w,其中 X 形状为 (N, D),w 是长度为 D 的权重向量,y_hat 是长度为 N 的预测向量。为什么一定要用矩阵表达?因为在训练时,N 条样本要同时参与运算。如果手写循环遍历样本,代码不仅慢,而且梯度公式很容易写错。矩阵乘法把“对样本求和”隐含在运算里,反而更接近数学推导。

构造矩阵时有一个常见的细节:把偏置 b 并进权重向量中。具体做法是给特征矩阵 X 的左侧加一列全1,然后把权重长度增加为 D+1。模型变成 y_hat = X_b @ w_b。好处是更新权重和偏置时不用分开写,一套梯度公式就能处理。

为什么线性模型适合作为起点?第一是解释性强,每个权重直接表示对应特征对目标的影响方向和强度。如果温度特征的权重为正,说明温度升高时预测值也升高,这个结论可以反向检查数据是否合理。第二是优化简单,线性回归配合均方误差损失函数,整体是凸优化问题,梯度下降能保证找到全局最优解,不需要担心像神经网络那样陷入局部最优。

2.2 损失函数为什么选MSE

回归任务需要用一个数值来衡量“预测值和真实值到底差多远”。最常用的是均方误差(MSE):

loss = (1/N) * Σ(y_hat - y)^2

选MSE有几个实际原因。首先,它处处可导,梯度计算方便。其次,平方项会把差距较大的样本放大,让模型在训练时优先修正那些偏差明显的预测。这在实际训练中很有用。如果把损失函数换成平均绝对误差MAE,虽然在异常值很多的数据上更稳健,但它零点不可导,手写梯度下降时要额外处理,对初学者并不友好。

评估时建议同时看RMSE:RMSE = sqrt(MSE),它和原始数据同量纲,方便人理解。比如预测浓度的RMSE为8.5,可以理解为“平均预测偏差大约8.5个单位”。作业报告通常需要同时展示训练集和验证集的RMSE,用来判断模型是不是过拟合。

2.3 梯度下降的三个关键参数

梯度下降是最小化损失的标准迭代方法,更新公式就是 w = w - lr * grad。学习率、迭代次数、批量大小这三个参数是这次作业绕不开的坎。

学习率决定每一步走多大。太高会在最优值附近来回震荡甚至发散,太低会走得非常慢。我建议从0.01起步,观察loss曲线再调整。迭代次数决定看多少轮训练数据。如果次数太少,模型还没有收敛;次数太多且模型容量大,训练误差继续下降的同时,验证误差可能反过来上升。批量大小在入门阶段可以用全量样本,每次迭代都用全部数据算梯度,最直观也最稳定。

这里要特别提一个容易被新手忽略的细节:梯度下降对特征尺度非常敏感。如果一个特征数值在0到1之间,另一个特征在0到100000之间,那么梯度在不同维度上的尺度可能差几十倍,模型会像在狭长山谷里行走一样,来回震荡,收敛极慢。这也是我在第三部分反复强调标准化预处理的原因。

2.4 正则化:作业里加一项L2有什么用

过拟合是回归作业里最典型的问题,解决它的常用手段是正则化。L2正则化在损失函数中加入惩罚项 λ * Σ(w^2),梯度更新时相当于把权重往零的方向拉一点,从而限制单个特征对结果影响过大。

作业阶段不是非加不可,但如果发现训练集RMSE很低、验证集RMSE很高,第一反应应该就是打开L2正则项。λ取值范围可以先试0.001、0.01、0.1,看验证集变化。

给一个形象解释:正则化就像作文规定字数上限,多余一个字都要扣分。写手不得不删掉冗余修饰,模型也被迫放弃那些对泛化不友好的极端权重。注意一个实现细节:严格来说偏置 b 不应该参与正则化惩罚,但用统一矩阵计算梯度时,如果不小心会把偏置维度也一起惩罚。比较严谨的做法是把权重分成 b 和其余部分,只对后者添加惩罚项。

3. 完整实操:从数据清洗到模型训练

3.1 数据预处理与划分

任何回归项目的第一步都不是训练模型,而是理解数据。我这次使用了一份模拟的某区域空气观测数据,约5000条小时级记录。字段包括温度、湿度、风速、气压,以及过去1到6小时的污染物浓度,目标列是当前小时的污染物浓度。拿到数据之后,先统计每一列的缺失值数量,再检查取值范围是否有异常。

最后发现两类问题。第一类是缺失值,某个传感器在部分时段没有回传,对应位置是NaN;第二类是异常值,有一行湿度显示为117%,明显超过物理范围。对于缺失值,我的处理方式是用训练集中该列的均值填充;对于异常值,直接删除整条记录。

这里有一个非常容易做错的环节:要先划分训练集和验证集,再对训练集计算填充值和标准化参数。如果在全量数据上计算均值,然后填充,验证集的信息就已经在训练阶段被模型“偷看”到了。对于时序类数据,划分方式更不能随机打散。时间前后有关联,随机划分会把未来信息混进过去。我的方案是按时间顺序取前80%做训练集,后20%按顺序做验证集。

3.2 特征工程与标准化

特征工程决定了模型效果的上限。在原始气象特征之外,我能做的第一件有效操作是增加“延后特征”:把过去1到6小时的浓度作为当前预测的特征。这组特征特别有用,因为当前浓度与上一小时的浓度有很强的时间相关性。加入后验证集RMSE立刻下降了约一成。

接着又尝试了交互项和多项式特征。温度与风速的乘积、温度的平方项,都能让线性模型捕捉到一部分非线性变化。但特征不是越多越好,特征太多而数据量有限时,模型容易记住训练集噪声。判断标准是看验证集RMSE:如果新特征让验证集误差下降,说明有效;如果误差不变甚至上升,说明新特征反而带来了干扰。

标准化是这里最不能省略的一步。用训练集每个特征的均值和标准差做Z-score变换,让所有特征都落在零均值单位方差的尺度上。标准化的公式是 x' = (x - mean) / std,经过变换后所有特征的均值接近0、标准差接近1,梯度下降的等高线从狭长山谷变成近似圆形,每一步更新都能朝更合理的方向前进。我第一次没做标准化,loss卡在高位慢慢下降;标准化之后,同样500轮迭代,前100轮就明显收敛。注意,mean和std只能用训练集计算,再应用到验证集和测试集,这是整个流程里最容易被忽略但也最重要的数据边界。

3.3 训练循环与效果评估

训练循环的代码不长,核心就是前向传播、计算误差、求梯度、更新参数四步。我给出一个可以直接参考的NumPy实现:

import numpy as np def train_linear_regression(X_train, y_train, X_val, y_val, lr=0.01, epochs=500): N, D = X_train.shape X_train_b = np.hstack([np.ones((N, 1)), X_train]) N_val = X_val.shape[0] X_val_b = np.hstack([np.ones((N_val, 1)), X_val]) w = np.zeros(D + 1) for epoch in range(epochs): y_pred = X_train_b @ w error = y_pred - y_train loss = np.mean(error ** 2) grad = (2 / N) * X_train_b.T @ error w -= lr * grad if epoch % 50 == 0: val_pred = X_val_b @ w val_loss = np.mean((val_pred - y_val) ** 2) print(f"epoch {epoch}, train_loss {loss:.4f}, val_loss {val_loss:.4f}") return w

代码中,X_train_b 在最前面加了一列全1,对应权重向量的第一维就是偏置。train_loss 和 val_loss 同时被打印,这样可以一边训练一边观察是否过拟合。我实际跑完500轮后,训练RMSE约8.5,验证RMSE约8.7,差距不大,说明模型没有明显过拟合。

如果对比不同学习率,差异非常直观:

学习率训练RMSE验证RMSE现象
0.1NaNNaNloss爆炸
0.018.58.7正常收敛
0.0019.810.6收敛变慢
0.000110.211.8迭代不足

具体数值在不同数据集中不会一致,但规律是稳定的:学习率过大直接发散,学习率过小会让收敛速度明显变慢。建议从0.01起步,观察前几轮loss的变化趋势再决定加还是减。

3.4 加上L2正则项后的对比

加入L2正则化可以改善过拟合。实现上是把损失函数变成 loss + λ * Σ(w^2),梯度更新时对权重额外加一个 2 * λ * w 项。为了避免偏置被误惩罚,我把权重拆成第一维和其他维度,只对其他维度添加惩罚。我在同样的特征组合上跑了三种λ:

正则强度λ训练RMSE验证RMSE
08.58.7
0.0018.88.6
0.019.49.1

λ=0.001时,验证集RMSE从8.7降到8.6,训练集RMSE略有上升,这是正则化起作用的预期信号。λ增大到0.01后,验证集也跟着变差,说明惩罚过强,模型变得过于保守。所以正则项强度需要调,不是越大越好。

4. 踩坑记录与问题排查

4.1 loss不降反升:学习率过大的现场

第一次手写梯度下降时,我把学习率设为0.1,结果没跑几轮,loss直接变成NaN。损失函数不降反升,最常见的原因就是学习率太大:每一步都跨过了山谷最低点,甚至跳到更远更高的位置,最终发散。这就像下坡时步子迈得太大,直接越过谷底冲上对面山坡。

排查方法是先看loss的打印顺序。如果前几步还在下降,突然跳成NaN,大概率是学习率过大;如果一开始就是NaN,那要先检查数据里有没有NaN或inf。我的处理是把0.1调低到0.02,发现loss开始正常,但后期仍有小幅震荡;继续调到0.01,震荡消失。如果想收敛更稳,可以在迭代过程中使用学习率衰减,比如每200轮乘以0.5,前期大步探索,后期小步收敛。

4.2 特征标准化晚一步,梯度下降卡死

另一个让我印象很深的问题是特征标准化没有做,或者做晚了。我最早一版代码只做了缺失值清理,没有标准化就直接训练,结果500轮之后loss还在高位慢慢蠕动。原因是不同特征的数值范围差别太大,梯度下降在参数空间里来回锯,很难直线走到山谷底。

标准化之后,同样500轮,前100轮就能看到loss明显下降。这里有一个顺序问题需要特别注意:先切分数据集,再只用训练集计算每个特征的均值和标准差。如果先对整个数据集标准化再切分,验证集的统计信息会流入训练流程,最后得到的验证分数就不真实。这个细节写不进公式,但直接决定了作业结果的可信度。

4.3 常见问题速查表

把这次作业里遇到的典型问题整理成速查表:

症状可能原因排查与对策
loss变成NaN学习率过大或数据含无穷值调低学习率,检查数据是否含NaN/inf
loss降得很慢特征未标准化或学习率过小做Z-score标准化,适当加大学习率
训练RMSE低但验证RMSE高过拟合加L2正则、增加数据、减少高次特征
训练和验证RMSE都高欠拟合增加有效特征、加迭代轮数、增大模型容量
预测结果接近常数特征与目标相关性弱重新检查特征选择,观察目标分布
每次运行结果不同数据划分有随机性固定随机种子,或按时间固定切分

4.4 一个容易被忽视的细节:把验证集当测试集用

作业里最容易翻车的不是模型结构,而是评估流程。有人为了追求更好的分数,反复提交测试集,根据测试分数修改参数。表面上看分数一路攀升,实际模型已经在测试集上“作弊”,最终成绩失真。这个行为可以看作数据泄露的一种变体,在真实项目里更是大忌。

正确的做法是先固定训练集和验证集,在验证集上尝试不同的学习率、迭代次数、正则强度,选择验证集结果最好的方案。确认参数之后,才用测试集跑一次,记录最终分数。如果中途改过任何超参数,之前那次测试分数就不能算数。

这次作业做下来,我的整体体会是:Regression看着简单,真正难的是理解训练集、验证集、测试集三者之间的边界。很多人卡住,不是公式看不懂,而是不知道在哪个环节悄悄泄漏了信息。手写一遍梯度下降,把每一步中间结果打印出来看看,会比读十遍讲义更有帮助。如果现在正在做类似的回归作业,建议先花半小时把数据划分和标准化环节理顺,再开始写模型,后面会少踩很多坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询