Делать Multi-Label классификацию с BERT - PullRequest
1 голос
/ 06 мая 2019

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

Для этого я хочу адаптировать пример run_classifier.py из GERT-репозитория 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.

1 Ответ

2 голосов
/ 06 мая 2019

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

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

probabilities = tf.sigmoid(logits)

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

...