☰
机器学习数学基础:求导、梯度下降与反向传播实战
2026/10/2 10:46:16 网站建设 项目流程

机器学习中的数学:求导技术

做机器学习这些年,我越来越觉得一个事实常被新手忽略:机器学习本质上就是一门求导技术。模型学习的目标函数需要优化,优化方向来自梯度,而梯度就是导数。你跑PyTorch时调一行loss.backward(),背后发生的全部事情就是链式法则求导。理解这一层,你会看透很多上层概念——梯度下降为什么要有学习率,网络为什么越深越难训练,激活函数为什么那样选。我把这一套东西从数学原理到实战踩坑完整梳理了一遍。

这篇文章不打算写成教材,而是尽量以我实际调模型的经验来讲,目标读者是已经入门机器学习、但数学基础不是那么牢的同学。读完你应该能搞清楚:求导在机器学习里到底做了什么,导数在参数更新中怎么起作用,以及当你自己动手从零实现一个训练循环时,这些数学工具是如何一环一环衔接起来的。

1. 求导是机器学习的“方向盘”:从损失函数到参数更新

1.1 学习本质上是优化,优化靠的是梯度

机器学习训练模型的过程,说白了就是调参。你有一个模型,模型里有一堆参数,训练数据进来,模型给出预测,预测和真实答案之间有差距——这个差距用一个函数来衡量,叫损失函数。训练的全部任务就是不断调整参数,让这个损失函数的值尽可能小。

那就引出一个问题:怎么调整参数才靠谱?如果参数是10个,你可以瞎试,如果参数是1亿个呢?你不可能遍历整个参数空间。这里有且只有一个系统性的办法:算导数。

导数的几何意义是函数在某一点的瞬时变化率,而在这件事上,它告诉你的就是——当前这个参数,往哪个方向调,损失会下降得最快。多维情况下,所有偏导组成的向量叫梯度。梯度方向就是函数增长最快的方向,那我的参数更新自然要往反方向走。

w_new = w_old - learning_rate * gradient

这个公式是所有一阶优化算法(SGD、Adam、RMSProp等)的共同底座。搞懂了梯度,你就搞懂了优化器里最核心的东西。

1.2 从标量到矩阵:机器学习中的求导对象

很多人卡在求导这个环节,其实是因为机器学习的求导对象比高等数学里的典型例题复杂太多了。高数课上你求的是 y = f(x),x和y都是标量。机器学习里,虽然最终的loss是一个标量,但中间过程全是矩阵和向量。

  • 输入 x 可能是一个向量(甚至是一个 batch 的矩阵)
  • 权重 W 是一个矩阵
  • 预测值是向量
  • 损失是标量

这种情况下,求导不再是简单的 d y / d x,而是涉及矩阵对矩阵求导、Jacobian矩阵、维度匹配等问题。很多新手在这里栽跟头,从数学到代码对不上号。

我的经验是,入门阶段不要一上来就啃矩阵微积分的教材,先理解一个核心原则就够了:梯度必须和参数的形状保持一致。后面我会详细讲这一点,它帮我解决了很多实际问题。

1.3 为什么反向传播是神经网络的核心引擎

深度学习里的反向传播算法,本质上就是链式法则的工程化实现。链式法则你肯定学过:如果 y = f(u),u = g(x),那么 d y / d x = d y / d u · d u / d x。

在神经网络里,这个链会长得多。一个层叠一个层,损失对最后一层参数的导数,要先算损失对输出的导数,再算输出对中间结果的导数,逐层往回推。这正好对应了“反向”传播这个名字:误差信号从输出层开始,一层一层向前传播,每一层根据链式法则算出自己那部分梯度贡献。

值得注意的一个经验是:手推一遍反向传播,比自己看十遍教程都管用。我自己最开始学深度学习时,就是照着《神经网络与深度学习》里的公式,手动推了一个两层的网络,用Python纯手写实现了一遍前向和反向,之后对backward的理解就彻底不同了。

2. 四个必须掌握的求导工具和它们的实战含义

2.1 求导工具一:基础求导法则,这是地基中的地基

