核心要点

  • 能说清 with tf.GradientTape() 块内记录可微 op,块外调 tape.gradient(loss, vars) 反向求梯度,再 optimizer.apply_gradients

  • 能讲 tape 默认只追踪 tf.Variable,对普通常量张量需 tape.watch() 显式追踪

  • 能说明默认 tape 用一次即释放,求多个 target 或高阶导需 persistent=True

  • 能对比:PyTorch Autograd 默认隐式建图,TF 用显式 tape 块界定记录范围,控制更精细

标准回答

TensorFlow 2.x 的自动微分核心是 tf.GradientTape

python
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.kerasmodel.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 梯度。

追问

追问 1GradientTape 和 tf.keras fit 用哪个?

标准监督训练直接用 model.fit,简洁且自带回调、分布式、进度条;需要自定义训练逻辑(GAN 多优化器、自定义损失/梯度操作、强化学习、元学习)时才手写 GradientTape 训练循环。也可重写 Model.train_step,在保留 fit 便利的同时插入自定义梯度逻辑。

追问 2如何求高阶导数?

嵌套 GradientTape:外层 tape 记录"内层 tape 求一阶导"的过程,再对一阶导求导得二阶。需让内层 tape persistent=True 或确保被外层追踪。常用于物理约束损失(PINN)、二阶优化、梯度惩罚(如 WGAN-GP)。

追问 3tape 外定义的变量能求梯度吗?

能。关键不是变量在哪定义,而是用到它的运算是否发生在 with 块内被记录。若它是 tf.Variable,tape 自动追踪;若是普通张量,需在块内 tape.watch(x)。只要前向计算在 tape 上下文里执行,tape.gradient 就能算出对它的梯度。

延伸学习

与本题相关的知识库文章、术语、工具与行业资讯。

🛠️ AI 工具

  • Pytorch

    Meta 开源的深度学习框架,100K+ stars。以动态计算图和 Pythonic 风格著称,在学术界和工业界都有广泛应用,支持分布式训练、移动端部署和 ONNX 导出

  • Tensorflow

    全球最流行的机器学习框架之一,195K+ stars。Google 开源的端到端 ML 平台,支持 TensorFlow、Keras 等多种 API,覆盖深度学习、强化学习、移动端部署等全场景,是 AI 工程师的必备工具

  • Keras

    深度学习框架,64,020+ stars。高级神经网络 API,支持 TensorFlow、JAX、PyTorch 多后端。以用户友好著称,让深度学习从实验到生产的转化变得简单高效