You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算Keras网络输出对输入变量的梯度?附示例

在Keras(TensorFlow后端)中计算输出对输入的梯度——附具体示例

嘿,我完全懂你现在的卡点:用Keras搭好网络近似函数后,想求输出对每个输入变量的偏导,查了资料要么模糊要么看不懂,用tf.gradients也没搞定。我结合你给的f(x,y,z)=x²+y²+z²的例子,一步一步给你讲清楚怎么实现,保证能跑通。

核心思路

Keras是TensorFlow的高阶API,所以我们要用到TF2.x推荐的GradientTape来追踪梯度(别再用旧的tf.gradients了,灵活性差很多)。关键是要让TensorFlow能追踪输入张量的运算过程,这样才能反向计算输出对输入的偏导。

完整代码示例

1. 导入依赖库

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import numpy as np

2. 生成训练数据

按照你的需求,生成x/y/z的随机样本,以及对应的x²+y²+z²标签:

# 固定随机种子保证结果可复现
np.random.seed(42)
# 生成10000个样本,每个样本是(x,y,z),取值范围[-5,5]
samples = np.random.uniform(-5, 5, (10000, 3))
# 计算每个样本对应的标签值:x²+y²+z²
labels = np.sum(samples**2, axis=1, keepdims=True)

3. 搭建并训练网络

用你定义的Sequential结构:

# 搭建网络
network = Sequential()
network.add(Dense(128, input_shape=(3,), activation='relu'))
network.add(Dense(128, activation='relu'))
network.add(Dense(1, activation='relu'))  # 原函数非负,用relu没问题

# 编译并训练
network.compile(optimizer='adam', loss='mse')
network.fit(samples, labels, epochs=50, batch_size=32, validation_split=0.1)

4. 定义梯度计算函数

这是最关键的部分,我们写一个函数,输入样本点,返回网络的近似输出值和对x/y/z的偏导:

def predict_with_gradients(model, input_point):
    # 把numpy数组转成TensorFlow张量,方便追踪梯度
    input_tensor = tf.convert_to_tensor(input_point.reshape(1, 3), dtype=tf.float32)
    
    # 用GradientTape记录前向传播过程
    with tf.GradientTape() as tape:
        # 显式告诉TF要追踪这个输入张量的梯度
        tape.watch(input_tensor)
        # 推理模式下计算网络输出(training=False避免影响Dropout/BatchNorm等层)
        output = model(input_tensor, training=False)
    
    # 计算输出对输入张量的梯度,结果形状是(1,3),对应x/y/z的偏导
    gradients = tape.gradient(output, input_tensor)
    
    # 把张量转成numpy数组返回,方便后续使用
    return output.numpy()[0][0], gradients.numpy()[0]

5. 测试效果

用你说的输入(1,2,3)来验证:

test_point = np.array([1, 2, 3])
predicted_val, grads = predict_with_gradients(network, test_point)

print(f"网络近似函数值:{predicted_val:.4f}(真实值:14)")
print(f"对x的偏导近似值:{grads[0]:.4f}(真实值:2)")
print(f"对y的偏导近似值:{grads[1]:.4f}(真实值:4)")
print(f"对z的偏导近似值:{grads[2]:.4f}(真实值:6)")

关键细节解释

  • 为什么用GradientTape? TF2.x默认是即时执行模式,需要用GradientTape记录前向运算的所有步骤,才能反向推导梯度。旧的tf.gradients是图模式下的API,现在已经不推荐使用了。
  • tape.watch(input_tensor)? 默认情况下,TF不会追踪输入张量的梯度(因为Keras模型的输入通常是占位符),所以必须显式调用watch告诉TF要追踪这个张量的变化。
  • training=False? 确保在计算梯度时用推理模式,比如Dropout层不会随机丢弃神经元,BatchNormalization用训练好的均值和方差,这样梯度计算更准确。

扩展说明

如果要处理批量输入(比如多个样本同时计算梯度),只需要把input_point改成形状为(batch_size, 3)的numpy数组,函数会返回每个样本的近似值和对应的三个偏导,非常方便。

内容的提问来源于stack exchange,提问作者gb4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:07:46