首先复习一下机器学习里最常用的几个基础求导公式。别小看这一部分,我面试过不少人,算法题刷得飞起,但问一个对 logistic 损失函数求导就磕磕绊绊——这些都是最基础但又最常用的。

  • 常数求导:对常数求导结果为0。
  • 幂函数求导:d(x^n)/dx = n x^(n-1)。机器学习里大量出现平方项,求导后系数对半。
  • 指数与对数:d(e^x)/dx = e^x;d(ln x)/dx = 1/x。softmax、交叉熵损失里全是这些。
  • 四则运算法则:乘积法则(uv)' = u'v + uv',商法则(u/v)' = (u'v - uv') / v^2。
  • 链式法则:这个最核心,前面已经提过,后面会反复用到。

这些法则本身不难,难的是面对一个复杂的复合函数时,能不能快速判断出用哪个法则、拆解顺序如何。我的一个土办法是:“由外到内,一层层剥洋葱”。先看最外层是什么函数结构,然后逐步往里。

2.2 求导工具二:偏导数和梯度,从单变量到高维

当函数有多个自变量时,我们需要偏导数。偏导数的计算方式和普通导数几乎一样,区别仅仅是:对某个变量求偏导时,把其他所有变量当常数处理。

举个例子,假设损失函数 L(w1, w2) = (w1 - 3)^2 + 2*(w2 + 1)^2。对 w1 求偏导:把 w2 当常数,得到 ∂L/∂w1 = 2*(w1 - 3);对 w2 求偏导:把 w1 当常数,得到 ∂L/∂w2 = 4*(w2 + 1)。

梯度就是把所有偏导拼成一个向量:∇L = (∂L/∂w1, ∂L/∂w2)。在参数更新时,我们对每个参数减去学习率乘以对应的偏导数值。这里有一个关键经验:梯度的维度必须与参数的维度完全一致,这是写优化更新代码时最容易出错的地方。

2.3 求导工具三:链式法则,深度学习的骨架

链式法则在机器学习里的标准化应用场景:多层网络中的误差反向传播。我来写一个具体例子。

假设有一个2层网络(省略偏置项):

  • 输入 x
  • 第一层:h = W1 @ x(线性变换)+ relu(激活)
  • 第二层输出:ŷ = W2 @ h(线性变换)
  • 损失 L = (ŷ - y)^2(MSE)

损失对 W2 求导: ∂L/∂W2 = 2*(ŷ - y) * ∂ŷ/∂W2 = 2*(ŷ - y) * h^T

损失对 W1 求导: ∂L/∂W1 = 2*(ŷ - y) * W2 * relu'(h) * x^T

你会看到,∂L/∂W1 的表达式里依赖两个关键的中间量:∂L/∂ŷ(即 2*(ŷ-y))以及第二层权重 W2。这正是反向传播做的事情——先算出输出层误差,再乘W2把它传回到上一层。

在我实际调试的过程中,最有效的验证方式是维度检查:W1 的梯度维度一定是和 W1 一模一样。如果哪一行算出来的梯度维度对不上,基本就是公式推错了。

2.4 求导工具四:矩阵求导与维度分析

接下来是矩阵求导。严格来说这是一个很深的数学话题,但在机器学习工程实践里,真正需要用到的高频结论其实非常有限。掌握几个结论,配合维度分析,基本能应付绝大部分场景。

四个高频结论(这里假设 x、y、W 形状合理):

  • d(Wx)/dW 的结果维度是 x 的维度(严格说是关于W的Jacobian,但在工程推导中我们关注梯度形状)。
  • d(x^T W x)/dW = x x^T,二次型的导数,线性回归里极常见。
  • d(||Wx - y||^2)/dW = 2*(Wx - y) @ x^T,最小二乘的梯度。
  • 向量对向量求导得到Jacobian矩阵,但在自动微分框架中这个矩阵不直接显式存在,而是以矢量Jacobian乘积(VJP)的形式传递给上一层。

我强烈建议你在推导矩阵梯度的每一步都问自己:“形状对不对?”。例如 W 的形状是 (3,4),那么梯度也必须是 (3,4)。如果算出来是 (4,3),大概率少做了一个转置。这个维度验证法几乎能排查掉所有手推矩阵求导的错。

3. 实操:手写梯度下降训练线性回归

3.1 问题的数学定义

我们现在亲手实现一个最经典也最容易理解的任务:用梯度下降训练线性回归模型。

线性回归的模型表达式是: ŷ = w^T x + b

损失函数选择一个相对简单的均方误差(MSE): L(w, b) = (1/N) * Σ (ŷ_i - y_i)^2

