AI数学基石:从导数原理到PyTorch梯度实战,打通模型优化核心 📅 发布时间:2026/8/22 7:01:16 👁 浏览次数: 1. 项目概述为什么学导数比学Python语法更重要如果你刚开始接触人工智能尤其是机器学习或深度学习大概率会一头扎进TensorFlow、PyTorch的教程里对着几行代码反复调试。但很快你就会遇到一堵墙模型不收敛、梯度爆炸、损失函数居高不下。翻看解决方案满眼都是“学习率衰减”、“梯度裁剪”、“优化器选择”。这些概念的背后都站着一个共同的数学基石——导数。很多人把“人工智能数学基础”当成一门理论课觉得会调包就行。但我的经验是导数这东西你理解到什么深度直接决定了你调试模型的效率上限。它不仅仅是反向传播里那个“链式法则”的符号更是你理解模型如何“学习”的钥匙。比如为什么用Sigmoid函数会有梯度消失为什么ReLU能缓解这个问题答案都藏在它们的导数图像里。这个内容就是帮你把这把钥匙造出来。我们不搞复杂的数学证明而是聚焦于两件事第一从几何和物理意义上真正理解导数是什么第二用Python把它“算出来”并“画出来”把抽象概念变成屏幕上的曲线和数字。当你看到改变一个参数切线斜率如何实时变化时那种直观感受是看十遍公式都换不来的。适合谁呢所有打算认真做AI而不是仅仅跑通Demo的朋友。无论你是学生、转行者还是已经入门想夯实基础的开发者这里从零开始用代码驱动理解目标只有一个让你下次看到gradient这个词时脑子里浮现的不再是恐惧而是一幅清晰的动态图景。2. 核心概念拆解导数不是魔术是变化率的精确描述2.1 从平均变化率到瞬时变化率微积分的核心思想我们从一个最实际的例子开始监控服务器CPU使用率。假设你有一份每秒采样一次的数据想判断在某一瞬间比如第5秒CPU使用率是在飙升、下降还是平稳。笨办法是看第5秒和第6秒的数据算一下差值。但这代表的是第5秒到第6秒这一整秒内的平均变化情况。如果CPU在第5.0秒瞬间被一个任务打满又在第5.1秒降下来这个“平均变化率”就完全错过了关键瞬间。导数的思路就精巧在这里它想知道的是“瞬时”的变化。数学上的做法是先看第5秒到第6秒的平均变化再把时间间隔不断缩小看第5秒到第5.1秒再到第5.01秒第5.001秒……当这个时间间隔无限趋近于0时平均变化率所逼近的那个极限值就是第5秒这一时刻的瞬时变化率也就是导数。用公式表示对于函数y f(x)在点x0处的导数f(x0)定义为f(x0) lim (Δx - 0) [f(x0Δx) - f(x0)] / Δx这个式子就是上面思想的数学翻译。lim表示极限Δx就是那个不断缩小的间隔。注意这里很容易混淆“导数”和“微分”。简单说导数是一个数是特定点的瞬时变化率斜率。而微分dy f(x)dx是一个函数描述的是当x有微小变化dx时y的近似变化量dy。在AI的上下文中我们绝大多数时候关心的是导数梯度。2.2 几何意义切线斜率一切优化的可视化基础导数的几何意义极其重要它是我们可视化优化过程的基础。在函数图像上导数f(x0)就是曲线在点(x0, f(x0))处切线的斜率。为什么这一点对AI至关重要训练神经网络的本质就是不断调整参数让损失函数的值降到最低。你可以把损失函数想象成一片崎岖的山地我们的位置就是当前参数值损失值就是海拔。我们的目标是走到最低的谷底全局最小或局部最小。梯度多维导数的方向就指向当前位置最陡峭的上山方向。那么为了下山我们自然要往它的反方向走。这就是梯度下降法的根本原理。如果你不能直观理解“导数即斜率”就很难理解为什么优化器总是在沿着梯度反方向更新参数。我用一个简单的二次函数f(x) x^2来演示。在x1处函数值为1。它的导数f(x) 2x所以在x1处导数为2。这意味着在(1,1)这个点切线是向上倾斜的斜率为正并且比较陡。如果我们想最小化f(x)就应该向x减小的方向左移动因为那是下山的方向。2.3 物理意义从速度到AI模型参数更新的“速度”从物理角度看如果你把x看作时间f(x)看作位移那么导数f(x)就是瞬时速度。如果f(x)是速度那么导数就是加速度。在AI中这个类比非常有用。我们把损失函数关于某个参数的导数理解为“改变这个参数时损失值变化的敏感度或速度”。导数绝对值很大正或负说明参数稍有变动损失就会剧烈变化。这个参数目前处于一个“关键”或“不稳定”的状态。导数接近0说明参数在当前点对损失的影响很小可能接近一个局部最优点平地也可能是遇到了梯度消失的问题。在高级优化器如Adam中它不仅仅看当前的导数梯度还会计算梯度平方的指数移动平均这有点像同时考虑“速度”和“加速度”从而能更稳定、更快地收敛。3. 基础运算规则手算导数的“语法手册”在真正用Python计算之前我们必须掌握一些基础函数的导数公式和运算法则。这就像学编程先学语法是后续一切自动微分和推导的基础。3.1 基本初等函数的导数公式这些是构建复杂函数的基本砖块必须熟记。函数导数公式备注与AI中的常见场景f(x) c(常数)f(x) 0常数的变化率为零。在神经网络中偏置项bias的初始化常数为0但其梯度在训练中会变化。f(x) x^nf(x) n*x^(n-1)幂法则。非常核心线性层Wx b中权重的梯度计算依赖于此。f(x) e^xf(x) e^x指数函数以其导数等于自身而独特。是Sigmoid、Softmax等激活函数的组成部分。f(x) ln(x)f(x) 1/x自然对数。常用于交叉熵损失函数中其导数形式简单。f(x) sin(x)f(x) cos(x)周期性函数。在某些位置编码如Transformer或特定网络结构中会出现。f(x) cos(x)f(x) -sin(x)同上。f(x) a^xf(x) a^x * ln(a)一般指数函数。f(x) log_a(x)f(x) 1/(x * ln(a))一般对数函数。3.2 函数组合的运算法则链式法则的铺垫复杂函数都是由基本函数通过加、减、乘、除和复合组合而成的。掌握它们的求导法则是理解链式法则的前提。加减法则[u(x) ± v(x)] u(x) ± v(x)实操心得这是最直接的。在神经网络中一个神经元的输入通常是多个输入的加权和其求导就是各个分量求导再相加。乘法法则[u(x) * v(x)] u(x)*v(x) u(x)*v(x)理解不是简单地把导数相乘可以类比为“第一个函数的变化率乘以第二个函数的当前值加上第一个函数的当前值乘以第二个函数的变化率”。示例求f(x) x^2 * sin(x)的导数。令ux^2,vsin(x)则u2x,vcos(x)。所以f(x) 2x*sin(x) x^2*cos(x)。除法法则[u(x) / v(x)] [u(x)*v(x) - u(x)*v(x)] / [v(x)]^2记忆口诀“上导下不导减去上不导下导除以分母的平方”。注意事项分母v(x)不能为0否则函数本身无定义更谈不上求导。3.3 链式法则神经网络反向传播的灵魂这是整个深度学习的数学核心必须彻底理解。公式如果y f(u) 而u g(x)那么y关于x的导数为dy/dx (dy/du) * (du/dx)。 可以推广到更多层dy/dx (dy/du_n) * (du_n/du_{n-1}) * ... * (du_1/dx)。为什么叫“链式”因为求导过程像解开一条链条从外到内一层一层地乘起来。AI中的核心地位神经网络就是一系列函数的嵌套。输入x经过线性层z1 W1*x b1、激活函数a1 σ(z1)、再到下一层……最终得到输出y。计算损失L对第一层权重W1的梯度∂L/∂W1就必须通过链式法则将梯度从损失L一层层反向传播回来∂L/∂W1 (∂L/∂y) * (∂y/∂a_n) * ... * (∂a_1/∂z_1) * (∂z_1/∂W_1)。这个过程就是反向传播。一个具体例子计算y sin(x^2)在x√(π/2)处的导数。分解令u x^2则y sin(u)。分别求导du/dx 2xdy/du cos(u)。链式相乘dy/dx cos(u) * 2x cos(x^2) * 2x。代入求值当x √(π/2)x^2 π/2cos(π/2) 0。所以dy/dx 0 * 2*√(π/2) 0。 这意味着在该点函数sin(x^2)的切线是水平的。实操心得初学链式法则时一定要不怕麻烦把中间变量设出来一步步写清楚。熟练之后才能做到“心算”简单网络的梯度。这是调试自定义层或损失函数时不可或缺的能力。4. Python实现从数值近似到符号求导理论懂了现在让计算机来算。Python中有两种主流的求导方式数值微分和符号微分。它们各有用途。4.1 数值微分理解极限的直观实现数值微分直接使用导数的定义公式用一个极小的h如1e-5来代替理论上的极限。它不需要函数的数学表达式只需要能给出函数值即可适用于任何黑盒函数。前向差分公式f(x) ≈ [f(xh) - f(x)] / h这是最直观的实现但误差较大。中心差分公式更精确f(x) ≈ [f(xh) - f(x-h)] / (2h)它利用了x点左右两点的信息精度更高是实践中更常用的数值微分方法。import numpy as np def numerical_derivative(f, x, h1e-5): 使用中心差分法计算函数f在点x处的数值导数。 参数: f: 函数对象接受一个数值输入。 x: 求导点。 h: 微小的步长默认1e-5。 返回: 导数近似值。 return (f(x h) - f(x - h)) / (2 * h) # 测试求 f(x) x^2 在 x1 处的导数理论值为2。 def func(x): return x**2 x0 1.0 derivative_at_1 numerical_derivative(func, x0) print(ff(x)x^2 在 x{x0} 处的数值导数为: {derivative_at_1}) print(f与理论值2的绝对误差为: {abs(derivative_at_1 - 2)})注意事项与局限步长h的选择是门艺术h太大截断误差大公式不精确h太小舍入误差大计算机浮点数精度问题。通常1e-5到1e-7是一个比较安全的范围。计算成本高对于有N个参数的函数计算完整梯度需要O(N)次函数评估。在神经网络中参数动辄百万这是不可接受的。因此数值微分主要用于梯度检查——在实现反向传播后用数值微分的结果验证其正确性而不是用于训练。实操心得写梯度检查代码时比较数值梯度和解析梯度反向传播得到的梯度的相对误差通常1e-7以内的相对误差可以认为是正确的。可以使用公式relative_error |grad_numerical - grad_analytic| / (|grad_numerical| |grad_analytic| 1e-12)。4.2 符号微分用SymPy获得精确表达式符号微分基于数学规则进行公式推导得到导函数的精确表达式。import sympy as sp # 定义符号变量 x sp.symbols(x) # 定义函数表达式 f_expr x**2 * sp.sin(x) print(原函数 f(x) , f_expr) # 符号求导 f_prime_expr sp.diff(f_expr, x) print(导函数 f(x) , f_prime_expr) # 输出: 2*x*sin(x) x**2*cos(x) # 可以将符号表达式转换为可计算的函数 f_prime_func sp.lambdify(x, f_prime_expr, numpy) # 计算在具体点的值 import numpy as np x_val np.array([1.0, 2.0, 3.0]) print(在 x [1,2,3] 处的导数值:, f_prime_func(x_val))优点与局限优点得到精确的数学表达式便于分析和理解。局限对于非常复杂的函数组合如深度神经网络符号表达式会急剧膨胀导致表达式“爆炸”求导效率低下。因此现代深度学习框架PyTorch, TensorFlow使用的是下一节要讲的自动微分。4.3 自动微分深度学习框架的引擎自动微分Automatic Differentiation AD是数值微分和符号微分的巧妙结合。它不是通过极限近似也不是生成庞大的符号表达式而是在计算函数值的过程中同时记录所有的计算操作计算图并应用链式法则来累积梯度。原理简述前向模式假设有函数y f(x1, x2)。自动微分会引入“对某个输入变量的导数”作为伴随变量。例如要计算∂y/∂x1它设定ẋ1 1因为∂x1/∂x1 1ẋ2 0。然后按照计算顺序对每一个基本操作加、减、乘、sin等不仅计算函数值还计算其微分规则。最终伴随变量ẏ的值就是∂y/∂x1。PyTorch实战PyTorch使用反向模式自动微分这正是反向传播所需要的——一次性计算输出对所有输入的梯度。import torch # 1. 创建需要求梯度的张量。requires_gradTrue 告诉PyTorch跟踪其上的所有操作。 x torch.tensor([1.0, 2.0, 3.0], requires_gradTrue) # 2. 进行前向计算构建计算图。 y x**2 2*x 1 # 假设我们的损失是一个标量需要对y求和得到一个标量才能进行反向传播。 # 因为梯度只能对标量输出进行反向传播。 loss y.sum() # 3. 反向传播计算梯度。 loss.backward() # 4. 查看梯度。梯度会累积到叶子张量x的.grad属性中。 print(梯度 ∂loss/∂x:, x.grad) # 理论计算y x^22x1, dy/dx 2x2。 # 当 x[1,2,3]时理论梯度为 [4, 6, 8]。 # 因为 loss sum(y)所以 ∂loss/∂x ∂sum(y)/∂x [1,1,1] * dy/dx dy/dx。 # 所以 x.grad 应该等于 [4, 6, 8]。关键操作解析requires_gradTrue这是启动梯度跟踪的开关。只有设置了此属性的张量其参与的计算才会被记录。.backward()这是触发反向传播的指令。它从调用它的张量必须是一个标量开始沿着计算图反向传播计算所有requires_gradTrue的叶子张量的梯度。.grad梯度计算完成后会累积到叶子张量的这个属性中。with torch.no_grad():在这个上下文管理器中的计算不会被跟踪用于推理阶段或更新参数时节省内存和计算资源。.detach()从计算图中分离出一个张量新的张量不需要梯度。踩坑实录最常见的错误是“在非标量上调用.backward()”。反向传播的起点必须是一个标量单个数值因为梯度是向量对向量的导数雅可比矩阵但框架默认期望计算的是损失标量对参数的梯度。如果需要对向量输出求导需要在.backward()中传入一个gradient参数通常是一个全1的、与输出同形的张量这相当于先对输出向量求和得到一个标量再求导。5. 核心应用场景导数在AI中的四大关键作用理解了怎么算更要明白为什么算。导数在AI中无处不在以下是四个最核心的应用场景。5.1 梯度下降模型学习的导航仪梯度下降是所有优化算法的基石。其参数更新公式非常简单θ_new θ_old - η * ∇L(θ_old)。其中θ是参数η是学习率∇L是损失函数关于参数的梯度。Python模拟一维梯度下降import numpy as np import matplotlib.pyplot as plt def f(x): 目标函数y x^2 10*sin(x) return x**2 10*np.sin(x) def grad_f(x): 目标函数的导数解析解 return 2*x 10*np.cos(x) def gradient_descent(start_x, learning_rate, n_iterations): x start_x history [x] # 记录x的轨迹 for i in range(n_iterations): gradient grad_f(x) # 计算当前点的梯度 x x - learning_rate * gradient # 沿负梯度方向更新 history.append(x) return x, history # 执行梯度下降 start_x 5.0 # 起始点 lr 0.1 # 学习率 iters 50 # 迭代次数 final_x, x_history gradient_descent(start_x, lr, iters) print(f起始点: {start_x}) print(f最终点: {final_x:.6f}) print(f最终函数值: {f(final_x):.6f}) # 可视化 xs np.linspace(-6, 6, 400) plt.figure(figsize(12,5)) plt.subplot(1,2,1) plt.plot(xs, f(xs), b-, labelf(x)) plt.scatter(x_history, f(np.array(x_history)), cr, s20, labelGD Steps) plt.plot(x_history, f(np.array(x_history)), r--, alpha0.5) plt.xlabel(x) plt.ylabel(f(x)) plt.legend() plt.title(Gradient Descent Path) plt.subplot(1,2,2) plt.plot(range(len(x_history)), x_history, g-o) plt.xlabel(Iteration) plt.ylabel(x value) plt.title(Convergence of x) plt.tight_layout() plt.show()关键参数解析学习率 (η)这是最重要的超参数之一。太大会在最优点附近震荡甚至发散太小收敛速度极慢。上图可以尝试调整lr为0.01和0.5观察收敛行为的巨大差异。初始点对于非凸函数如神经网络不同的初始点可能导致收敛到不同的局部最优点。迭代次数需要足够多次迭代才能接近最优点。5.2 激活函数导数决定梯度流动的关键激活函数的导数直接影响了反向传播中梯度的大小和方向是解决梯度消失/爆炸问题的关键。Sigmoid函数及其导数import numpy as np import matplotlib.pyplot as plt def sigmoid(x): return 1 / (1 np.exp(-x)) def sigmoid_derivative(x): s sigmoid(x) return s * (1 - s) # 导数公式可由链式法则推导 x np.linspace(-6, 6, 100) y sigmoid(x) dy sigmoid_derivative(x) plt.figure(figsize(10,4)) plt.subplot(1,2,1) plt.plot(x, y, labelSigmoid) plt.title(Sigmoid Function) plt.grid(True) plt.subplot(1,2,2) plt.plot(x, dy, labelSigmoid, colororange) plt.title(Derivative of Sigmoid) plt.grid(True) plt.tight_layout() plt.show() # 分析当x的绝对值很大时4sigmoid值接近0或1其导数接近0。 print(f当x5时sigmoid导数: {sigmoid_derivative(5):.6f}) print(f当x-5时sigmoid导数: {sigmoid_derivative(-5):.6f})问题从右图可见Sigmoid的导数范围在(0, 0.25]之间。在深层网络中梯度需要连续乘以多个小于1的数极易导致梯度指数级衰减到接近0这就是梯度消失。因此在深层网络中Sigmoid已较少用作隐藏层激活函数。ReLU函数及其导数def relu(x): return np.maximum(0, x) def relu_derivative(x): return np.where(x 0, 1.0, 0.0) # 大于0导数为1小于等于0导数为0 x np.linspace(-3, 3, 100) y relu(x) dy relu_derivative(x) plt.figure(figsize(10,4)) plt.subplot(1,2,1) plt.plot(x, y, labelReLU) plt.title(ReLU Function) plt.subplot(1,2,2) plt.step(x, dy, labelReLU) # 使用step图更准确 plt.title(Derivative of ReLU) plt.tight_layout() plt.show()优势在正区间ReLU的导数恒为1彻底解决了梯度消失问题使得深层网络训练成为可能。计算也非常简单。缺陷死亡ReLU在负区间导数为0。如果一个神经元在大部分训练数据下都输出负值那么它的梯度将永远为0权重无法更新该神经元“死亡”。Leaky ReLU, PReLU等变体就是为了缓解这个问题。5.3 损失函数优化指导模型前进的方向损失函数的导数梯度指明了模型参数应该调整的方向。以最常见的均方误差MSE损失为例 对于单个样本(x, y_true)模型预测为y_pred则MSE Loss (y_true - y_pred)^2。 其对y_pred的导数为d(Loss)/d(y_pred) -2 * (y_true - y_pred)。 这个梯度非常直观如果预测值y_pred小于真实值y_true梯度为负意味着增加y_pred可以减少损失反之亦然。这个梯度会通过链式法则继续反向传播去更新更前面的网络参数。5.4 模型敏感度分析理解输入如何影响输出导数可以用来进行显著性分析或对抗样本生成。核心思想是计算模型输出对输入特征的梯度。梯度绝对值大的特征说明输入在该特征上的微小变化会导致输出发生较大变化即模型对该特征敏感。import torch import torch.nn as nn # 一个简单的线性模型 model nn.Linear(in_features5, out_features1, biasFalse) # 假设输入一个样本 input_tensor torch.randn(1, 5, requires_gradTrue) output model(input_tensor) # 计算输出对输入的梯度 output.backward() # 假设output是标量或者先求和 input_grad input_tensor.grad print(模型输出对输入的梯度形状:, input_grad.shape) print(梯度值:, input_grad) print(各输入特征的敏感度梯度绝对值:, torch.abs(input_grad))在这个例子中input_grad的每个元素就代表了对应输入特征对最终输出的“贡献度”或“影响力”。在可解释性AI中这可以用来生成热力图显示图像的哪些像素对分类决策最重要。6. 常见问题与实战调试技巧理论最终要服务于实践。在实际编码和调试中关于导数梯度的问题层出不穷。6.1 梯度消失与梯度爆炸深度网络的顽疾现象梯度消失深层网络中靠前的层梯度值极小几乎为零导致参数更新缓慢甚至停滞。梯度爆炸梯度值变得极大如NaN或Inf导致参数更新步长巨大模型无法收敛。诊断方法 在训练循环中定期打印或记录各层权重梯度的范数均值、最大值、L2范数。for name, param in model.named_parameters(): if param.grad is not None: grad_norm param.grad.norm().item() # 计算梯度L2范数 grad_max param.grad.max().item() grad_min param.grad.min().item() print(f{name}: grad norm{grad_norm:.6f}, max{grad_max:.6f}, min{grad_min:.6f})解决方案权重初始化使用Xavier或He初始化根据激活函数调整初始化方差让前向和反向传播的信号方差保持稳定。激活函数选择使用ReLU及其变体Leaky ReLU, PReLU替代Sigmoid/Tanh。梯度裁剪设置一个阈值当梯度范数超过该阈值时将梯度按比例缩小。这是解决梯度爆炸最直接有效的方法。torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)批归一化在激活函数前加入批归一化层可以稳定每一层的输入分布极大缓解梯度问题。残差连接如ResNet中的跳跃连接让梯度可以直接流过缓解深层网络中的梯度消失。6.2 学习率设置寻找“黄金步伐”学习率太小训练慢太大容易震荡甚至发散。调试技巧学习率范围测试从一个极小的值如1e-6开始逐步增大每次乘10在一个或几个epoch内观察损失下降情况。绘制损失-学习率对数曲线找到损失开始快速下降和开始震荡/上升的两个拐点最佳学习率通常在这两个拐点之间。周期性学习率如余弦退火、OneCycle策略在训练中动态调整学习率前期大步伐探索后期小步伐收敛。自适应优化器使用Adam、AdamW等优化器它们为每个参数维护自适应的学习率对初始学习率的选择不那么敏感。通常可以从3e-4或1e-3开始尝试。6.3 自定义函数求导确保梯度正确当你需要实现一个PyTorch或TensorFlow没有提供的操作时必须自定义其前向和反向传播规则。PyTorch示例实现一个自定义的Sigmoid激活函数import torch import torch.nn as nn class MySigmoid(nn.Module): def __init__(self): super().__init__() def forward(self, x): # 前向传播计算输出 self.save_for_backward torch.sigmoid(x) # 保存中间结果供反向传播用 return self.save_for_backward def backward(self, grad_output): # 反向传播计算梯度 # grad_output 是损失对本层输出的梯度 # 需要返回损失对本层输入的梯度 s self.save_for_backward grad_input grad_output * s * (1 - s) # 链式法则上游梯度 * 本层导数 return grad_input # 更标准的做法是继承 torch.autograd.Function class MySigmoidFunc(torch.autograd.Function): staticmethod def forward(ctx, x): # ctx 是上下文对象用于保存反向传播需要的数据 s torch.sigmoid(x) ctx.save_for_backward(s) # 保存s return s staticmethod def backward(ctx, grad_output): s, ctx.saved_tensors grad_input grad_output * s * (1 - s) return grad_input # 使用 my_sigmoid MySigmoidFunc.apply x torch.randn(3, requires_gradTrue) y my_sigmoid(x) loss y.sum() loss.backward() print(x.grad) # 检查梯度是否正确梯度检查实现自定义层后务必用数值梯度进行验证。from torch.autograd import gradcheck # gradcheck 需要在双精度下进行且输入需要是浮点数 input (torch.randn(3, 4, dtypetorch.double, requires_gradTrue),) test gradcheck(MySigmoidFunc.apply, input, eps1e-6, atol1e-4) print(梯度检查通过:, test)6.4 高阶导数洞察优化曲率一阶导数梯度告诉我们方向二阶导数海森矩阵则告诉我们曲率即这个方向的陡峭程度。这对于理解优化地形、设计二阶优化算法至关重要。计算二阶导数在PyTorch中可以通过对梯度再次求导来获得。x torch.tensor(2.0, requires_gradTrue) y x**3 2*x**2 # 计算一阶导 first_grad torch.autograd.grad(y, x, create_graphTrue)[0] # create_graph允许对梯度再求导 print(一阶导数 dy/dx:, first_grad.item()) # 在x2时 dy/dx 3x^24x 20 # 计算二阶导 second_grad torch.autograd.grad(first_grad, x)[0] print(二阶导数 d^2y/dx^2:, second_grad.item()) # 在x2时 d^2y/dx^2 6x4 16注意计算高阶导数在计算图和内存上开销较大通常只在理论分析或特定算法中使用。