· 深度学习
梯度下降:从「哪里陡往哪走」到一条能预测的直线
把梯度下降拆成一条完整推导链:找关联 → 建模型 → 定标准 → 构造损失 → 求偏导 → 合成梯度 → 沿反方向下山。每一步只回答一个问题:现在往哪走、走多远。
一个能预测价格的函数是怎么被「找」出来的?本文把梯度下降拆成一条完整的推导链:找关联 → 建模型 → 定标准 → 构造损失函数 → 求导数 → 求偏导 → 合成梯度 → 沿反方向下山。每一步都只回答一个问题:现在该往哪走,走多远。
让曲线穿过每一个数据点
看起来「完全拟合」,但新数据一进来就落在曲线之外。样本越多,曲线越扭曲,换来的是零泛化能力。这就是过拟合:过犹不及。
用一条直线去近似,再用误差挑出最好的那条
直线只有斜率和截距两个自由度,抗噪、可外推。把「哪条更好」量化成一个可以求最小值的函数,问题就从「审美」变成了「计算」。
雾中下山的直觉:梯度下降的骨架只有一句话
- 梯度下降的核心假设:不需要知道整座山的样子,只需要知道脚下这一步的坡度。
- 策略极简——朝当前最陡的下坡方向迈一步,然后重新测量,重复到走不动为止。
- 后面出现的导数、偏导、梯度、学习率,全部是在精确化「哪边最陡」和「一步多大」这两件事。
设想你站在一座雾气很重的山坡上,能见度极低,看不到山顶也看不到谷底,唯一能感知的是脚下这一小块地面的倾斜程度。目标是走到最低处的山谷。
信息如此匮乏,可行的策略只有一条:感受脚下哪里最陡,朝那个最陡的下坡方向迈出一步,在新的位置再感受一次,再迈一步。如此反复。
这个策略朴素得不像个算法,但它就是梯度下降的全部骨架。它放弃了对全局地形的认知,只依赖局部信息;代价是有可能停在某个小坑里出不来,收益是在高维空间里它依然跑得动——而高维空间里人类根本没法「看一眼全局」。
后续所有的数学,都只是在把两件事说得更准确:方向是哪个方向,一步迈多远。
预测的前提,是先承认数据之间存在关联
- 「先发制人」的有效性来自准确预测,而预测的前提是掌握规律,规律只能从数据里来。
- 规律的表现形式是数据与数据之间的关联,例如气温与雪糕销量同向变化。
- 把两组数据放进同一个坐标系,是发现关联最直接的动作:横轴一个量,纵轴另一个量。
算法是为解决实际问题而出现的。「先发制人,后发而制于人」这句话成立的前提是先发要有效;而有效先发,靠的是对事物的准确预测。要预测,先得掌握规律;规律从哪来?从数据上来。
所以关键动作是找到数据与数据之间的关联。气温越高,雪糕的销售额越高;左边的量变大时右边的量也跟着变大,这就是一条关联。
找到关联最直接的办法,是把两组数据摆到同一个坐标系里。横坐标取房子的面积,纵坐标取房子的价格,散点落上去之后,两者同向变化的趋势几乎肉眼可见。
但「看出正相关」离「能用来预测」还差着一步:你需要两者之间的函数关系式。有了它,下次只给出一个面积,代进去就能算出价格。
为什么不要一条穿过所有点的曲线
- 让曲线穿过每个数据点看似完美,实则把噪声也当成了规律记住。
- 只要出现新样本,它几乎必然不在这条曲线上——拟合得越死,泛化得越差。
- 这类「用力过猛反而更差」的做法,名字叫过拟合,本质是过犹不及。
要求函数关系式,一个自然的想法是:做一条曲线,把坐标系里所有的点都穿过去。点被完美覆盖,误差为零,听起来无懈可击。
问题是这条路走不通。当新数据加进来时,你会发现它根本不在这条曲线上——因为那条曲线是照着旧数据「雕刻」出来的,每一个拐弯都在迁就某个具体的点,包括那些本就带有偶然性的噪声。
这相当于做了一件吃力不讨好的事。这样的动作有个正式名称:过拟合。它拟合的是样本,不是规律;记住的是噪声,不是趋势。
对于明显存在相关关系的数据,最朴素的方法往往效果更好:直接用一条直线去拟合。直线只有两个参数,容不下对单个样本的过度迁就,反而更容易逼近背后的真实关系。
线性回归:一条直线只需要两个数
- 直线就是一次函数 y = kx + b,确定斜率 k 与截距 b,这条线就被唯一确定。
- 找到最合适的那条直线的整个过程,叫线性回归。
- 模型的「学习」,在这个场景下等价于在两个参数上做搜索。
直线好处理,因为它就是一次函数:y = kx + b。斜率 k 决定倾斜程度,截距 b 决定它与纵轴的交点。
也就是说,只要把 k 和 b 两个数定下来,这条直线就被唯一确定了。整个问题瞬间收缩成一个二维搜索:在 (k, b) 这个平面上,哪一组取值对应最贴合数据的那条线。
把「从数据中找出最合适的直线」这个动作称为线性回归。名字听起来像统计学的专门术语,实质上它做的就是参数搜索。
接下来真正的问题是:凭什么说这条线比那条线更合适?在候选线还没有确定标准之前,「最合适」只是一句空话。
怎么判断哪条线更好:给候选线办一场选秀
- 候选线给出的值是估算值,真实数据与估算值之间的差距就是误差,在图上表现为点到直线的距离。
- 把每个点的误差累加起来,总误差更小的线,与原始数据更吻合。
- 评价标准一旦可计算,「哪条线更好」就从主观判断变成了可比较的数值。
既然一时定不准哪条线最好,就把候选线全都摆上台面比一比,选出表现最好的那条。剩下的问题只有一个:选秀的标准是什么。
设坐标系里那些点是真实数据,候选线有 A 和 B 两条。无论哪条候选线,它给出的都是估算值,与真实值之间必然存在差距。这个差距就是误差,在图上体现为:真实数据点到这条直线的垂直距离有多长。
把 A 线在所有样本点上的距离算出来,再把 B 线的算出来,两者一比就能看出差别——距离之和更短的那条线,和原始数据吻合得更好,它胜出。
这一步是整个推导的转折点:原本模糊的「更合适」,被换成了一个能算出具体数字的量。有了数字,才能谈最小化。
距离为什么必须平方:解决正负抵消
- 直接用真实值减估算值,位于直线上方的点算出来是正数,下方的点是负数。
- 一正一负相加会互相抵消,导致明明偏差很大的线,算出的误差总和却很小。
- 消除符号影响的办法是把每一项平方后再相加,平方同时放大了大偏差的权重。
用数学语言把这个标准写下来。真实数据是 y₁、y₂、y₃、y₄、y₅,候选线给出的估算值是 ŷ = kx + b,那么每个点的误差就是 yᵢ − ŷᵢ,把它们全加起来,就是这条线的「距离之和」。
这里立刻出现一个问题:点在直线上方时,真实值减估算值是正的;点在线下方时,算出来是负的。直接累加,正负相消,一条明明偏差很大的线,最后可能得到一个很小的总数。
为了消除正负号带来的干扰,最直接的做法是把每一项取平方再相加。平方之后全是正数,不会互相抵消,同时还能反映偏差的总体大小。
顺带得到一个副作用:平方会让较大的偏差被放大得更厉害。一条线如果多数点贴得很近、却对某个点偏得离谱,平方和会把这种「个别严重错误」惩罚得更重——这通常正是我们想要的。
为什么还要除以样本数:让不同规模可比
- 累加平方和有一个缺陷:取样点越多,总和必然越大,不同样本量的结果无法直接比较。
- 取平均即可消除样本数量的影响——五个点就除以五,十个点就除以十,N 个点就除以 N。
- 这个平均值就是平均平方误差 MSE,也是本场景下真正要最小化的目标。
平方和解决了符号问题,却带来第二个麻烦。如果一条候选线只取 5 个样本点,另一条取了 10 个,那么取点更多的那条,累加出来的平方和天然更大。
也就是说,样本数量不同的时候,两个平方和根本没有可比性。数量本身成了干扰项。
处理方法很朴素:取平均。取 5 个点就在前面除以 5,取 10 个点就除以 10,取 N 个点就除以 N。平均之后,「每个点平均偏差多少」成了共同尺度,随便怎么比都成立。
于是选秀标准正式落地:算出来的值越小,这条线与原始数据吻合得越好。这个标准的名字叫平均平方误差,记作 MSE。
MSE 与 MAE:为什么梯度下降偏爱平方
- 既然目的是消除正负号,取绝对值同样可行,这一版本叫平均绝对误差 MAE。
- 两者在不同场景各有优势,没有绝对优劣。
- 梯度下降一般选择 MSE,因为它的数学性质更好,求导更顺手。
一个自然的反问:既然平方是为了消除正负号,那直接取绝对值不是一样能消除吗?
当然可以。取绝对值再取平均,得到的是平均绝对误差,记作 MAE。它同样是一个合法的评价标准,而且在「惩罚离群点」这件事上比 MSE 更温和。
MSE 和 MAE 在不同场景下各有优势与特点,并不存在哪个更先进。
但在梯度下降这个框架里,一般用 MSE。原因很实际:MSE 的数学性质更好,平方函数处处光滑、处处可导,沿着它做求导和迭代不会有磕绊;绝对值函数在原点处不可导,处理起来要多绕几步。做推导时,遇到平方总比遇到绝对值顺手。
候选无穷多:把选秀问题升维成一张曲面
- 候选线少的时候可以逐条试算,候选无限多时就必须换一种组织方式:用参数 (k, b) 来索引。
- 每一组 (k, b) 对应一条直线,也对应一个 MSE 值 Z,三者构成确定性的映射。
- 以 k、b 为自变量、Z 为函数值,得到一个二元函数;原来的「挑最好的线」变成了「找 Z 的最小值」。
如果候选线只有几条,肉眼能看出来,或者稍加计算就能定。但参数可以取任意实数,候选线是无限的。逐条试算显然不可行,得换个组织方式。
把候选线列成一张表会更清晰:每条线都有自己的斜率和截距,比如第一条是 (k₁, b₁),把它代入 MSE 的表达式,算出一个具体的数值 Z₁;第二条是 (k₂, b₂),算出 Z₂;依此类推。
任务于是变成:把所有的 MSE 值算出来,挑出其中最小的那一个,它所对应的 (k, b) 就是你想要的直线参数。
到这里,一个关键的结构变化发生了。k 和一个 b,经过计算得到一个 Z——这不就是一个以 (k, b) 为自变量、以 Z 为函数值的二元函数吗?二维平面上的散点问题,被抬到了三维空间里的一张曲面上。
损失函数:任务变成找山谷最低点
- 这张曲面把每个参数组合映射到一个误差值,它的正式名称是损失函数。
- 曲面的高度代表「这个参数有多差」,最低点代表「这个参数最好」。
- 求解目标从此与数据无关,纯粹是一个几何问题:在曲面上找到最低的那个位置。
二元函数大致呈现出碗状或山谷状:参数偏离最优值时,函数值升高;参数接近最优值时,函数值下降。
这个函数被称为损失函数。它的输入是模型参数,输出是这个参数组合下模型有多差。高度即误差,越高越差。
原本的目标「找出 Z 的最小值」,翻译到这张曲面上,就是找出这个损失函数最低的位置——山谷的谷底。
换个说法:要找一条最合适的直线,等价于在一张有高低起伏的曲面上找到最低的那个点。找直线的问题,正式变成了下山的问题。
导数:既指方向,也给步长
- 先把维度降下来看一元函数:某点的导数就是该点切线的斜率,符号直接给出上坡方向。
- 导数为正,说明往自变量增大的方向走是上坡;导数为负,说明要往减小的方向走。
- 导数的绝对值可以直接当作步长:坡度越陡迈得越大,接近坡顶时步长自然收缩,导数为零则停下。
要讲清楚下山,得先从上山讲起。先看一维情形:一个一元函数 f(x),曲线画在平面上。给曲线铺上经纬线,就像地图一样方便定位——在二维情形里,一条是 k 方向,一条是 b 方向。
假设你现在站在 x₀ 这个位置,对这一点求导,得到的几何意义就是该点切线的斜率。如果算出来大于 0,意味着往 x 增大的方向走才是上坡;换到另一点 x₁,如果导数为负,那就得往 x 减小的方向走才能上坡。
所以导数首先解决方向:它告诉你哪边是往上,哪边是往下。
但只知道方向还不够,还需要知道一步迈多远,以及什么时候该停。恰好导数也能做这件事——直接把导数的大小当步长。若 x₀ 处的导数是 2,就以 2 为步长,往增大的方向走到 x₀ + 2;在新位置再求导,假设得到 0.5,就再往前挪 0.5,到达 x₀ + 2.5。
越靠近坡顶,坡度越小,步长自动收缩。抵达坡顶时导数为 0,步长也为 0,直接停下。方向、步长、终止条件,一个量全部给出。
步子迈太大,会出三种事故
- 跨过坡顶不算致命:新位置的导数变成负值,下一步自动往回走,多次反复仍会收敛。
- 真正危险的是跨到对称位置——两边来回跳,或跳到更陡处导致越跳越远,直接发散。
- 还有一种失败与步长无关:卡在局部的小山顶上,坡度归零,误以为已经到达最高处。
把这个过程写成式子:当前所在点是 xₙ,对它求导,把导数值直接加到自己身上,得到的结果就是下一个落脚点。这是最理想的状态。
实际会出岔子。第一种情况:起点的切线太陡,步长过大,一步跨过了坡顶。这时不必慌——站在越过坡顶的新位置上求导,得到的是负值,下一步会自动往回走。来回几次,仍然能到达坡顶。
第二种情况:一步恰好跳到了对称的位置。因为对称,在那里求导再往回跳,又跳回起点,于是两点之间反复横跳,永远停不下来。
第三种情况更糟:一步跳到斜率更大的地方,下一步往回跳得更远,再下一步跳得更远,循环放大,数值直接爆炸。
还有一类失败与步长无关。如果地形不止一个山顶,前面那段坡又很缓,导致每一步都很小;好不容易爬到一个矮山头,坡度归零,迈不过去了,就会以为已经到顶而停下。这叫陷入局部最优解。
学习率:给步长加一个可调的系数
- 更新位置时,在导数前面乘一个系数 α,用它来控制每一步的长短。
- 这个系数叫学习率,是梯度下降里最关键的可调参数——太大会震荡发散,太小会爬得极慢。
- 学习率不必是固定值,怎么随过程变化属于策略问题。
针对上面这些事故,自然的对策是:更新位置时不要直接用导数当步长,而是在导数前面乘一个系数 α。
这个系数叫学习率。它把「坡度」换算成「我实际愿意迈出的距离」——坡度是地形给的,迈多远是自己定的。
学习率不一定是个定值,主要看策略:可以开始时给大一些快速接近,接近谷底时调小以避免来回震荡,也可以按迭代次数衰减。
至此一维情形已经完整:导数值给出方向,学习率控制步长,导数为零时停止。剩下的事情,是把它搬到有两个方向的空间里。
从一维到二维:方向是可以分解的
- 二元函数的自变量有两个:k 方向和 b 方向,上山的方向是这两个方向的合成。
- 和在平面地图上一样,向东走一段再向北走一段,等价于直接向东北方向走。
- 既然总方向是上坡,那么它在两个分量方向上的投影,也必然各自都是上坡。
二元函数难在方向不再是一条线上的两个朝向,而是整整一个平面。站在 (k₀, b₀) 这个点上,可以沿 k 方向走,可以沿 b 方向走,也可以斜着走。
上坡的方向可以看作两个方向分量的合成,这和地图上的情形完全一样:往东走一段,再往北走一段,最终效果等价于直接往东北方向走。
由此得到一个重要推论:既然你的总方向是上坡,那么在 k 方向和 b 方向上的投影,也应当分别都是上坡。反过来,只要分别求出这两个分量方向上的上坡幅度,把它们组合起来,就得到了完整的上坡方向。
问题于是降级为两个简单版的一维问题:沿 k 方向怎么走,沿 b 方向怎么走。
偏导数:把另一个变量当常数
- 沿 k 方向切一刀,截出的这条曲线上所有点的 b 值都相同,于是问题退化成一元函数。
- 把 b 当常数、只对 k 求导,得到的就叫对 k 的偏导数;另一个方向同理。
- 两个偏导数的值,分别就是 k 和 b 各自应该变化多少。
先看 b 方向。假设当前站在 (k₀, b₀),沿 k 轴方向切一刀——也就是固定 k = k₀,从侧面看过去,截出来的实际上是一条曲线,这条曲线位于 b 与 Z 构成的平面上。
既然要求 b 方向的上坡幅度,就对这个点求导。关键在于:这条截线上所有的点,k 值都固定为 k₀ 不变。
于是把 k 当作常数处理,只对 b 求导——这不就是二元函数对 b 的偏导数吗。求出偏导之后,把 b = b₀ 代进去,得到的数值就是 b 该变多少。
k 方向完全对称:换个视角切一刀,固定 b = b₀,沿着 k 方向截出一条曲线,重复同样的步骤求偏导,得到 k 该变多少。
两个方向各自的变化量都算出来了,把它们放进一个括号里组合起来,就得到了一个完整的量。
梯度:一个指示方向与幅度的二维向量
- 把两个偏导数组合成的量,既给出 k 和 b 各自往哪走,也给出各自变化多少。
- 具备方向与大小两个属性的量就是向量,这个向量叫梯度。
- 梯度是参数平面上的二维向量,不是三维曲面上的三维向量,这一点容易混淆。
两个偏导数并排写在一起,形式上是一个带括号的组合。它同时回答了两个问题:k 和 b 分别往哪个方向走,以及各自变化多大。
既有方向又有大小的量,在数学里叫向量。这个向量有专门的名字:梯度。
需要注意它所在的维度。梯度指明的是 k 方向和 b 方向各自的变化量,所以它是 (k, b) 参数平面上的一个二维向量,而不是三维空间里的箭头——曲面的高度只是用来算偏导的,箭头本身躺在参数平面上。
用具体数字走一遍。假设现在站在点 (1, 2),此处算出的梯度向量是 (2, 3),那么下一个落脚点就是:1 + 2 = 3,2 + 3 = 5,落在 (3, 5)。梯度的两个分量,直接就是两个坐标的增量。
下山:沿梯度的反方向走
- 梯度指向的是函数值增大的方向,也就是上坡;下山只需沿它的反方向走。
- 数学上就是把梯度向量乘以 −1,再让参数沿这个方向更新。
- 完整更新式:新参数 = 旧参数 − 学习率 × 该方向偏导数,两个方向分别执行。
梯度给的是上山的方向。要下山怎么办?关键在于这里的曲面是连续可微的:既然沿着梯度方向走是上升,那么反着走必然是下降。
数学上的操作很直接:求出梯度向量,在它前面乘 −1,然后沿着这个方向走,就是下山。方向问题就此解决。
写成更新式。当前参数是 (kₙ, bₙ),下一个位置是:kₙ₊₁ = kₙ − ∂Z/∂k,bₙ₊₁ = bₙ − ∂Z/∂b。也就是各自减去自己方向上的偏导数。
别忘了还要控制步长:在每个偏导数前面乘上学习率 α,得到 kₙ₊₁ = kₙ − α · ∂Z/∂k,bₙ₊₁ = bₙ − α · ∂Z/∂b。
这就是梯度下降的完整迭代规则。它的每一轮只做三件事:算两个偏导,乘上学习率,从当前位置减掉。
收敛:偏导归零的地方就是谷底
- 随着迭代推进,两个偏导数逐渐趋近于零,意味着坡度消失、走不动了。
- 走不动的位置就是损失函数的最低点,此时得到的 k 和 b 正是线性回归要找的斜率与截距。
- 回看整条链路:数据关联 → 直线模型 → 误差标准 → 损失函数 → 偏导 → 梯度 → 反向下山,每一步都在为下一步准备输入。
迭代持续进行,参数不断被推向低处。当两个偏导数逐渐变为零的时候,意味着在当前点上,两个方向的坡度都已经消失——你走不动了。
走不动的地方,就是这张损失函数曲面的最低位置。此时手上这组 k 和 b,正是从头开始就一直想要的那条直线的斜率和截距。
回头看整条推导链:从数据之间的关联出发,用一条直线建立模型,用误差定义优劣,把优劣组织成以参数为自变量的损失函数,再用偏导数求出每个参数方向上的坡度,组合成梯度,最后反向行走。
每一步单独看都不复杂,复杂的是它们之间的咬合关系:没有损失函数,偏导无处可求;没有偏导,梯度无从合成;没有梯度,下山没有方向。梯度下降之所以成立,是因为这条链的每一环都恰好是下一环的输入。
术语速查
按出现顺序排列。
- 过拟合Overfitting
- 模型把样本中的噪声也当成规律记住,在训练数据上表现极好、遇到新数据立刻失效。
- 线性回归Linear Regression
- 用一次函数 y = kx + b 拟合数据,通过确定斜率与截距得到最贴近数据的直线。
- MSE平均平方误差
- 每个样本的误差平方求和后除以样本数,值越小说明拟合越好,是梯度下降常用的损失。
- MAE平均绝对误差
- 对误差取绝对值再取平均,与 MSE 并列的另一种评价标准,对离群点更宽容。
- 损失函数Loss Function
- 以模型参数为自变量、以误差为函数值的函数,其最小值对应最优参数。
- 导数Derivative
- 一元函数在某点切线的斜率,符号指示上升方向,绝对值可度量为步长。
- 偏导数Partial Derivative
- 多元函数中固定其余变量、只对某一个变量求导,得到该方向上的变化率。
- 梯度Gradient
- 由各方向偏导数组成的向量,指向函数值增长最快的方向,位于参数平面上。
- 学习率Learning Rate / α
- 乘在偏导数前控制步长大小的系数,过大会震荡发散,过小则收敛缓慢。
- 局部最优Local Optimum
- 坡度归零但并非全局最低的位置,算法可能误判为终点而提前停止。