在这里,N 是样本数量,ŷ_i 是第 i 个样本的预测值,y_i 是真实值。

我们要求的目标:计算出 ∂L/∂w 和 ∂L/∂b 的解析形式,并在代码中用梯度下降更新参数。

3.2 推导梯度表达式

我们先对单个样本推导,然后取平均。

设单个样本的损失为: L_i = (w^T x_i + b - y_i)^2

记误差项 e_i = w^T x_i + b - y_i = ŷ_i - y_i。

对 w 求偏导: ∂L_i/∂w = 2 * e_i * x_i

对 b 求偏导: ∂L_i/∂b = 2 * e_i

所以整个训练集上的梯度是: ∂L/∂w = (2/N) * Σ e_i * x_i ∂L/∂b = (2/N) * Σ e_i

这两个公式其实非常好记忆:梯度就是残差乘以输入(或1),再取平均。

3.3 从零开始写训练代码

我们来一步一步写代码。这里我用纯NumPy实现,不用任何自动微分框架,以便看清楚每个数学公式如何转化为代码。我按照“初始化参数 → 前向计算 → 算loss → 算梯度 → 更新参数”的流程来写。

import numpy as np # 生成模拟数据 np.random.seed(42) X = np.linspace(0, 10, 100).reshape(-1, 1) # 100个样本,1个特征 true_w = 2.5 true_b = 1.0 y = true_w * X.squeeze() + true_b + np.random.randn(100) * 0.5 # 初始化参数 w = np.random.randn() # 随机初始化 b = np.random.randn() learning_rate = 0.01 epochs = 100 loss_history = [] for epoch in range(epochs): # 前向计算 y_pred = w * X.squeeze() + b # 计算损失 loss = np.mean((y_pred - y) ** 2) loss_history.append(loss) # 计算梯度(这是我们的核心公式) error = y_pred - y # 残差,shape = (100,) grad_w = 2.0 / len(X) * np.sum(error * X.squeeze()) grad_b = 2.0 / len(X) * np.sum(error) # 更新参数 w -= learning_rate * grad_w b -= learning_rate * grad_b if epoch % 20 == 0: print(f"Epoch {epoch:3d}, Loss: {loss:.4f}, w: {w:.3f}, b: {b:.3f}") print(f"最终结果: w = {w:.3f}, b = {b:.3f} (真实值: w=2.5, b=1.0)")

跑完这段代码,你最后得到的估计值应该非常接近真实参数 w=2.5, b=1.0。这里需要注意一下:我这里用了全部样本的梯度来更新,也就是批量梯度下降。如果你样本量非常大,这样做每次迭代计算成本很高,这时候就要换成小批量或随机版本。

3.4 向量化版本的效率提升

上面的代码是逐标量更新的可读性版本。实际工程里,我们更喜欢写成矩阵形式,既简洁又高效。同样是这个线性回归,向量化的写法如下。

# 把X转换成包含偏置列的设计矩阵 X_b = np.c_[np.ones((len(X), 1)), X] # 第0列全1对应bias项 # 参数向量 theta = np.array([b, w]) epochs = 1000 learning_rate = 0.01 for epoch in range(epochs): y_pred = X_b @ theta # (100,2) @ (2,) = (100,) error = y_pred - y gradient = (2.0 / len(X)) * X_b.T @ error # (2,) 对应两个参数的梯度 theta -= learning_rate * gradient print(f"向量化结果: theta = {theta} (对应 [b, w])")

这个版本把偏置 b 并进了权重向量 theta 里,逻辑更紧凑。用到了我们前面矩阵求导的结论:∂L/∂theta = (2/N) * X_b^T @ error。你注意看,这个矩阵乘法的顺序和维度关系:X_b.T 是 (2,100),@ error 是 (100,),结果正好是 (2,)。如果你不小心写反了顺序或者忘了转置,梯度形状立刻就错了。这就是前面说的维度检查法在实际编程中的应用。

4. 损失函数里的高级求导技巧:从MSE到交叉熵

4.1 MSE的求导与优化轨迹

上面的线性回归用了MSE,我们来从数学优化角度再深挖一层,看一下梯度的几何含义。

MSE损失函数是参数 w 的一个二次函数。二次函数的性质是:只有一个全局最小值,梯度方向始终指向这个最优点(或者其反方向)。这意味着,使用梯度下降求解标准线性回归时,只要学习率选择得当,无论从哪里初始化,最终大概率都能收敛到全局最优。

