USING TRANSFORMERS(二) | 训练和微调

🤗 Transformers 中的模型类被设计为与本机PyTorch和TensorFlow 2兼容,并且可以与其中任何一个无缝使用。在这个快速入门中,我们将展示如何使用两种框架中可用的标准培训工具来微调(或从头开始培训)模型。我们还将展示如何使用包含的Trainer()类,它可以为您处理很多复杂的训练。
本指南假设您已经熟悉加载和使用我们的模型进行推理;否则,请参见任务摘要。我们还假设您熟悉深度神经网络的训练。

在原生PyTorch中进行微调

🤗 Transformers 中不以TF开头的模型类是PyTorch模块,这意味着您可以像使用PyTorch中的任何模型一样使用它们进行推理和优化。

让我们考虑在序列分类数据集上微调像BERT这样的掩码语言模型的常见任务。当我们用from_pretrained()实例化模型时,将使用指定模型的模型配置和预先训练过的权值来初始化模型。该库还包括许多特定于任务的最终层或“头”,它们的权值在指定的预训练模型中不存在时被随机实例化。例如,用 BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2) 将创建一个BERT模型实例,其编码器权重从bert-base-uncased模型复制而来,并在编码器上随机初始化一个输出大小为2的序列分类头。 模型默认以评估模式初始化。我们可以调用model.train()将其置于训练模式。

from transformers import BertForSequenceClassification
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
model.train()

这是很有用的,因为它允许我们使用预先训练好的 BERT 编码器,并在我们选择的任何序列分类数据集上轻松训练它。我们可以使用任何PyTorch优化器,但我们的库也提供了AdamW()优化器,它实现了梯度偏差校正以及权重衰减:

from transformers import AdamW
optimizer = AdamW(model.parameters(), lr=1e-5)

优化器允许我们为特定的参数组应用不同的超参数。例如,我们可以对除偏差和层归一化项外的所有参数应用权重衰减:

