【机器学习】损失函数与梯度下降:机器如何通过“犯错”不断变好

上一节我们把日志整理成了真正可用的数据集:样本定义了模型在决策时能看见什么,标签定义了它应当相信什么,数据分布则划定了它将面对怎样的世界。

但一份数据集放到模型面前,模型并不会自己"领会规律"。它首先得知道:自己的预测到底错在哪里,错得有多严重;然后还要知道,该把内部哪一部分往哪个方向改一点。

这正是损失函数与梯度下降要解决的事。前者把"做得不好"变成可度量的反馈,后者把这份反馈变成一次次参数修正。

文章摘要

本文以单关节机械臂的负载估计为例,解释模型如何把"预测错了"转化为可执行的学习信号。损失函数负责度量预测与真实结果之间的差距,同时把任务目标、误差偏好与安全边界写进训练过程;梯度则描述每个参数朝哪个方向微调,最能让损失下降。文章借助"在损失地形中下山"的直觉,说明前向计算、损失评估、反向传播与参数更新构成的训练闭环,并讨论学习率过小、过大和合适时的差别。最后结合控制系统的反馈思想,区分训练误差与真实泛化能力,提醒读者:损失下降并不自动代表模型理解了世界,数据质量、任务定义和测试边界仍决定模型能否可靠部署。

写在前面

继续回到那台单关节机械臂。

假设我们已经按上一节的原则,准备好了一批可靠样本:输入是过去一段时间的位置、速度、电流、温度与控制命令;标签则是经过标定的真实末端负载。现在,模型接收一条新样本后,给出了一个估计值:

  • 真实负载是 3 kg;
  • 模型第一次预测成了 4.2 kg;
  • 下一次,它又预测成了 3.7 kg;
  • 经过足够多轮训练后,才逐渐逼近真实值。

这里最值得追问的并不是"模型最后准不准",而是:它为什么会从 4.2 kg 改成 3.7 kg?它又凭什么知道该改哪几个参数,而不是随机地胡乱尝试?

机器学习不是让机器第一次就答对,而是让它把每一次偏差都变成下一次改进的依据。

如果把控制系统看作"根据当前误差修正执行器输出"的快速反馈环,那么模型训练可以理解为一个更慢、也更抽象的反馈环:它不直接调节电机,而是调节自己内部的参数。

于是,这一节真正要回答的问题是:

损失函数怎样定义一次"犯错"?梯度下降又怎样把犯错转化为模型内部的持续改进?


一、先给结论:学习,本质上也是一个反馈闭环

先把结论说清楚。

一次典型的监督学习训练,并不是"把数据输入模型,答案自然出现"。它至少要经过下面四步:

  1. 预测:模型根据输入给出当前答案;
  2. 比较:损失函数将预测与真实标签比较,得到一个误差分数;
  3. 归因:梯度计算每个参数对误差的影响方向与敏感程度;
  4. 修正:优化器依据梯度,小幅更新参数后再尝试一次。

这四步不断循环,才形成了机器学习真正的训练过程。

训练环节 它回答的问题 对机械臂负载估计意味着什么
模型预测 "按当前理解,我会给出什么答案?" 根据位置、电流、速度等信号估计负载
损失函数 "这个答案离目标有多远?" 4.2 kg 与真实 3 kg 的差距应被记成多严重
梯度 "改动哪里最可能让误差变小?" 哪些内部权重对当前高估最敏感
参数更新 "下一次该怎样调整?" 略微改变权重后,再用相似样本检验

这和前面专栏里反复出现的反馈思想高度一致:没有比较,就没有误差;没有误差信号,就谈不上修正;没有持续修正,系统也无法逐步逼近目标。

不同只在于,控制器通常调整的是此刻的控制输入 uuu;而训练过程调整的是模型长期保留的参数 θ\thetaθ。前者要在毫秒级赶上物理过程,后者可以花几秒、几小时甚至更久,从大量历史经验中慢慢改变自身。


二、损失函数:先把"错得多严重"说清楚

模型的输出与真实标签之间,当然可以直接做差;但"做差"并不等于已经定义好了学习目标。

仍以负载估计为例。若真实负载为 yyy,模型预测为 y^\hat{y}y^,最朴素的误差是:

e=y^−y e = \hat{y} - y e=y^−y