我在实际跑这个实验的时候,专门留意过损失的变化曲线:前几十轮损失下降很快,过了某个点之后,下降速度明显放缓。这背后的数学解释是:二次函数的梯度大小与距离最优点的距离成正比,离最优点越近,梯度越小,参数更新量也越小。所以看到损失下降变慢,不一定是学习率有问题,可能只是已经接近最优点附近了。

这里有一个实操中的常见困惑:既然线性回归的MSE有解析解(正规方程),为什么还要用梯度下降?答案很简单——当特征维度很大时,求解 (X^T X) 的逆矩阵是 O(n^3) 复杂度,而梯度下降每一步只做矩阵乘法,是 O(n^2) 复杂度。对于上百万个特征的高维问题,迭代法比解析法快得多。这也是求导技术真正发挥工程价值的地方。

4.2 交叉熵损失与Softmax组合求导的化简技巧

接下来是分类问题里最常用、也最容易被卡住的求导:Softmax + 交叉熵损失。

Softmax函数定义:给定一个得分向量 z = (z1, z2, ..., zK),第 k 类的概率为:

p_k = e^(z_k) / Σ_j e^(z_j)

交叉熵损失(针对单样本,真实标签为 y): L = -log(p_y)

这里的 p_y 是真实类别对应的 softmax概率。

我们现在回答一个灵魂问题:∂L / ∂z_i 是什么?

很多新手直接对交叉熵里的 log 求导,然后又对 softmax 的分式求导,过程中把所有情况都列出来,最后绕得晕头转向。其实有一个非常优雅的结论:

  • 当 i ≠ y 时:∂L / ∂z_i = p_i
  • 当 i = y 时:∂L / ∂z_i = p_y - 1

两个式子合并: ∂L / ∂z_i = p_i - 1(i == y)

其中 1(i == y) 是指示函数,当 i 等于真实类别时为1,否则为0。

这个公式简洁得不可思议,而且在代码实现时几乎零成本。PyTorch里的nn.CrossEntropyLoss()之所以要求你输入原始logits(未经过softmax的得分),就是因为可以在内部高效地算这个梯度,省去中间变量。你不需要自己把softmax结果传进去——传进去反而算的是错误的梯度,因为框架内部已经帮你做了组合操作。

这个推导过程我强烈建议手动推一遍。我的经验是:先对 softmax 的一般项求偏导,注意两种情况(i = j 和 i ≠ j)要分开处理,然后借助 Σ_j p_j = 1 的性质合并同类项,最后能化简出那个优雅的结果。推完你会有一种“瞬间通透了”的感觉。

4.3 激活函数的求导选择

神经网络中激活函数的求导特性,直接影响了训练能否顺利进行。我用一张表总结常见激活函数及其导数:

激活函数函数形式导数形式梯度特性
Sigmoidσ(x) = 1 / (1 + e^(-x))σ(x)(1 - σ(x))x较大或较小时导数接近0,容易导致梯度消失
Tanhtanh(x) = (e^x - e^(-x)) / (e^x + e^(-x))1 - tanh^2(x)输出零中心,但两端同样饱和
ReLUmax(0, x)x > 0为1,x <= 0为0正区间梯度恒为1,缓解梯度消失但可能造成神经元死亡
Leaky ReLUmax(αx, x),α通常0.01x > 0为1,否则为α在负区间保留小梯度,避免神经元完全死亡

为什么现在CNN、Transformer里ReLU系激活函数大行其道?从求导的角度看非常清楚:它的梯度在正区间恒为1,不会随网络加深而指数减小。Sigmoid在深层网络中之所以不好用,是因为其导数的最大值只有0.25,链式法则乘两三层之后,梯度就衰减到可以忽略不计。这就是从导数视角看待网络设计的经典例子。

5. 调试技巧与常见求导陷阱

5.1 用数值微分校验你的梯度

如果有一天你决定自己实现一个自定义网络层,或者手写一个复杂的损失函数,求导出现错误几乎是必然的。这时候最有效的工具就是数值梯度校验。

数值微分的原理是导数的定义式: f'(x) ≈ (f(x + ε) - f(x - ε)) / (2ε)

注意用中心差分,比单侧差分精度高不少。ε一般取1e-5到1e-6比较合适。然后用相对误差来对比数值梯度和你的解析梯度:

