使用BERT进行多标签分类

时间:2019-05-06 13:51:00

标签: python tensorflow classification multilabel-classification

我想使用BERT model对Tensorflow进行多标签分类。

为此,我想改写BERT github repository中的示例run_classifier.py,该示例是如何使用pre-trained weights given by Google Research使用BERT进行简单分类的示例。 (例如,使用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来加载和解析我的自定义数据集
  • 将标签变量的类型从数字值更改为数组,并随处使用

因此,如果有人知道我应该怎么做才能解决我的问题,或者甚至指出我可能犯了一些明显的错误,我将很高兴听到它。

注意:

  • 我发现this article与我要执行的操作非常吻合,但是它使用PyTorch,并且无法将其转换为Tensorflow。

1 个答案:

答案 0 :(得分:2)

您要用Sigmoid代替对可能的输出进行单一分布建模的softmax(所有分数加起来为1),而sigmoid则为每个类别建模一个独立的分布(每个输出都有是/否的分布)。

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

    <html> 
    <body>
     <form action="/a.html"> <center><h1>Vignesh</h1> > </center> <BR><br> <input type="submit" value="SUBMIT"> 
    </form> >
     </body> 
    </html>

Here is my a.html code...

    <html>
    <body>
    <h1>
    <b>SUBMITTED<b>
    </h1>
    </body>
    </html>

在这种情况下,您不需要probabilities = tf.sigmoid(logits)