问题在于,正负误差会互相抵消:高估 1 kg 与低估 1 kg 相加是 0,但两次预测显然都没有做好。因此,我们通常需要把"偏离目标"转换成一个始终非负、且可以比较的分数,这个分数就是损失(loss)

1. 损失不是成绩单,而是模型的"改进方向盘"

常见的回归损失之一是均方误差:

L=1N∑i=1N(y^i−yi)2 L = \frac{1}{N} \sum_{i=1}^{N} (\hat{y}_i - y_i)^2 L=N1i=1∑N(y^i−yi)2

不必急着记住这个式子。它只表达了两个直觉:

  • 每个样本的预测偏差都要算进去;
  • 偏差越大,惩罚会增长得越快。

于是,把 3 kg 错估成 3.1 kg 与错估成 7 kg,不会被当作同样程度的问题。对机械臂这类系统而言,这种偏好常常是合理的:较大的负载误判可能带来更明显的轨迹误差、力控风险或安全余量不足。

但均方误差不是唯一选择。损失函数其实是在告诉模型:在这个任务里,哪种错误更不能接受。

任务或关注点 常用的损失思路 它表达的偏好
连续数值预测 均方误差、绝对误差 预测值应接近真实数值
少量极端异常不应主导训练 更稳健的误差函数 不让个别离群点牵着全部参数走
故障是否发生的分类 交叉熵一类的分类损失 对正确类别给出更高置信度
漏报风险远高于误报 加权损失、代价敏感损失 更严厉地惩罚漏掉关键风险

因此,损失函数不是训练之后才看的分数,而是训练开始时就写下的一条价值判断。若我们只最小化"平均误差",模型可能在常见工况下很好,却忽略重载、高温或临界故障这些更重要的少数场景;若把所有异常都赋予极高权重,模型又可能频繁误报。

这与 LQR、MPC 中的代价设计并没有本质差别:优化器只会认真完成我们写进目标里的事情。

2. 一个下降的损失,不一定代表问题被解决

这里需要保留一份警惕。

如果标签本身错位、训练数据几乎都是空载工况,或者损失函数只关心平均误差,那么训练损失完全可能持续下降;但模型学到的只是"在这一小块熟悉世界里,把这道题做得更像训练答案"。

上一节讨论的数据质量、时间泄漏和分布覆盖,并没有在进入训练后失效。它们决定了损失所比较的"正确答案"是否可信,也决定了这份下降能否代表未来真实任务中的进步。

更准确地说:

损失函数能度量模型相对既定目标的偏差;它不能替我们证明,既定目标、标签和数据世界本身就是正确的。


三、梯度:它不只告诉模型"错了",还告诉模型"该往哪儿改"

现在,模型已经拿到一个损失值。假如损失是 0.82,这个数字本身依然不够。

它只能说明"当前不好",却没有说明:模型内部成千上万、甚至上百万个参数中,究竟该动哪个?每个参数应该增大还是减小?动多大才合适?

这便轮到梯度登场。

1. 用"下山"理解梯度

可以把所有模型参数想象成我们在一片复杂地形中的位置。不同参数组合会得到不同损失,于是整片地形的高度就代表损失大小:高处意味着预测很差,低处意味着预测更接近目标。

梯度并不是"最低点的位置",而是站在当前位置时,地形上升最快的方向。要让损失下降,就朝它的反方向走一小步。

在山坡上,若你想尽快下山,最有用的信息不是"你现在海拔 820 米",而是"此处哪个方向最陡"。梯度提供的正是这种局部方向信息。

对于某个参数 θ\thetaθ:

  • 梯度为正,意味着把它再增大一点,损失倾向于变大;
  • 梯度为负,意味着把它增大一点,损失倾向于变小;
  • 梯度接近零,意味着当前位置附近已较平缓,或这个参数暂时对损失不敏感。

因此,最基本的更新形式是:

θ←θ−η∇θL \theta \leftarrow \theta - \eta \nabla_\theta L θ←θ−η∇θL

其中 ∇θL\nabla_\theta L∇θL 是损失对参数的梯度,η\etaη 是稍后要讨论的学习率。这个式子最重要的只有一句话:减号意味着朝让损失下降的方向移动。

2. 梯度是局部建议,不是全知地图

