如何在预训练的 BERT 模型之上添加多类多标签层?

How to add a multiclass multilabel layer on top of pretrained BERT model?

我正在尝试使用来自 huggingface transformers 库的预训练 BERT 模型来执行多任务多类句子分类任务。我曾尝试从那里使用 BERTForSequenceClassification 模型,但我遇到的问题是我无法将它扩展到多个任务。我会尝试通过这个例子让它更丰富。

假设我们有四个不同的任务,对于每个句子和每个任务,我们都有如下示例中的标签:

  1. A :[ 'a' , 'b' , 'c' , 'd' ]
  2. B :[ 'e' , 'f' , 'g' , 'h' ]
  3. C :[ 'i' , 'j' , 'k' , 'l' ]
  4. D :[ 'm' , 'n' , 'o' , 'p' ]

现在,如果我有一个关于这个模型的句子,我希望输出为所有四个不同的任务 (A、B、C、D) 提供输出。

这是我之前做的

   model = BertForSequenceClassification.from_pretrained(
    "bert-base-uncased", # Use the 12-layer BERT model, with an uncased vocab.
    num_labels = 4, # The number of output labels--2 for binary classification.
                    # You can increase this for multi-class tasks.   
    output_attentions = False, # Whether the model returns attentions weights.
    output_hidden_states = False, # Whether the model returns all hidden-states.
)

然后我尝试像这样实现一个 CustomBERT 模型:

class CustomBERTModel(nn.Module):
    def __init__(self):
          super(CustomBERTModel, self).__init__()
          self.bert = BertModelForSequenceClassification.from_pretrained("bert-base-uncased")
          ### New layers:
          self.linear1 = nn.Linear(768, 256)
          self.linear2 = nn.Linear(256, num_classes) ## num_classes is the number of classes in this example

    def forward(self, ids, mask):
          sequence_output, pooled_output = self.bert(
               ids, 
               attention_mask=mask)

          # sequence_output has the following shape: (batch_size, sequence_length, 768)
          linear1_output = self.linear1(sequence_output[:,0,:].view(-1,768)) 
          linear2_output = self.linear2(linear2_output)

          return linear2_output

我已经浏览了与之前可用的类似问题的答案,但其中 none 回答我的问题 。我已尝试了解所有我认为有助于理解我的问题的要点,如果我在解释问题时出现任何不一致,我会尝试进一步澄清。任何与此相关的答案都会非常有帮助。

您应该使用 BertModel 而不是 BertModelForSequenceClassification,因为 BertModelForSequenceClassification 在 BERT 模型之上添加了一个用于分类的线性层并使用 CrossEntropyLoss,这意味着多类分类。

因此,首先使用BertModel代替BertModelForSequenceClassification

class CustomBERTModel(nn.Module):
    def __init__(self):
          super(CustomBERTModel, self).__init__()
          self.bert = BertModel.from_pretrained("bert-base-uncased")
          ### New layers:
          self.linear1 = nn.Linear(768, 256)
          self.linear2 = nn.Linear(256, 4) ## as you have 4 classes in the output
          self.sig = nn.functional.sigmoid()

    def forward(self, ids, mask):
          sequence_output, pooled_output = self.bert(
               ids, 
               attention_mask=mask)

          # sequence_output has the following shape: (batch_size, sequence_length, 768)
          linear1_output = self.linear1(sequence_output[:,0,:].view(-1,768)) 
          linear2_output = self.linear2(linear2_output)
          linear2_output = self.sig(linear2_output)

          return linear2_output

接下来,多标签分类使用'Sigmoid'激活而不是'Softmax'(这里,在上面的代码中添加了sigmoid层)

此外,对于多标签分类,您需要使用BCELoss而不是CrossEntropyLoss