相对误差 = |解析梯度 - 数值梯度| / (|解析梯度| + |数值梯度|)

我给的判断经验:

  • 小于1e-7:完美,基本可以确认梯度正确。
  • 在1e-4左右:可能有一点点小问题,检查是否漏了除以N。
  • 大于1e-2:梯度绝对算错了,老老实实重新推导。

这个方法救过我太多次。尤其是在实现矩阵运算时,一个转置的失误是肉眼很难发现的,但数值校验一试就露馅了。

5.2 学习率与梯度的互动关系

梯度下降里学习率的选择,本质上是对梯度这个信号的信任程度问题。学习率太大,你会一步跨出太远——参数更新过度,损失反而变大甚至发散;学习率太小,每次更新都像乌龟爬坡——训练效率极低,浪费计算资源。

我在前面对线性回归的例子中,把学习率设为0.01。你跑的时候可以试一下把它改成1.0:大概率你会看到 loss 不降反升,最后变成 NaN。改成0.000001:loss 下降得你怀疑人生,100轮之后还在原地踏步。

这是我对新手讲课时最常演示的“坑”。普通梯度下降(非自适应优化器)对学习率尤其敏感,所以实际工程中我们一般用Adam这种带有适应性缩放效果的优化器来降低对学习率的敏感度。即便如此,精确理解梯度信号方向与学习率之间的博弈,对调试仍然非常重要。

有一个经验:当我看到 loss 剧烈抖动或者变成 NaN,我会先把学习率除以10试试。如果还是不行,再去查数据里有没有异常值。

5.3 维度不匹配问题的快速诊断法

在自动微分框架里,如果你手写backward时维度过不了,最常见的报错是矩阵乘法形状不匹配。但要警觉的是:有时候形状恰好匹配,但数学含义是错的,这种错误不会被框架报出来,只会让损失不下降或者收敛到错误结果。

我个人常用一个“铅笔加纸张”的排查思路:

  1. 写下从输入到损失的前向链条中每个变量的形状。
  2. 对某个中间的矩阵 W,根据链式法则推算出梯度应当由哪些量相乘得到。
  3. 检查最终梯度形状是否和 W 完全一致。
  4. 如果不一致,看是缺了转置还是漏了一个矩阵。

这四个步骤基本能定位绝大多数梯度维度问题。在我带团队的几年里,我要求每位新人也必须掌握这种“形状推导法”——它可以帮你快速建立对模型内部数据流的敏感度,这种敏感度在调试时远远比在网上搜一个“怎么让loss下降”的帖子有用。

5.4 自动微分框架下的“伪求导”:需要留心的数学简化

使用 PyTorch 或 TensorFlow 时,你通常不会直接手写梯度公式,而是调用框架的自动微分功能。但框架的自动微分并不是魔法,它背后做的是你对链式法则的工程解析——只是把这些运算法则预先编码在计算图里。

这里大家容易忽略的一个点是:框架自动微分会保留计算图,所以反向传播所需内存取决于前向计算量。如果你的模型用了几十个中间层,那么反向传播时就需要保存这些中间层的激活值,显存占用会显著增加。

从这个角度看,理解求导能帮你从底层优化显存:比如某些框架提供“梯度检查点”技术,通过重算而非保存的方式节省显存,这就是在“前向时间”和“反向内存”之间做均衡,背后的原理还是链式法则的计算路径。

另外我还要提一个实践细节:当你使用自动微分框架时,如果在自定义Layer里手写了某个操作的forward,但没有正确实现backward,训练出来的模型可能出现梯度错误但不会崩溃。此时数值梯度校验依旧是找出问题的黄金手段。我见过太多模型精度差的问题,最后定位到一个新算子求导bug上。

6. 从求导技术延伸:二阶导数与优化算法

6.1 二阶导数的直觉理解

一阶导数告诉你“该往哪个方向走”,二阶导数告诉你“这条路是不是越来越陡”。在优化中,二阶导数(更为常见的是Hessian矩阵)体现了损失函数局部的 curvature(曲率)。

怎么理解曲率对梯度下降的影响?我用一个简化的例子:假设目标函数是 f(w) = w^2(曲率2),在 w=10 处梯度是20,学习率0.1的话,更新量是2,一步跳到 w=8。而如果目标函数是 f(w) = 0.1*w^2(曲率0.2),同样 w=10 处梯度是2,更新量0.2,挪到 w=9.8——同样在距离最优点为10的位置,需要的步数差很多。曲率大的地方梯度变化快,你用固定的步长容易被“弹来弹去”;曲率小的地方梯度变化慢,你又会走得很“缓慢”。

