使用 BERT 进行多标签分类

Doing Multi-Label classification with BERT

我想使用 BERT model 通过 Tensorflow 进行多标签 class 化。

为此,我想改编 BERT github repository, which is an example on how to use BERT to do simple classification, using the pre-trained weights given by Google Research 中的示例 run_classifier.py。 (例如 BERT-Base, Cased

我有 X 个不同的标签,它们的值为 0 或 1,所以我想向原始 BERT 模型添加一个新的大小为 X 的密集层并使用 sigmoid_cross_entropy_with_logits 激活函数.

所以,对于理论部分,我认为我还可以。

问题是我不知道如何使用现有的 BertModel class.[=23= 附加一个新的输出层并用我的数据集重新训练这个新层]

这是来自 run_classifier.py 的原始 create_model() 函数,我想我必须在其中进行修改。但是我有点不知道该怎么做。

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)

我在代码中修改的其他内容我没有问题:

所以,如果有人知道我应该如何解决我的问题,或者甚至指出我可能犯的一些明显错误,我会很高兴听到。

备注:

您想用 sigmoid 替换对可能输出(所有分数总和为 1)的单一分布建模的 softmax,它为每个 class(有 yes/no 分布建模独立分布对于每个输出)。

因此,您正确地更改了损失函数,但您还需要更改计算概率的方式。应该是:

probabilities = tf.sigmoid(logits)

在这种情况下,您不需要 log_probs