欢迎访问宙启技术站
智能推送

在PyTorch_Pretrained_BERT.Modeling中实现多任务学习

发布时间:2024-01-15 09:11:30

在PyTorch_Pretrained_BERT库中,可以实现多任务学习(Multi-Task Learning)的方法有很多种。这里,我们将讨论一种常见的方法:共享特征提取层(Shared Feature Extraction)。

共享特征提取层是指在BERT模型的基础上,将其最后几层的参数进行共享,同时在每个任务上添加各自的任务特定层。这样做可以在进行多任务学习时充分利用BERT的预训练参数,并且仍能够根据每个任务的需求调整各自的任务特定层。

我们以实现一个文本分类和命名实体识别(Named Entity Recognition)的多任务学习为例。我们假设已经加载了预训练的BERT模型,并且准备好了训练数据。

首先,我们需要定义一个多任务模型,继承自nn.Module类。在这个模型中,我们将包含两个任务:文本分类和命名实体识别。

import torch
import torch.nn as nn
from transformers import BertModel

class MultiTaskModel(nn.Module):
    def __init__(self, num_labels_classifier, num_labels_ner):
        super(MultiTaskModel, self).__init__()
        self.bert = BertModel.from_pretrained('bert-base-uncased')
        self.classifier = nn.Linear(self.bert.config.hidden_size, num_labels_classifier)
        self.ner = nn.Linear(self.bert.config.hidden_size, num_labels_ner)
        
    def forward(self, input_ids, attention_mask):
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
        pooled_output = outputs[1]
        
        classifier_logits = self.classifier(pooled_output)
        ner_logits = self.ner(outputs[0])  # [0]表示取BERT模型输出的最后一层(即所有隐藏层)的结果
        
        return classifier_logits, ner_logits

接下来,我们需要定义模型训练的部分。这包括计算损失、更新参数等。

def train(model, train_dataloader_classification, train_dataloader_ner, optimizer, device):
    model.train()
    
    for step, (inputs_classification, labels_classification, inputs_ner, labels_ner) in enumerate(zip(train_dataloader_classification,
                                                                                                       train_dataloader_ner)):
        input_ids_classification = inputs_classification[0].to(device)
        attention_mask_classification = inputs_classification[1].to(device)
        labels_classification = labels_classification.to(device)
        
        input_ids_ner = inputs_ner[0].to(device)
        attention_mask_ner = inputs_ner[1].to(device)
        labels_ner = labels_ner.to(device)
        
        optimizer.zero_grad()
        
        logits_classification, logits_ner = model(input_ids_classification, attention_mask_classification,
                                                  input_ids_ner, attention_mask_ner)
        
        loss_classification = nn.CrossEntropyLoss()(logits_classification, labels_classification)
        loss_ner = nn.CrossEntropyLoss()(logits_ner.view(-1, num_labels_ner), labels_ner.view(-1))
        
        total_loss = loss_classification + loss_ner
        total_loss.backward()
        
        optimizer.step()

最后,我们可以将模型、数据加载器、优化器等组合起来进行多任务学习的训练。

from transformers import BertTokenizer
from torch.utils.data import DataLoader

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

train_dataset_classification = ...
train_dataloader_classification = DataLoader(train_dataset_classification, batch_size=32, shuffle=True)

train_dataset_ner = ...
train_dataloader_ner = DataLoader(train_dataset_ner, batch_size=32, shuffle=True)

model = MultiTaskModel(num_labels_classifier, num_labels_ner)
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

for epoch in range(num_epochs):
    train(model, train_dataloader_classification, train_dataloader_ner, optimizer, device)

以上代码演示了如何在PyTorch_Pretrained_BERT中实现一个简单的多任务学习模型,该模型包含了文本分类和命名实体识别两个任务。你可以根据自己的需求进行适当的修改和扩展。