梯度并不会告诉模型"全局最低点在哪"。它只能根据当前位置附近的地形,给出一次局部建议。

这也解释了训练为什么必须迭代:走一步后,位置变了,地形的局部方向也变了;模型再重新计算梯度、再走下一步。很多微小修正叠加起来,才构成从粗糙预测到较好预测的过程。

在深度神经网络中,一个输出往往经过多层计算才得到。最终损失要想影响靠前层的参数,就需要把"这次误差对后面每层的影响"逐层传回去。这个高效的梯度计算过程,就是常说的反向传播

要注意,反向传播并不等于训练的全部:它负责算清梯度;而究竟怎样使用梯度、是否加入动量、是否为不同参数调整步长,则属于优化器的职责。


四、从一次样本到一次训练:模型怎样完成"预测---犯错---修正"

为了更直观地看清训练闭环,可以先忽略网络内部的复杂结构,只看一次小批量训练发生了什么。

python 复制代码
# 1. 用当前参数做预测
prediction = model(features)

# 2. 把预测与真实标签比较
loss = loss_function(prediction, target)

# 3. 清除上一次残留的梯度,再反向计算本次梯度
optimizer.zero_grad()
loss.backward()

# 4. 按优化规则更新参数
optimizer.step()

这几行代码背后,其实仍是熟悉的反馈闭环:

代码动作 训练中的含义 控制系统中的相似角色
model(features) 当前参数下的预测输出 被控对象对输入的响应
loss_function(...) 衡量预测与目标的偏差 误差计算环节
loss.backward() 找出各参数对偏差的影响 误差如何传播、如何归因
optimizer.step() 据此更新模型内部状态 控制律给出修正动作

真正的训练并不会只看一条样本。通常,模型会同时处理一个小批量(mini-batch)数据,再用这批样本的平均损失更新一次。这样做既能降低单条样本噪声造成的偶然影响,又不必每次都等待整个数据集计算完毕。

一轮把训练集大致遍历一次的过程,常被称作一个 epoch。随着 epoch 增加,训练损失通常会先快速下降、后逐渐放缓;但我们仍应同步观察验证集表现,因为"训练集越来越熟"不等于"面对新工况越来越可靠"。


五、学习率:每一步走多远,决定模型是在靠近目标还是来回震荡

梯度给出了方向,学习率 η\etaη 则决定一次更新迈出多大的步子。

这很像控制系统里增益的选择:太小,修正极慢;太大,可能冲过目标、来回摆动,甚至彻底发散。

图中从左到右依次对应:步子过小、步子合适、步子过大。训练不是"每次改得越多越好",而是在速度与稳定性之间寻找可控的尺度。

学习率状态 常见现象 背后的直觉
过小 损失缓慢下降,训练耗时很长 每次只挪动极小距离,方向虽然正确却推进不足
合适 损失总体下降,偶有波动但能逐步稳定 每一步既能获得进展,也没有越过太多
过大 损失剧烈震荡、变大或出现数值异常 每次都越过低点,甚至被推向更高处

现实中的损失地形远比一个规则碗面复杂:有的方向陡,有的方向平;有的参数尺度很大,有的很小;小批量数据还会给梯度带来噪声。因此,常见优化器会在基础梯度下降上加入动量、自动调整步长或学习率衰减等机制。

不过这些技巧不应遮住核心。无论使用 SGD、Momentum、Adam 还是其他优化方法,始终都在完成同一件事:根据当前误差的局部反馈,选择一次更稳妥的参数修正。


六、为什么"训练损失下降"仍不足以宣布成功?

看到损失曲线往下走,确实值得高兴;但在真实工程中,还不能立刻把模型交给生产系统。

因为损失的下降至少可能混合了两类完全不同的原因:

  • 模型真正抓住了输入与目标之间可迁移的关系;
  • 模型只是记住了训练数据中的偶然模式、设备个性或错误标签。

下面这些现象尤其值得在训练时主动检查。

现象 可能原因 应先检查什么
训练损失下降,验证损失上升 过拟合,模型记住训练集细节 划分是否按时间/批次隔离,模型是否过复杂
损失长期不降 学习率不合适、输入无有效信息或标签噪声过大 基线模型、标签对齐、特征量纲与数据管道
损失突然变成异常值 学习率过大、数值溢出、数据中混入非法值 输入范围、梯度范围、数据缺失和归一化
平均损失很好,关键工况很差 常态样本占比过高,目标函数未体现风险 重载/高温/异常分组指标与加权策略
离线指标很好,上线效果变差 训练与部署的信息边界不一致 时间泄漏、传感器差异、分布偏移

