李哥深度学习第三节 回归实战
先聊个有意思的事。我见过太多人学深度学习,前两节课还兴致勃勃,一到回归实战就开始“犯迷糊”。原因不复杂:大家在各种教程里看到的例子大多是图像分类,猫猫狗狗、手写数字,所以脑子里默认深度学习就是“把东西分个类”。但真到了工业界、到了业务项目里,你遇到的第一类刚需问题往往不是分类,而是“预测一个数”。库存备多少?产品良率大概是多少?设备的剩余寿命还能撑多久?传感器读数对应的物理量是多少?这些都是回归问题。
这一节,李哥带你把回归实战这条路彻底走通。从“回归在解决什么问题”这个底层认知讲起,到数据怎么准备、网络骨架怎么搭、损失函数和评估指标怎么选、训练怎么调参,再到踩坑记录和工具选型,一套流程走完,你就能独立把一个回归任务从零跑到出结果。听完这节课,你回头看那些只会跑分类demo的教程,会发现它们确实只教了半截功夫。
1. 回归不是“预测房价”这么简单——先建立正确的任务认知
1.1 回归问题最本质的定义:输出是连续值
回归问题的定义听起来特别简单:输入一组特征,输出一个连续数值。但请注意,这个连续数值背后涉及的数学假设,决定了你的模型设计思路。分类任务的输出是离散的标签,比如“猫、狗、猪”,没有大小关系;回归任务的输出是一个实数区间里取值,比如价格、温度、浓度、寿命,相邻两个值之间的差距具有实际意义。
“连续值”这三个字意味着什么?意味着Loss函数要考虑“预测错了多少”,而不只是“预测对了没有”。你预测房价差了5万和差了50万,完全是两个量级的错误,模型必须能感知这种差距。这直接决定了输出层的结构:回归模型最后一层通常是一个神经元、没有激活函数(linear activation),输出范围是整个实数域;分类模型最后一层是Softmax,输出范围是0到1的概率分布。
有些初学者会把逻辑回归(Logistic Regression)当成回归算法,这是特别常见的误解。逻辑回归名字里带“回归”,但它的输出经过Sigmoid映射到(0,1)区间,本质是二分类,不是回归。真正做回归任务时,线性回归、支持向量回归(SVR)、随机森林回归、XGBoost回归这些经典方法,和深度学习回归模型是两条路线,后面我会专门讲它们之间怎么选型。
1.2 回归任务的“真实地图”:从你身边的数据到专有领域
光说定义还是太虚。我们直接把回归任务按数据形态和业务场景拆开来看,你会发现它无处不在,深度学习回归的核心优势也就藏在这些场景里。
- 表格型数据回归:传感器标定、工艺参数预测、金融风控里的违约损失率估计、电商销量预测。这种任务的特征通常是几十到几百个离散字段,结构化程度高。
- 图像型数据回归:从缺陷图片预测缺陷长度(工业质检)、从生物医学影像测量器官尺寸、从卫星遥感影像估算地表参数。图像本身是像素矩阵,回归目标往往是物理量。
- 时序型数据回归:设备剩余寿命预测、能源负载预测、股票波动率估计。输入是连续采样的时间序列,输出可以直接是下一秒的数值,也可以是未来一段窗口的数值序列。
- 文本/多模态回归:从评论预测评分、从产品描述预测受众年龄段。这类任务样本稀少时难度极高,但大模型时代已经逐步成熟。
你在实战里遇到的回归任务,基本跑不出这张地图。深度学习回归和经典回归的边界也在这里拉开了:表格数据上数据量不大时,XGBoost往往是性价比之王;但图像、时序、多模态这种特征高度复杂的数据,深度学习模型就是更合理的选择。
1.3 回归模型的核心学习目标:逼近真实映射函数
我们再往深挖一层。输入特征x和输出数值y之间,客观存在一个我们不知道的真实关系,记为y=f(x)。机器学习模型的本质就是用一个参数化的函数g(x;θ)去逼近f。分类任务里,g的输出是一个离散分布;回归任务里,g的输出是一个连续值。
理解这一层,你才能看透后面所有的选择。比如,为什么要用MSE做损失函数?因为MSE本质上是假设误差服从高斯分布,模型去最大化似然估计的结果。为什么要做特征归一化?因为神经网络用梯度下降训练,不同特征尺度差异过大会导致损失函数等高线呈椭圆形,梯度更新路径震荡。这些都不是“别人说这么做所以我也这么做”,而是“回归任务的性质决定了该这么做”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据准备和预处理——回归实战最容易翻车的环节
2.1 数据清洗:离群值比缺失值更致命
很多实战教程会把数据清洗一笔带过,好像pandas里dropna一下就算完事。回归任务里,离群值(outlier)的处理优先级远高于缺失值。为什么?因为回归模型在MSE损失下,对离群值极其敏感。一个偏离正常范围10倍的样本,它的损失是正常样本的100倍,模型为了“照顾”这个异常点,会把整体回归曲线都拉歪。
我自己的习惯流程是:
- 先用describe()看各特征的min、max、mean、std,初步确认有没有明显的异常范围。
- 再用散点图矩阵或箱线图目检特征和目标值的关系,重点看目标值本身的分布。
- 对离群值不轻易删除,先判断是测量噪声还是真实极端情况。如果是测量噪声,直接删除或winsorize(缩尾处理);如果是真实极端情况,要评估业务上是否需要单独建模。
数据泄露这个问题在回归任务里也尤其隐蔽。举个例子,你预测设备剩余寿命,如果把“已经运行的总时长”作为特征,模型很容易“作弊”,因为剩余寿命和已运行时长高度相关,但这个相关性在真实部署时完全失效。做特征工程时,必须逐一问自己:这个特征在预测时点拿得到吗?拿得到的情况下,值会不会被未来信息污染?
2.2 特征工程:别急着上深度学习,先把特征做扎实
神经网络在表格数据上的优势本来就不明显,特征工程做得差,再好的网络也白搭。回归任务的特征工程有几个关键动作:
- 量纲统一:这一步主要解决数值范围问题。常用的有StandardScaler(标准化为均值0方差1)、MinMaxScaler(缩放到0-1区间)、RobustScaler(基于四分位数,抗离群值)。回归任务里,我默认先试StandardScaler,效果不好再换。
- 数值特征变换:目标值如果呈长尾分布,比如价格、销量,建议先做log1p变换,让目标分布接近正态,训练会更稳定。预测完再做expm1逆变换还原。
- 类别特征编码:树模型可以直接吃LabelEncoder的结果,但神经网络里类别特征建议用One-Hot或Embedding。如果类别基数特别大(比如几百个城市),Embedding是更好的选择。
数据量很小时,特征工程的优先级甚至高于网络结构设计。你花一个小时清洗数据、构造特征,比花一个小时调网络结构收益大得多。
2.3 训练集/验证集/测试集的划分策略
回归任务样本之间如果存在时间相关性(比如时序预测),绝对不能随机打乱划分,否则就是在用未来数据预测过去,验证结果虚高。正确做法是按时间切分:前80%时间段做训练,中间10%做验证,最后10%做测试。
对普通表格回归,推荐用分层抽样或K折交叉验证。注意目标值是连续值,没法直接“分层”,可以先把目标值切成几个分位桶,再按桶做StratifiedSplit,这样能保证每一折的目标分布和整体一致。
我给学员的建议是:划分数据集之前先明确你最终要解决什么问题。如果答案是“模型上线后预测未来数据”,那就必须按时间切;如果答案是“随机抽样的样本预测”,那随机划分没问题。很多人不分青红皂白,上来就是train_test_split,这是很危险的。
3. 网络骨架怎么搭——从全连接到CNN再到Transformer的选型逻辑
3.1 全连接网络:回归任务的第一块跳板
处理表格型回归,最简单也最可靠的是多层感知机(MLP),也就是全连接网络。你别看它结构简单,只要数据量够、特征工程到位,MLP在表格回归上的表现相当能打。
搭建时的几个关键设计点:
- 输入层维度 = 特征数。
- 隐藏层数量:一般2到4层足够,每层从128个神经元起步,按需递增。表格数据很少需要超过4层。
- 激活函数:隐藏层默认ReLU,但如果网络层数较深且训练不稳定,可以试试LeakyReLU或Swish。输出层一定不设激活函数,否则输出范围被限制,无法回归任意实数。
- Dropout和BatchNorm:回归任务里Dropout别用太猛,0.1到0.3就够,用太猛会让模型欠拟合;BatchNorm通常放在全连接层和激活函数之间,能明显加速收敛。
下面是一个基础MLP回归模型的示例(PyTorch风格):
python复制import torch
import torch.nn as nn
class MLPRegressor(nn.Module):
def __init__(self, in_features, hidden_size=128, num_layers=3, dropout=0.2):
super().__init__()
layers = []
for i in range(num_layers):
if i == 0:
layers.append(nn.Linear(in_features, hidden_size))
else:
layers.append(nn.Linear(hidden_size, hidden_size))
layers.append(nn.BatchNorm1d(hidden_size))
layers.append(nn.ReLU())
layers.append(nn.Dropout(dropout))
layers.append(nn.Linear(hidden_size, 1)) # 输出层无激活函数
self.net = nn.Sequential(*layers)
def forward(self, x):
return self.net(x).squeeze(-1)
这段代码其实就是回归任务里最常用的基础骨架。从这个骨架出发,你可以按需加特征选择、加宽隐藏层、加正则化项,但核心思路不变。
3.2 从图像回归到CNN:特征在哪,卷积就在哪
当你的输入变成图像,全连接网络就不好使了。一张224x224的RGB图像,直接展成向量是15万个维度,全连接层的参数量直接爆炸。CNN天然具有局部连接和权值共享的特性,非常适合从图像里提取空间特征。
图像回归模型的结构通常是:卷积层负责提取特征,最后接一个全局池化或自适应池化,再通过一个小的全连接层输出回归值。比如你用Halcon做深度学习工具(DLTool)处理缺陷图片时,本质上也是这个逻辑:先把图像映射到高维特征空间,再回归出缺陷的尺寸或位置。
做图像回归时有几个实测经验:
- 回归目标如果和图像中目标的大小、位置强相关,建议先做目标检测定位,再在裁剪区域上做回归,精度会比直接在整图上回归好很多。
- 数据增强对分类任务很有用,但对回归任务要小心。旋转和翻转会改变某些物理量的数值含义,比如“角度回归”任务里,旋转90度可能让目标值完全变了。需要针对具体任务设计增强策略。
- 预训练模型迁移学习:图像回归的样本量通常不足,直接用ImageNet预训练模型做backbone,冻结前几层,只训练后面的回归头,效果往往比从头训练好得多。
3.3 时序回归:从RNN到Transformer的选择
时序回归是另一个高频场景。经典做法是LSTM/GRU,它们按时间步逐步处理序列,能捕捉相对短期的依赖关系。但近几年Transformer架构在时序任务上越来越常用,尤其是长序列场景。它的自注意力机制可以直接建模任意两个时间步之间的关系,缺点是计算量大、小数据上容易过拟合。
时序回归在工程里的落地,有一个很重要的设计决策:多步预测是用自回归(把上一步预测值作为下一步输入)还是直接多输出?自回归方式灵活,但会累积误差;直接多输出方式更稳定,但输出维度固定。实践中,如果预测步数不长(比如未来5到10步),直接多输出更省心。
基于深度学习的视频目标跟踪算法、深度估计这类任务,本质上也属于“结构化回归”:输出不是单个数值,而是一整张与输入分辨率相关的结果图(深度图、热力图)。这类任务通常使用编解码器结构,U-Net就是最常用的骨架之一。
3.4 损失函数的组合拳:不是只有MSE和MAE
回归任务最常用的损失函数是MSE(L2损失)和MAE(L1损失)。但要清楚它们各自的脾气:
- MSE:对大误差的惩罚呈平方级放大,所以模型会特别努力地拟合离群点。优点是处处可导,梯度更新平滑,收敛稳定。
- MAE:对所有误差一视同仁,对离群点更鲁棒,但在0点处不可导,收敛速度偏慢,训练后期容易出现“震荡”。
实战里我更推荐Huber Loss:误差小于阈值delta时用MSE,大于delta时用MAE,综合两者优点。PyTorch里直接调用nn.SmoothL1Loss()即可。
还有一类特殊回归任务,比如预测一个角度、预测一个概率值,输出被限制在固定区间。这时建议在输出层加Tanh或Sigmoid,把输出范围先限制住,并用对应的损失函数,训练会更稳。如果输出是多维度的(比如同时预测位置x、y、宽、高),各维度之间的尺度差异可能很大,可以先做归一化再算Loss,或者给不同维度设不同权重。
4. 训练循环里的关键细节——学习率、batch size、归一化、训练曲线,一个都别省
4.1 学习率:回归任务里最重要的超参数,没有之一
回归任务用MSE做损失函数时,损失曲面在高维空间里非常崎岖,学习率设大了,Loss直接震荡甚至爆掉;设小了,训练半天看不到进展。我的经验是:先用一个较大的学习率起步(比如1e-3),观察前几个epoch的Loss下降趋势,如果Loss剧烈震荡或直接变成NaN,立刻降到1e-4或3e-5;如果Loss平稳但下降太慢,再适当调大。
更省事的方案是配合学习率调度器,比如PyTorch里的ReduceLROnPlateau,它会在验证Loss连续几个epoch没有下降时自动降低学习率。我每次跑回归任务几乎必用这个调度器,因为它省去了手动盯训练曲线的功夫。
4.2 batch size的选择对收敛速度的影响
batch size太小,梯度估计噪声大,训练不稳定;batch size太大,虽然梯度方向更精确,但每个epoch的更新次数变少,模型可能收敛到尖锐极小值,泛化性变差。回归任务在数据量不太大(几千到几万样本)的情况下,我习惯取32或64。数据量很大时取128或256。小batch size配合稍低的学习率,往往能训练出泛化性更好的模型。
BatchNorm在回归任务里还有个额外好处:可以缓解小batch size带来的训练不稳定问题。所以如果你的网络结构里加了BatchNorm,batch size设小一点(16甚至8)也还能稳住。
4.3 归一化的“放错位置”就是灾难
我在实战中反复强调过:特征归一化是回归任务里性价比最高的一步。它不仅加速收敛,而且直接影响了MSE/MAE等损失函数的效果。比如一个特征的取值范围是0到1,另一个是0到100000,如果你不做归一化,MSE损失基本被大尺度特征主导,小尺度特征对梯度的贡献几乎可以忽略,模型等于没学到这个维度。
但归一化有个非常隐蔽的坑:测试阶段如果用了训练集的均值和标准差,没问题;如果用错了全局统计量,或者在生产环境里对单个样本做推理时没有维护好均值和标准差,结果会偏移。正确做法是把Scaler在训练集上fit好,然后保存下来,推理时加载同一个Scaler做变换。
4.4 会读训练曲线是入门到进阶的分水岭
回归任务的训练曲线一般看两条:训练Loss和验证Loss。我总结了一个简单好用的判断方法:
- 训练Loss高、验证Loss高:欠拟合,模型容量不够或者特征没做好。加层、加神经元、加深网络,或者回炉重做特征工程。
- 训练Loss低、验证Loss高:过拟合,模型把训练集“背”下来了。加Dropout、加正则化、加数据增强、减小模型容量、收集更多数据。
- 两个Loss都平稳但验证Loss有轻微波动:属于正常现象,配合Early Stopping在验证Loss最低点保存模型就行。
训练轮数不是越大越好。很多人用“固定的200个epoch”训练,然后看结果不好就去改网络结构,这完全跑偏了。正确做法是配合Early Stopping,比如连续20个epoch验证Loss没有改善就停止训练,然后加载验证Loss最低的模型权重。
5. 回归实战中的“隐形坑”——模型评估和数据切分的进阶议题
5.1 R²不是万能的:评估指标要和业务挂钩
回归任务最常用的评估指标是R²(决定系数)和RMSE(均方根误差)。R²的取值范围是负无穷到1,越接近1越好。但R²有一个天然缺陷:它强烈依赖数据本身的方差。如果你的测试集目标值方差本来就很小,R²会很难看,但这不代表模型差;反过来,如果目标值波动巨大,一个蹩脚模型也能拿到不错的R²。
因此实战中我强烈建议同时报告RMSE、MAE和R²,并且一定要结合业务含义做判断。比如你预测的是设备寿命,RMSE是10天和是100天,业务价值完全不同。一个模型即使R²不如另一个,但如果在关键区间的误差更小,可能反而是更好的选择。
5.2 样本量不足时怎么办
深度学习的本质是数据驱动,回归任务同样如此。当样本量只有几百条时,深层网络的泛化能力很难保证,这时候有几个务实的策略:
- 换模型:直接退到经典机器学习,随机森林回归、XGBoost回归、支持向量回归(SVR)在小样本上远比深度学习稳。
- 迁移学习:如果任务是图像回归,用预训练backbone提取特征,再在提取的特征上跑一个简单的回归头,能大幅降低数据需求。
- 数据增强:对表格数据可以做SMOTE回归版本,对图像数据可以做专业的增强策略,对时序数据可以用滑窗重采样。
有一类被忽视的“数据增强”是物理约束。如果你预测的是一个物理量,比如压力、温度、浓度,那它们之间往往有已知的物理关系。把这些约束结构嵌进模型设计里,比如增加一个残差连接来保证输出满足守恒方程,不仅让模型更合理,还能显著减少对样本量的需求。
5.3 上线部署时要注意“环境一致性”
模型训练环境用的Python版本、PyTorch版本、CUDA版本,和线上推理环境不一致,经常会导致推理结果有细微差异。别小看这些差异,回归任务输出的是连续值,一个细微的数值偏差可能在业务上就是不可接受的。我的习惯是用Docker把训练环境完整打包,推理服务直接用同一个镜像,从源头杜绝环境漂移。
在Windows系统上配置深度学习环境的坑特别多。我建议有条件直接上Linux,如果公司机器只有Windows,一定用Anaconda或Miniconda管理环境,千万别在系统Python里直接pip install。PyTorch在Windows上的CUDA版本选择和显卡驱动的兼容性,也容易出问题,装之前先查好自己显卡的驱动支持哪个CUDA版本。
6. 深度学习回归和经典回归,到底该选哪个——从实战出发的选型框架
6.1 表格数据:GBDT系列的统治力有多强
如果你是做表格型数据回归,数据量在几万到几十万这个区间,我第一个推荐的不是深度学习,而是XGBoost回归或随机森林回归。这不是我保守,而是实战里反复验证的结果。树模型对特征尺度和缺失值不敏感,能自动捕捉特征间的非线性交互,而且训练快、可解释性强。
那我为什么还要学深度学习回归?因为表格数据的天花板不在于模型,而在于特征和业务理解。深度学习在表格数据上的优势只有在两种情况下才会显现:一是数据量巨大(百万级以上),且特征高度复杂;二是文本、图像、序列这类非结构化数据,树模型根本没法直接处理。其他情况,先跑XGBoost当baseline,永远是性价比最高的策略。
6.2 图像时序多模态:深度学习回归的王牌阵地
当输入是图像、音频、视频或长文本时,深度学习回归就是唯一合理的选择。树模型做不了,传统统计回归更做不了。像Halcon平台里的深度学习目标定位、尺寸测量、缺陷检测,底层基本都是CNN+回归头。用DLTool做标注和训练,本质上是把深度学习的工程门槛降了下来,但你要真正调好模型、改进精度,还是得理解我前面讲的这些原理。
6.3 一条务实的选型路线
我自己的选型逻辑非常简单,你可以直接抄作业:
- 拿到回归任务,先看数据类型。表格型且数据量不大,上XGBoost,做特征工程,调参。
- 表格型且数据量很大,可以试试MLP,但baseline还是XGBoost,对比后再定。
- 图像型,用CNN+预训练backbone;时序型,如果序列不长用LSTM,序列长用Transformer;多模态,上大规模预训练模型做embedding,再接回归头。
- 无论哪种,先跑通一个简单的baseline,再逐步加复杂度。任何情况下,都不要一上来就搭一个巨大的网络,那是最容易把人劝退的做法。
我在Alpha工业项目里的流程就是这样:每次接到回归需求,先问清楚业务方“现在没有模型时,你们是怎么做的?误差大概多少?”如果业务现状已经是一个简单线性回归模型,你上一个XGBoost就能提升不少;如果现状是老师傅凭经验估计,那深度学习也好、经典回归也好,只要能输出一个量化结果,就已经是巨大进步。
最后分享一个实操心得:我是强烈建议每个做回归实战的人养成记录“实验卡”的习惯——样本量、特征数、模型结构、超参数、训练时间、RMSE/MAE/R²,每一次实验都记下来。模型调试最怕的是凭感觉改参数,改完不知道是哪个变化影响了结果。有了实验卡,你调参的效率能翻一倍。这一节的内容讲完了,剩下的就靠你自己拿一份数据跑起来,跑通一个完整的流程,比看十遍教程都有用。
