基于TensorFlow 2.1.0的Iris逻辑回归报Tensor不可调用TypeError排查
报错根因定位
报错和模块4的损失函数定义无关,触发逻辑如下:
- 你实例化的
tf.optimizers.SGD属于TensorFlow 2.x的Keras V2系列优化器,其内置的minimize方法对loss参数的默认要求是无参数可调用对象,方法内部会在梯度带追踪上下文里执行这个对象、获取损失值后计算梯度。 - 当前环境已通过
tf.compat.v1.disable_eager_execution()切回TF1风格静态图执行模式,没有即时执行的梯度带追踪能力,V2优化器按照自身流程,试图直接调用你传入的损失张量(而非可调用函数),最终触发'Tensor' object is not callable的类型错误。
修复方案
方案1(适配当前静态图代码风格,改动最小)
将模块6、模块7的优化器代码替换为TF1兼容版本,该版本的minimize方法原生支持直接传入损失张量,和现有代码逻辑完全匹配:
# 模块6修改内容 learning_rate = 0.003 batch_size = 30 iter_num = 1500 # 替换原有V2版SGD opt = tf.compat.v1.train.GradientDescentOptimizer(learning_rate=learning_rate) # 模块7修改内容 goal = opt.minimize(loss, var_list=[A, b])
修改后运行不会再触发类型错误,可正常启动图内的训练流程。
方案2(保留现有V2版优化器,调整调用规则)
如果希望继续使用tf.optimizers.SGD,需要把损失计算逻辑封装为无参数可调用函数传入minimize方法,不能直接传已定义好的损失张量:
# 模块7修改内容 def calc_loss(): # 将前向传播、损失计算逻辑全部包裹在可调用函数内 logits = tf.matmul(data, A) + b return tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=target)) # 传入函数对象而非张量对象 goal = opt.minimize(calc_loss, var_list=[A, b])
附加注意事项
当前实现是单输出sigmoid二分类逻辑,和Iris数据集的三分类任务不匹配,报错解决后需要同步调整模型结构:
- 权重维度从
(4,1)改为(4,3) - 损失函数替换为
tf.nn.softmax_cross_entropy_with_logits,匹配三分类输出 - 标签的维度调整为和类别数匹配的one-hot格式
内容的提问来源于stack exchange,提问作者PUSHKAL SHUKLA
相关产品推荐
相关产品推荐

