TensorFlow2使用tf.keras.optimizers.SGD.minimize时报无梯度错误如何解决
ValueError: No gradients provided for any variable: ['Variable:0', 'Variable:0', 'Variable:0', 'Variable:0'].
报错根因
- 前向传播计算逻辑位置错误:你将
h1、y_out的计算放在了loss函数外部,代码运行到这里时已经直接计算出了固定的张量结果,后续loss函数返回的只是这个固定值的平方和,优化器无法追踪到损失和m1、b1、m2、b2这些变量之间的计算路径,因此找不到梯度。 - TF版本API混用:你用的是TensorFlow 2,却写了TensorFlow 1的
tf.Session()静态图执行逻辑,TF2默认开启即时执行模式,不需要通过Session运行操作,混用两套API也会导致梯度计算链路断裂。
修复方案
直接改成符合TensorFlow 2规范的写法,把所有前向传播逻辑移入损失计算过程,删除Session相关代码即可,修改后的完整代码如下:
import tensorflow as tf x = [[0.,0.],[1.,1.],[1.,0.],[0.,1.]] y_ = [[0.],[0.],[1.],[1.]] x0 = tf.constant(x, dtype=tf.float32) y0 = tf.constant(y_, dtype=tf.float32) # 初始化训练变量 m1 = tf.Variable(tf.random.uniform([2,3], minval=0.1, maxval=0.9, dtype=tf.float32)) b1 = tf.Variable(tf.random.uniform([3], minval=0.1, maxval=0.9, dtype=tf.float32)) m2 = tf.Variable(tf.random.uniform([3,1], minval=0.1, maxval=0.9, dtype=tf.float32)) b2 = tf.Variable(tf.random.uniform([1], minval=0.1, maxval=0.9, dtype=tf.float32)) # 损失函数包含完整前向传播逻辑,保证梯度路径可追踪 def loss(): h1 = tf.sigmoid(tf.matmul(x0, m1) + b1) y_out = tf.sigmoid(tf.matmul(h1, m2) + b2) return tf.reduce_sum(tf.square(y0 - y_out)) optimizer = tf.keras.optimizers.SGD(1.0) # 训练循环,TF2即时执行无需Session for step in range(500): optimizer.minimize(loss, var_list=[m1, b1, m2, b2]) # 输出结果 h1 = tf.sigmoid(tf.matmul(x0, m1) + b1) y_out = tf.sigmoid(tf.matmul(h1, m2) + b2) results = [m1, b1, m2, b2, y_out, loss()] labels = "m1,b1,m2,b2,y_out,loss".split(",") for label, result in zip(labels, results): print("") print(label) print(result.numpy()) print("")
关键修改说明
- 把
h1、y_out的计算放到了loss函数内部,优化器调用minimize时会自动追踪变量到损失的计算路径,正确生成梯度 - 删掉了
tf.Session()相关的所有代码,直接在循环中调用optimizer.minimize()执行训练,符合TF2即时执行的特性 - 最后输出结果时调用
.numpy()方法把张量转为numpy数组打印,符合TF2的常规操作
内容的提问来源于stack exchange,提问作者Luis Manuel Ambrocio
相关产品推荐
相关产品推荐

