Внутренняя ошибка: Попытался взять градиенты (или аналогичные) переменной без обработки данных в Tensorflow

#tensorflow #nlp #bert-language-model #tensorflow-hub #gradienttape

Вопрос:

Я настраиваю БЕРТА для класса анализа двоичных настроений с использованием Tensorflow. Я хочу использовать пользовательскую функцию цикла обучения/потери. Однако, когда я тренирую модель, я получаю следующую ошибку: 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)
 

Ответ №1:

Не могли бы вы повторить попытку с новейшей версией модели (https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/4)? Версия 4 представила поддержку градиентных лент, так что это может быть причиной того, что вы видите проблемы при попытке использования tf.GradientTape с версией v2.

Комментарии:

1. Я обнаружил, что просто изменение версий пакетов помогло. Тем не менее, это, возможно, также сделало свое дело. Спасибо!