TensorFlow即时执行报错:AttributeError: 'NoneType'对象无'_tape'属性
先把你的报错信息贴出来方便定位:
AttributeError 回溯(最近的调用最后)
in ()
17 answer=tf.convert_to_tensor(answers_train[i], dtype=tf.float32)
18 ---> 19 grads = grad(model, sent, quest, answer)
20 optimizer.apply_gradients(zip(grads, model.variables),
21 global_step=tf.train.get_or_create_global_step())
<ipython-input-20...
我之前在Eager模式下写自定义梯度计算时也踩过类似的坑,给你几个最可能的排查方向:
检查你的
grad函数实现是否规范
在Eager模式下计算梯度必须依赖tf.GradientTape上下文来追踪运算,如果你的grad函数是自己实现的,大概率是没正确用GradientTape包裹前向传播和损失计算。正确的模板应该是这样:def grad(model, sent, quest, answer): # 用GradientTape追踪梯度 with tf.GradientTape() as tape: # 前向传播得到预测结果 preds = model(sent, quest) # 计算损失(这里需要你实现对应的损失函数,比如交叉熵、MSE等) loss = tf.keras.losses.MSE(answer, preds) # 对模型的可训练变量求梯度 return tape.gradient(loss, model.trainable_variables)要注意:必须在tape的上下文里完成模型调用和损失计算,否则tape无法追踪到梯度;另外要明确对
model.trainable_variables求导,而不是直接对model对象操作。确认模型变量已正确初始化
Eager模式下,模型的变量是在第一次前向传播时才会创建的。如果在调用grad函数之前,你从来没运行过model(sent, quest)这种前向操作,模型内部还没有生成变量,那计算梯度时自然会抛出AttributeError。解决方法很简单:在调用grad之前,先跑一次前向传播初始化变量,比如加一行_ = model(sent, quest)。检查传入
grad的参数类型
虽然Eager模式支持自动把numpy数组转成张量,但有时候类型不匹配也会导致奇怪的报错。你已经把answer转成了tf.float32,那sent和quest最好也统一转成对应的张量类型(比如tf.int32如果是序列数据),避免隐式转换带来的问题。替换
model.variables为model.trainable_variables
看你后面的optimizer.apply_gradients用了model.variables,这个属性包含了模型所有变量(比如BatchNorm的moving_mean这种不可训练的变量),而我们计算的梯度只针对可训练变量,两者不匹配也可能间接导致问题。把它改成model.trainable_variables更稳妥。
内容的提问来源于stack exchange,提问作者SimonAda

