标准回答
TensorFlow 2.x 的自动微分核心是 tf.GradientTape:
with tf.GradientTape() as tape:
predictions = model(x, training=True)
loss = loss_fn(y, predictions)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))机制:tape 在 with 块内记录所有可微 op 及其依赖(动态计算图);gradient(target, sources) 从 target 向 sources 反向应用链式法则。
进阶:
- persistent=True:允许多次对同一 tape 求不同 target 的梯度
- watch():显式追踪非 Variable 张量
- @tf.function:将训练步编译为图,tape 在图内仍有效
- tf.keras 的 model.fit 内部自动处理梯度
与 PyTorch Autograd 对比:PyTorch 默认建图更「隐式」;TF 2.x 显式 tape 块,控制更精细。TF 1.x 静态图靠 tf.gradients 符号求导,2.x 以 tape 为主。详见 反向传播原理。
常见误区
⚠️ 常见踩坑
把前向计算写在 with 块外、只在块内放 loss,导致 tape 没记到中间 op,tape.gradient 返回全 None;另一个是对一个普通张量(非 tf.Variable)求导却忘了 tape.watch(x),同样拿到 None 梯度。
追问
追问 1:GradientTape 和 tf.keras fit 用哪个?
追问 2:如何求高阶导数?
嵌套 GradientTape:外层 tape 记录"内层 tape 求一阶导"的过程,再对一阶导求导得二阶。需让内层 tape persistent=True 或确保被外层追踪。常用于物理约束损失(PINN)、二阶优化、梯度惩罚(如 WGAN-GP)。
追问 3:tape 外定义的变量能求梯度吗?
能。关键不是变量在哪定义,而是用到它的运算是否发生在 with 块内被记录。若它是 tf.Variable,tape 自动追踪;若是普通张量,需在块内 tape.watch(x)。只要前向计算在 tape 上下文里执行,tape.gradient 就能算出对它的梯度。
延伸学习
与本题相关的知识库文章、术语、工具与行业资讯。
📰 AI 资讯
🛠️ AI 工具
- Pytorch
Meta 开源的深度学习框架,100K+ stars。以动态计算图和 Pythonic 风格著称,在学术界和工业界都有广泛应用,支持分布式训练、移动端部署和 ONNX 导出
- Tensorflow
全球最流行的机器学习框架之一,195K+ stars。Google 开源的端到端 ML 平台,支持 TensorFlow、Keras 等多种 API,覆盖深度学习、强化学习、移动端部署等全场景,是 AI 工程师的必备工具
- Keras
深度学习框架,64,020+ stars。高级神经网络 API,支持 TensorFlow、JAX、PyTorch 多后端。以用户友好著称,让深度学习从实验到生产的转化变得简单高效