基于TensorFlow Probability实现L-BFGS时无法存储各epoch损失值
解决TensorFlow Probability L-BFGS存储损失时的AttributeError问题
错误原因
你遇到的AttributeError: 'Tensor' object has no attribute 'loss'是因为在TensorFlow图模式下,你的函数f被编译为计算图中的Tensor节点,而非原本的Python函数实例。此时试图通过f.loss访问函数的列表属性,实际访问的是Tensor对象的属性,自然找不到loss。
解决方案
方案1:使用tf.Variable存储损失历史
tf.Variable可以在图模式和Eager模式下正常追踪和更新,适合存储训练过程中的损失值:
# 初始化可追踪的损失历史变量 loss_history = tf.Variable([], dtype=tf.float32) def f(model, x, y): with tf.GradientTape() as tape: y_pred = model(x, training=True) loss = tf.reduce_mean(tf.square(y_pred - y)) # 更新损失历史:将新损失追加到变量中 loss_history.assign(tf.concat([loss_history, [loss]], axis=0)) grads = tape.gradient(loss, model.trainable_variables) return loss, grads # 后续L-BFGS优化调用该函数即可 optimizer = tfp.optimizer.LBFGS() optimizer.minimize(lambda: f(model, x, y), var_list=model.trainable_variables)
方案2:切换到Eager模式手动记录损失
如果不需要严格的图模式优化,可以手动在Eager模式下运行L-BFGS步骤,直接用Python列表记录损失:
loss_history = [] optimizer = tfp.optimizer.LBFGS() def loss_fn(): y_pred = model(x, training=True) loss = tf.reduce_mean(tf.square(y_pred - y)) # 直接将损失值转为numpy后存入列表 loss_history.append(loss.numpy()) return loss # 手动执行优化 optimizer.minimize(loss_fn, var_list=model.trainable_variables)
方案3:修复原tf.py_function的用法(不推荐)
若坚持使用原代码结构,需确保损失列表能被tf.py_function正确访问。可以将列表封装为全局变量或类属性,同时修改tf.py_function的调用方式:
# 定义全局损失列表 loss_history = [] def append_loss(loss): loss_history.append(loss.numpy()) return # 在计算损失的函数中调用 def f(model, x, y): with tf.GradientTape() as tape: y_pred = model(x, training=True) loss = tf.reduce_mean(tf.square(y_pred - y)) # 使用tf.py_function调用外部的append_loss函数 tf.py_function(append_loss, inp=[loss], Tout=[]) grads = tape.gradient(loss, model.trainable_variables) return loss, grads
这种方式依赖Python全局状态,在复杂训练流程中容易出现问题,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Pavan Kumar J
相关产品推荐
相关产品推荐