这种差异正是牛顿法思想的核心:它利用二阶导数来调整每一步的步长,让更新在曲率大的方向迈小步,在曲率小的方向迈大步。不过,计算整个Hessian矩阵的代价通常非常高昂,每层参数有百万级时更是不现实。

6.2 深度学习优化器如何变相利用二阶信息

深度学习再怎么用一阶优化器为主?现代优化器比如Adam,其实在某种程度上“伪二阶”地利用了梯度信息来近似曲率。

Adam会分别维护两个指数移动平均:一阶矩 m(梯度的平均)和二阶矩 v(梯度平方的平均)。它的参数更新不是直接用当前梯度,而是用 m 除以 sqrt(v) 来归一化:

m_t = β1 * m_(t-1) + (1 - β1) * g_t v_t = β2 * v_(t-1) + (1 - β2) * (g_t)^2 θ_t = θ_(t-1) - lr * m_t / (sqrt(v_t) + ε)

这里除去一个小常数 ε,核心的 m / sqrt(v) 表示:当梯度持续同向时,m 增大,更新迈大步;当梯度始终来回震荡时,v 相对更大,更新迈小步。它类似于利用梯度的方差信息来感知局部地形曲率。每步没有真正计算Hessian,却能取得比普通SGD好得多的收敛稳定性。

我对初学者的建议是:用Adam作为默认优化器,然后把学习率先设为1e-3,看损失曲线的形状再去调。当你能把一阶导、二阶导、学习率之间的博弈用直觉串起来时,调参就不再是试运气了。

6.3 梯度消失与梯度爆炸:从导数视角看深层网络

提到梯度,就不得不提深度学习中臭名昭著的梯度消失和梯度爆炸。这两个问题的根源,都在于反向传播的链式法则会把每一层的导数相乘。

假如一个10层网络每层的梯度缩放因子是0.5,乘10次之后梯度缩小到原来的0.5^10 ≈ 0.000976倍,前几层的权重几乎得不到有效更新,训练等于停滞。这就是梯度消失。反过来,如果每层缩放因子是1.5,乘10次之后就是1.5^10 ≈ 57.7倍,梯度爆掉,参数更新直接飞出去。

历史上深度学习经历过很长一段“寒冬”,就是因为网络稍微加深一点就训练不动。直到ReLU激活函数、残差连接、合理的初始化策略相继出现,从导数链条上切断了持续乘积导致的爆炸或消失问题,深层网络才真正变得可训练。

从这个角度你就能理解残差网络(ResNet)的核心思路了:它让当前层输出 F(x) + x,从数学上等价于在梯度传播路径上添加了一个恒等跳跃,使得梯度在反向传播时可以“跳过”那些不利于传递的层,直达浅层。这就是用架构设计来调控导数传播的经典案例。

7. 写在最后的经验分享

干这行越久,越觉得数学基础不是门槛,而是天花板。求导看起来是最简单的数学工具,但它在机器学习中贯穿始终:线性回归的闭式解、逻辑回归的梯度推导、神经网络的反向传播、优化器的设计原理,全部长在导数这棵树上。

最后再分享几个我个人的习惯,希望能帮到你。

一是遇到不熟悉的新模型,不要急着往上堆框架代码,先手动把它的小规模版本用NumPy写一遍,把梯度推导和数值校验做一遍。这步看着费时间,但实际是最高效的学习路径。

二是尽量把公式推到底,不要停在“知道大概”。对Softmax交叉熵这种高频组合,把推导过程完整的在手边推一遍,之后用框架时会少踩很多隐藏的坑。

三是把梯度当成一个可以做可视化诊断的信号。如果你工作的项目里梯度分布异常(比如某一层梯度经常为NaN或为全零),别只看loss,试着把每一层的梯度和参数更新量打出来观察,往往很快就能定位问题层。

求导技术只是一个开始,但这是一个值得投入的开始。把这块地基打牢了,以后再接触强化学习里的策略梯度、生成模型里的重参数技巧这些高级话题时,你会发现自己能更快抓住本质——因为它们骨子里,还是那一套链式法则。

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

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

立即咨询