引言:几乎所有机器学习模型——线性回归、逻辑回归、神经网络——它们"学习"的本质,都是最小化一个损失函数。而最通用的最小化方法,就是梯度下降。理解了它,你就理解了"机器是怎么学的"。
在这里插入图片描述

一、梯度方向的直觉

想象你站在山坡上想最快下山,但只能看到脚下的坡度。梯度就是函数上升最快的方向,那么它的反方向就是下降最快的方向。在一维损失曲线上,梯度就是当前点切线的斜率:坡越陡,梯度的绝对值越大。
在这里插入图片描述

二、沿梯度反方向更新

既然反方向是下坡,那么我们每一步就朝反方向迈:

x = x − 学习率 × 梯度

反复迭代,损失越来越小,最终滚到谷底(最小值)。判断收敛的条件很简单:当梯度≈0 时,脚下变平了,说明已经到了极小值,停止迭代。

三、学习率太大 / 太小的影响

学习率(步长)是这把双刃剑:

  • 太大:一步迈过谷底,跑到对面山壁,甚至越跳越高,导致发散——损失不降反升。
  • 太小:每步只挪一点点,要很多轮才到底,收敛很慢

工程上常用衰减学习率,或者 Adam 这类自适应优化器,既快又稳。
在这里插入图片描述

四、完整 C++ 实现(带注释)

下面是核心迭代逻辑,损失函数取碗状曲线,f_prime 为其导数(梯度):

// 梯度下降核心迭代
// x0: 初始点  lr: 学习率(步长)
double gradient_descent(double x0, double lr) {
    double x = x0;                       // 从某个初始点出发
    for (int it = 0; it < ITERS; it++) {
        double g = f_prime(x);           // 当前点的梯度(斜率)
        x = x - lr * g;                  // 沿梯度反方向走一步
        if (fabs(g) < eps) break;        // 梯度≈0 → 到极小值
    }
    return x;
}

// 示例:损失 f(x) = (x - min)^2,其导数 f'(x) = 2 * (x - min)
double f_prime(double x) {
    const double MIN = 0.0;              // 谷底位置(损失最小处)
    return 2.0 * (x - MIN);              // 梯度
}

时间复杂度约为 O(迭代数 × 单次梯度成本),空间复杂度 O(参数个数)。

五、批量 / 随机 / 小批量

工程上按每次用多少样本算梯度,分为:**批量梯度下降(BGD)**用全部样本、**随机梯度下降(SGD)**每次一个样本、**小批量(Mini-batch)**取一小批,三者在速度与稳定性间取舍。
在这里插入图片描述

小结

梯度下降的核心就三句话:算梯度、沿反方向走一步、梯度≈0 时停。难点在于学习率的调节,以及非凸函数可能卡在局部极小或鞍点。码路星球(我不慌—成长杂货铺:https://wobuhuang.com)上有这道算法的可视化:蓝色损失曲线、橙色小球、紫色切线,一步步看小球滚到谷底,坡越缓步子越小。

梯度下降 / 机器学习 / 最优化 / 学习率 / 损失函数 / C++ / 算法可视化 / 深度学习入门

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