Выполнение классификации по нескольким меткам с помощью BERT

Я хочу использовать модель BERT для классификации с несколькими метками с помощью Tensorflow.

Для этого я хочу адаптировать пример run_classifier.py из репозитория Github BERT, который является примером на как использовать BERT для простой классификации, используя предварительно обученные веса, предоставленные Google Research. (Например, с BERT-Base, Cased)

У меня X разные метки, которые имеют значение 0 или 1, поэтому я хочу добавить к исходной модели BERT новый плотный слой размером X и использовать функцию активации sigmoid_cross_entropy_with_logits.

Итак, что касается теоретической части, я думаю, что я в порядке.

Проблема в том, что я не знаю, как добавить новый выходной слой и переобучить только этот новый слой с моим набором данных, используя существующий класс BertModel.

Вот оригинальная create_model() функция из run_classifier.py, где, я думаю, мне нужно внести свои изменения. Но я немного не понимаю, что мне делать.

def create_model(bert_config, is_training, input_ids, input_mask, segment_ids,
                 labels, num_labels, use_one_hot_embeddings):
  """Creates a classification model."""
  model = modeling.BertModel(
      config=bert_config,
      is_training=is_training,
      input_ids=input_ids,
      input_mask=input_mask,
      token_type_ids=segment_ids,
      use_one_hot_embeddings=use_one_hot_embeddings)

  output_layer = model.get_pooled_output()

  hidden_size = output_layer.shape[-1].value

  output_weights = tf.get_variable(
      "output_weights", [num_labels, hidden_size],
      initializer=tf.truncated_normal_initializer(stddev=0.02))

  output_bias = tf.get_variable(
      "output_bias", [num_labels], initializer=tf.zeros_initializer())

  with tf.variable_scope("loss"):
    if is_training:
      # I.e., 0.1 dropout
      output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)

    logits = tf.matmul(output_layer, output_weights, transpose_b=True)
    logits = tf.nn.bias_add(logits, output_bias)
    probabilities = tf.nn.softmax(logits, axis=-1)
    log_probs = tf.nn.log_softmax(logits, axis=-1)

    one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)

    per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)
    loss = tf.reduce_mean(per_example_loss)

    return (loss, per_example_loss, logits, probabilities)

А вот та же функция с некоторыми моими модификациями, но где чего-то не хватает (и чего-то не так?)

def create_model(bert_config, is_training, input_ids, input_mask, segment_ids, labels, num_labels):
  """Creates a classification model."""
  model = modeling.BertModel(
      config=bert_config,
      is_training=is_training,
      input_ids=input_ids,
      input_mask=input_mask,
      token_type_ids=segment_ids)

  output_layer = model.get_pooled_output()

  hidden_size = output_layer.shape[-1].value

  output_weights = tf.get_variable("output_weights", [num_labels, hidden_size],initializer=tf.truncated_normal_initializer(stddev=0.02))

  output_bias = tf.get_variable("output_bias", [num_labels], initializer=tf.zeros_initializer())

  with tf.variable_scope("loss"):
    if is_training:
      # I.e., 0.1 dropout
      output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)

    logits = tf.matmul(output_layer, output_weights, transpose_b=True)
    logits = tf.nn.bias_add(logits, output_bias)
    probabilities = tf.nn.softmax(logits, axis=-1)
    log_probs = tf.nn.log_softmax(logits, axis=-1)

    per_example_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)

    loss = tf.reduce_mean(per_example_loss)

    return (loss, per_example_loss, logits, probabilities)

Другие вещи, которые я адаптировал в коде и с которыми у меня не было проблем:

  • DataProcessor для загрузки и анализа моего пользовательского набора данных
  • Изменение типа переменной меток с числовых значений на массивы везде, где она используется

Итак, если кто-нибудь знает, что мне делать, чтобы решить мою проблему, или даже укажет на какую-то очевидную ошибку, которую я, возможно, совершил, я был бы рад это услышать.

Примечания :

  • Я нашел эту статью, в которой очень хорошо соответствуют тому, что я пытаюсь сделать, но он использует PyTorch, и я не могу перевести его в Tensorflow.

person Nakeuh    schedule 06.05.2019    source источник


Ответы (1)


Вы хотите заменить softmax, который моделирует единое распределение для возможных выходов (все оценки в сумме составляют один), на сигмоид, который моделирует независимое распределение для каждого класса (для каждого выхода существует распределение «да / нет»).

Итак, вы правильно изменили функцию потерь, но вам также необходимо изменить способ вычисления вероятностей. Должен быть:

probabilities = tf.sigmoid(logits)

В этом случае log_probs.

person Jindřich    schedule 06.05.2019
comment
Спасибо ! И можно ли установить, какой уровень я хочу обучать (например, freeze и unfreeze из Keras), чтобы я переучивал только последний слой? - person Nakeuh; 06.05.2019
comment
Вы можете применить tf.stop_gradient на output_layer, и это предотвратит обратное распространение в BERT модель. - person Jindřich; 06.05.2019