例如,模型可能把"某台机械臂的序列号"或某个特定时段的温度背景,当成负载的捷径;在同一台设备、相近日期的测试集上表现很好,换到另一台设备却立刻失效。损失函数并不会自动识破这件事------它只会尽力把当前喂给它的数据拟合得更好。

所以,训练过程至少应同时查看三组信息:

  1. 训练损失:模型是否能从现有样本中学习;
  2. 验证损失与分组指标:它是否能面对未参与更新的新数据,以及在关键工况下是否仍可靠;
  3. 部署边界:在线输入是否与训练时一致,模型输出是否仍受到原有控制器和安全逻辑约束。

这里的重点并非追求一条绝对平滑、绝对低的曲线,而是让每一个分数都有明确的任务语义与可追溯边界。


七、把损失函数放回五层知识框架:它是慢时间尺度上的误差反馈

从专栏开篇提出的"反馈回路进化"来看,损失函数与梯度下降并不是突然出现的一套陌生语言。

层次 被比较的偏差 被修正的对象 时间尺度
基础闭环控制 参考值与测量值之间的控制误差 控制输入、执行器输出 微秒到毫秒
状态估计与最优控制 预测、测量与代价之间的偏差 状态估计或控制序列 毫秒到秒
嵌入式实现 任务执行与截止时间、数值范围之间的偏差 调度、限幅、保护动作 微秒到秒
机器学习训练 预测值与标签之间的损失 模型参数 秒到小时甚至更久
大模型与 Agent 行动结果、目标与人类偏好之间的差距 策略、工具调用与后续规划 秒到天

它们都包含"观察结果---计算偏差---据此修正"的结构,只是优化对象和反应速度不同。

控制系统在运行中不断修正输出,是为了让机械臂此刻不偏离轨迹;机器学习在离线训练中不断修正参数,是为了让模型在未来面对类似但未见的数据时,能给出更好的估计。两者不能相互替代:训练模型无法取代毫秒级安全控制环,而一个固定控制律也很难独自吸收长期积累的复杂数据规律。

因此,在具身系统中更合理的分工往往是:底层控制环负责稳定、限幅和安全;学习模型负责预测、估计或补偿;损失函数则把"我们希望模型在哪些方面更可靠"明确写入训练反馈中。


In the end:下一步该看什么

到这里,我们已经知道模型如何得到误差信号、如何据此计算梯度,又如何通过一小步一小步的更新降低损失。

但新的问题也随之出现:如果只是线性地组合位置、电流、速度和温度,模型能表达的规律终究有限。面对接触摩擦、非线性温升或多传感器耦合时,机器为什么能够从原始数据中逐层抽取出更有用的特征?

下一节,我们将继续沿着这条反馈线进入神经网络内部:神经网络与表征:为什么层层变换能让模型学会特征?

相关推荐
jsl_jsl_jsl1 小时前
《Agent 是怎么“思考”的:ReAct 循环与流式 SSE 的完整实现》
人工智能
sarasuki1 小时前
失败重试:Agent 中指数退避的正确姿势
人工智能·设计模式·agent
sxwuyanzu1 小时前
DeepSeek冲IPO-谁在为它付钱-公众号发布稿
大数据·人工智能·科技
一切皆是因缘际会1 小时前
科技的赋能
人工智能
甲维斯1 小时前
RSI“真“”来了,OpenAI和Anthropic把人类逼到墙角!
人工智能
大模型码小白1 小时前
告别造假数据,直接连数据库查真实时序数据喂给 TimechoAI 大模型
java·数据库·人工智能·microsoft·架构
IvorySQL1 小时前
PostgreSQL 日报|建库策略致备库静默丢数据(9 月 12 日)
数据库·人工智能·postgresql
来两个炸鸡腿1 小时前
【Datawhale2609】算子开发实战 task01-熟悉沐曦GPU
人工智能·学习·大模型
opensnn2 小时前
AI竞争进入生态时代:OpenCL为何值得关注
人工智能