no_decay = ['bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [
    {'params': [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01},
    {'params': [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}
]
optimizer = AdamW(optimizer_grouped_parameters, lr=1e-5)

现在我们可以使用__call__()设置一个简单的虚拟训练批次。这将返回一个 BatchEncoding() 实例,它准备了我们可能需要传递给模型的所有东西。

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
text_batch = ["I love Pixar.", "I don't care for Pixar."]
encoding = tokenizer(text_batch, return_tensors='pt', padding=True, truncation=True)
input_ids = encoding['input_ids']
attention_mask = encoding['attention_mask']

当我们调用一个带有标签参数的分类模型时,第一个返回的元素是预测和传递的标签之间的交叉熵损失。在已经设置好优化器后,我们就可以进行反向传播,更新权重。

labels = torch.tensor([1,0]).unsqueeze(0)
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs.loss
loss.backward()
optimizer.step()

或者,你也可以直接得到logits,然后自己计算损失。下面的示例与前面的示例是等价的:

labels = torch.tensor([1,0])
outputs = model(input_ids, attention_mask=attention_mask)
loss = F.cross_entropy(outputs.logits, labels)
loss.backward()
optimizer.step()

当然,你也可以像往常一样通过调用to('cuda')对模型和输入进行GPU训练。

我们还提供了一些学习率调度工具。通过下面的方法,我们可以设置一个调度器,这个调度器会对num_warmup_steps进行预热,然后在训练结束时线性衰减为0。

from transformers import get_linear_schedule_with_warmup
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps, num_train_steps)

然后,我们要做的就是在optimizer.step()之后调用scheduler.step()。

loss.backward()
optimizer.step()
scheduler.step()

冻结编码器

在某些情况下,你可能会对保持冻结预训练编码器的权重、只优化头部层的权重感兴趣。要做到这一点,只需在编码器参数上将 requires_grad 属性设置为 False,就可以在库中的任何特定任务模型上使用 base_model 子模块进行访问。

for param in model.base_model.parameters():
    param.requires_grad = False

在原生 TensorFlow 2 中进行微调

模型也可以在TensorFlow 2中进行原生训练。就像PyTorch一样,TensorFlow模型可以用from_pretrained()来实例化,从预训练的模型中加载编码器的权重。

from transformers import TFBertForSequenceClassification
model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased')

让我们使用tensorflow_datasets从GLUE加载MRPC数据集。然后我们可以使用内置的glue_convert_examples_to_features()对MRPC进行标记化,并将其转换为TensorFlow Dataset对象。请注意,tokenizer是框架无关的,所以不需要在预训练的tokenizer名称前加上TF。

from transformers import BertTokenizer, glue_convert_examples_to_features
import tensorflow as tf
import tensorflow_datasets as tfds
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
data = tfds.load('glue/mrpc')
train_dataset = glue_convert_examples_to_features(data['train'], tokenizer, max_length=128, task='mrpc')
train_dataset = train_dataset.shuffle(100).batch(32).repeat(2)

该模型可以编译和训练为任何Keras模型:

optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(optimizer=optimizer, loss=loss)
model.fit(train_dataset, epochs=2, steps_per_epoch=115)

Trainer

我们还通过Trainer()TFTrainer()提供了一个简单但功能齐全的训练和评估界面。您可以通过广泛的训练选项和内置的功能(如日志、梯度累积和混合精度)来训练、微调和评估任何🤗Transformers 模型。

PyTorch版:

from transformers import BertForSequenceClassification, Trainer, TrainingArguments

model = BertForSequenceClassification.from_pretrained("bert-large-uncased")

training_args = TrainingArguments(
    output_dir='./results',          # output directory
    num_train_epochs=3,              # total # of training epochs
    per_device_train_batch_size=16,  # batch size per device during training
    per_device_eval_batch_size=64,   # batch size for evaluation
    warmup_steps=500,                # number of warmup steps for learning rate scheduler
    weight_decay=0.01,               # strength of weight decay
    logging_dir='./logs',            # directory for storing logs
)

trainer = Trainer(
    model=model,                         # the instantiated 🤗 Transformers model to be trained
    args=training_args,                  # training arguments, defined above
    train_dataset=train_dataset,         # training dataset
    eval_dataset=test_dataset            # evaluation dataset
)

TensorFlow版:

from transformers import TFBertForSequenceClassification, TFTrainer, TFTrainingArguments

model = TFBertForSequenceClassification.from_pretrained("bert-large-uncased")

training_args = TFTrainingArguments(
    output_dir='./results',          # output directory
    num_train_epochs=3,              # total # of training epochs
    per_device_train_batch_size=16,  # batch size per device during training
    per_device_eval_batch_size=64,   # batch size for evaluation
    warmup_steps=500,                # number of warmup steps for learning rate scheduler
    weight_decay=0.01,               # strength of weight decay
    logging_dir='./logs',            # directory for storing logs
)

trainer = TFTrainer(
    model=model,                         # the instantiated 🤗 Transformers model to be trained
    args=training_args,                  # training arguments, defined above
    train_dataset=tfds_train_dataset,    # tensorflow_datasets training dataset
    eval_dataset=tfds_test_dataset       # tensorflow_datasets evaluation dataset
)

现在只需调用 trainer.training() 进行训练,调用 trainer.evaluation() 进行评估。你也可以使用你自己的模块,但是从 forward 返回的第一个参数必须是你想优化的损失。

Trainer() 使用一个内置的默认函数来整理批次并准备将它们输入模型。如果需要,你也可以使用 data_collator 参数来传递你自己的整理函数,该函数以你的数据集提供的格式来接收数据,并返回一个准备好被输入到模型中的批次。注意 TFTrainer() 期望传递的数据集是来自 tensorflow_datasets 的数据集对象。

要计算除了损失之外的其他指标,你还可以定义自己的 compute_metrics 函数,并将其传递给训练者。

from sklearn.metrics import accuracy_score, precision_recall_fscore_support

def compute_metrics(pred):
    labels = pred.label_ids
    preds = pred.predictions.argmax(-1)
    precision, recall, f1, _ = precision_recall_fscore_support(labels, preds, average='binary')
    acc = accuracy_score(labels, preds)
    return {
        'accuracy': acc,
        'f1': f1,
        'precision': precision,
        'recall': recall
    }

最后,你可以通过在你指定的 logging_dir 目录下启动 tensorboard 来查看结果,包括任何计算的指标。

其他资源

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BERT(Bidirectional Encoder Representations from Transformers)是一种预训练语言模型,可以用于各种自然语言处理任务的微调。下面是BERT预训练微调的简要介绍: BERT预训练: BERT的预训练是指在大规模文本上训练出一个通用的语言模型,然后将这个模型微调到各种具体的NLP任务上。预训练BERT包含两个阶段:Masked Language Model(MLM)和Next Sentence Prediction(NSP)。在MLM阶段,部分输入单词被随机替换成[Mask]标记,模型需要预测这些[Mask]标记对应的原始单词;在NSP阶段,模型需要判断两个句子是否是连续的。BERT的预训练代码可以使用谷歌官方实现的TensorFlow版本或者Hugging Face开发的PyTorch版本。 BERT微调: BERT微调是指在任务特定的数据集上微调训练好的BERT模型。微调步骤包括数据处理、模型配置、模型微调和模型评估。在数据处理阶段,需要将任务特定数据集转换成适合BERT输入的格式;在模型配置阶段,需要根据任务需求选择合适的模型结构、超参数和优化器;在模型微调阶段,需要用微调数据集对模型进行训练;在模型评估阶段,需要使用测试集对微调后的模型进行评估。BERT微调代码可以使用各种框架实现,如PyTorch、TensorFlow等。 如果您想学习更多关于BERT预训练微调的内容,我建议您查看谷歌官方论文和Hugging Face官方文档。此外,您也可以在GitHub上找到各种不同的BERT实现和教程。如果您需要具体的代码示例,可以告诉我您所使用的框架和任务类型,我可以为您提供相关参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值