TensorFlow与PyTorch梯度计算对比及TensorFlow梯度返回None问题的排查与解决
为什么TensorFlow中梯度计算结果为None?如何正确计算?
问题根源
你的TensorFlow代码里,权重w和偏置b是用tf.random.normal()创建的普通tf.Tensor,这类张量默认不会被tf.GradientTape追踪梯度。而PyTorch里你给w和b设置了requires_grad=True,明确告诉框架要计算它们的梯度——这就是两者的核心差异。
TensorFlow的GradientTape默认只追踪tf.Variable类型的可训练变量的梯度,普通张量不在追踪范围内,所以调用tape.gradient()时会返回None。
正确的解决方法
有两种方式可以修复这个问题,推荐第一种(更符合TensorFlow的训练范式):
方法1:将w和b定义为tf.Variable
把原来的w和b的创建代码替换成tf.Variable,它会自动被GradientTape追踪:
import numpy as np import tensorflow as tf inputs = np.array([[73, 67, 43], [91, 88, 64], [87, 134, 58], [102, 43, 37], [69, 96, 70]], dtype='float32') targets = np.array([[56, 70], [81, 101], [119, 133], [22, 37], [103, 119]], dtype='float32') inputs = tf.convert_to_tensor(inputs) targets = tf.convert_to_tensor(targets) # 修改这里:用tf.Variable定义可训练参数 w = tf.Variable(tf.random.normal(shape=(2, 3))) b = tf.Variable(tf.random.normal(shape=(2,))) print(w, b) def model(x): return tf.matmul(x, w, transpose_b = True) + b def mse(t1, t2): diff = t1-t2 return tf.reduce_sum(diff * diff) / tf.cast(tf.size(diff), 'float32') with tf.GradientTape() as tape: pred = model(inputs) loss = mse(pred, targets) # 现在可以正常得到梯度 grads = tape.gradient(loss, [w, b]) print(grads)
方法2:手动用tape.watch()追踪普通张量
如果你因为某些原因必须使用普通tf.Tensor,可以在GradientTape上下文里手动调用tape.watch()来指定要追踪的张量:
with tf.GradientTape() as tape: # 手动追踪w和b tape.watch([w, b]) pred = model(inputs) loss = mse(pred, targets) grads = tape.gradient(loss, [w, b]) print(grads)
不过这种方式更适合临时追踪单个张量,训练模型时还是推荐用tf.Variable,它还支持自动管理优化器更新、保存加载等功能。
补充说明
TensorFlow的GradientTape工作逻辑是:在上下文管理器内记录所有对可追踪张量的运算,离开上下文后通过tape.gradient()反向计算梯度。只有tf.Variable(默认trainable=True)或者被tape.watch()标记的张量才会被记录运算路径,否则无法计算梯度。
内容的提问来源于stack exchange,提问作者user13
相关产品推荐
相关产品推荐

