我正在使用 Tensorflow 为二进制情感分析类微调 BERT。我想使用自定义训练循环/损失函数。但是,当我训练模型时,出现以下错误:ValueError: Internal error: Tried to take gradients (or similar) of a variable without handle data: Tensor("transformer_encoder/StatefulPartitionedCall:1019", shape=(), dtype=resource)
.
为了调试,我尝试简化我的训练循环以仅计算标准二进制交叉熵,这应该等同于如果我调用 model.fit() 并将二进制交叉熵作为损失函数(它工作得很好)。但是,在运行这个简化的训练循环时,我遇到了与上面相同的错误,我不确定是什么原因造成的。注意:我使用的是 tensorflow 2.3.0。
这是模型:
def create_model():
max_seq_length = 512
input_word_ids = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,
name="input_word_ids")
input_mask = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,
name="input_mask")
input_type_ids = tf.keras.layers.Input(shape=(max_seq_length,), dtype=tf.int32,
name="input_type_ids")
bert_layer = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/2", trainable=True)
pooled_output, sequence_output = bert_layer([input_word_ids, input_mask, input_type_ids])
drop = tf.keras.layers.Dropout(0.3)(pooled_output)
output = tf.keras.layers.Dense(1, activation='sigmoid', name="output")(drop)
model = tf.keras.Model(
inputs={
'input_word_ids': input_word_ids,
'input_mask': input_mask,
'input_type_ids': input_type_ids
},
outputs= output
)
return model
这是训练循环功能。ypred = model(train_x)
在 tf.GradientTape()中运行时似乎出现了这个问题:
def train_step(train_batch):
train_x, train_y = train_batch
with tf.GradientTape() as tape:
ypred = model(train_x)
loss = tf.reduce_mean(tf.keras.losses.binary_crossentropy(train_y, ypred))
grads = tape.gradient(loss, model.trainable_weights)
optimizer.apply_gradients(zip(grads, model.trainable_weights))
return loss
同样,这似乎只发生在 tf.GradientTape() 中,因为 model.fit() 不会导致任何问题。
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=2e-5),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=[tf.keras.metrics.BinaryAccuracy()])
model.fit(train_data,
validation_data=valid_data,
epochs=epochs,
verbose=1)