使用预先训练过的模型有很大的好处。它降低了计算成本,你的碳足印,并允许你使用最先进的模型,而不必从头开始训练一个。Transformer提供了数以千计的预先训练的模型,广泛的任务。当你使用一个预先训练好的模型时,你会在一个特定于你任务的数据集上训练它。他的作品被称为微调,一种非常强大的训练技巧。在本教程中,您将使用自己选择的深度学习框架对一个预先训练好的模型进行微调:
在微调预训练模型之前,请下载数据集并为训练做准备。上一个教程向您展示了如何处理用于训练的数据,现在您有机会对这些技能进行测试!
从加载 Yelp 评论数据集开始:
from datasets import load_dataset
dataset = load_dataset("yelp_review_full")
dataset["train"][100]
{'label': 0,
'text': 'My expectations for McDonalds are t rarely high. But for one to still fail so spectacularly...that takes something special!\\nThe cashier took my friends\'s order, then promptly ignored me. I had to force myself in front of a cashier who opened his register to wait on the person BEHIND me. I waited over five minutes for a gigantic order that included precisely one kid\'s meal. After watching two people who ordered after me be handed their food, I asked where mine was. The manager started yelling at the cashiers for \\"serving off their orders\\" when they didn\'t have their food. But neither cashier was anywhere near those controls, and the manager was the one serving food to customers and clearing the boards.\\nThe manager was rude when giving me my order. She didn\'t make sure that I had everything ON MY RECEIPT, and never even had the decency to apologize that I felt I was getting poor service.\\nI\'ve eaten at various McDonalds restaurants for over 30 years. I\'ve worked at more than one location. I expect bad days, bad moods, and the occasional mistake. But I have yet to have a decent experience at this store. It will remain a place I avoid unless someone in my party needs to avoid illness from low blood sugar. Perhaps I should go back to the racially biased service of Steak n Shake instead!'}
正如您现在所知道的,您需要一个标记器来处理文本,并包含一个填充和截断策略来处理任何可变的序列长度。若要一步处理数据集,请使用 Datasets map 方法对整个数据集应用预处理功能:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
def tokenize_function(examples):
return tokenizer(examples["text"], padding="max_length", truncation=True)
tokenized_datasets = dataset.map(tokenize_function, batched=True)
如果您愿意,您可以创建完整数据集的一个更小的子集来进行微调,以减少所需的时间:
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))
Pytorch
Transformer为训练Transformer模型提供了一个优化的教练班,使其更容易开始训练没有手动编写自己的训练循环E Trainer API 支持广泛的训练选项和特性,如日志记录、梯度累积和混合精度。
首先加载您的模型并指定预期标签的数量。从 Yelp 评论数据卡上,你可以知道有五个标签:
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained("bert-base-cased", num_labels=5)
你会看到一个关于一些预先训练的权重没有被使用的警告和一些权重被随机初始化。别担心,这是完全正常的!去掉 BERT 模型的预训练头,代之以一个随机初始化的分类头。您将在您的序列分类任务上对这个新模型进行微调,将预先训练的模型的知识传递给它。
接下来,创建一个 TrainingArguments 类,其中包含所有可以调优的超参数以及用于激活不同训练选项的标志。对于本教程,您可以从默认的训练超参数开始,但是您可以自由地尝试这些参数以找到您的最佳设置。
指定从训练中保存检查点的位置:
from transformers import TrainingArguments
training_args = TrainingArguments(output_dir="test_trainer")
Trainer不会在训练期间自动评估模型的性能。您将需要传递 Trainer 一个函数来计算和报告度量。数据集库提供了一个简单的精度函数,你可以用 load_metric (参见本教程获取更多信息)函数来加载:
import numpy as np
from datasets import load_metric
metric = load_metric("accuracy")
调用计算公制来计算你的预测的准确性。在将预测传递给计算机之前,您需要将预测转换为 logits (记住所有变形金刚模型都返回 logits) :
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
return metric.compute(predictions=predictions, references=labels)
如果希望在微调过程中监视评估指标,请在训练参数中指定 evaluation_strategy 参数,以在每个历元结束时报告评估指标:
from transformers import TrainingArguments
training_args = TrainingArguments(output_dir="test_trainer", evaluation_strategy="epoch")
用你的模型、训练参数、训练和测试数据集以及评估功能创建一个训练对象:
trainer = Trainer(
model=model,
args=training_args,
train_dataset=small_train_dataset,
eval_dataset=small_eval_dataset,
compute_metrics=compute_metrics,
)
然后通过调用 train ()来微调你的模型:
trainer.train()
TensorFlow
Transformer模型还支持通过 kerasapi 在 TensorFlow 中进行训练。
将数据集转换为 TensorFlow 格式
Defaultdatacolator 将张量装配成一个批处理,供模型进行训练。确保指定 return_TensorFlow 张量返回 TensorFlow 张量:
from transformers import DefaultDataCollator
data_collator = DefaultDataCollator(return_tensors="tf")
Trainer 默认使用 DataCollatorWithPadding,因此不需要显式地指定数据排序器。
接下来,使用 to_tf_dataset 方法将标记化的数据集转换为 TensorFlow 数据集。在列中指定输入,在 label_cols 中指定标签:
tf_train_dataset = small_train_dataset.to_tf_dataset(
columns=["attention_mask", "input_ids", "token_type_ids"],
label_cols=["labels"],
shuffle=True,
collate_fn=data_collator,
batch_size=8,
)
tf_validation_dataset = small_eval_dataset.to_tf_dataset(
columns=["attention_mask", "input_ids", "token_type_ids"],
label_cols=["labels"],
shuffle=False,
collate_fn=data_collator,
batch_size=8,
)
加载带有预期标签数量的 TensorFlow 模型:
import tensorflow as tf
from transformers import TFAutoModelForSequenceClassification
model = TFAutoModelForSequenceClassification.from_pretrained("bert-base-cased", num_labels=5)
然后像使用其他 Keras 模型一样编译和微调你的模型:
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=5e-5),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=tf.metrics.SparseCategoricalAccuracy(),
)
model.fit(tf_train_dataset, validation_data=tf_validation_dataset, epochs=3)
Pytorch
Trainer负责训练循环,并允许您在一行代码中对模型进行微调。对于喜欢编写自己的训练循环的用户,还可以在本地 PyTorch 中微调 Transformers 模型。
在这一点上,你可能需要重新启动你的笔记本或者执行下面的代码来释放一些内存:
del model
del pytorch_model
del trainer
torch.cuda.empty_cache()
接下来,手动对_dataset 进行后处理,以便为训练做准备。
删除文本列,因为模型不接受原始文本作为输入:
tokenized_datasets = tokenized_datasets.remove_columns(["text"])
将标签列重命名为 labels,因为模型期望参数命名为 labels:
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")
设置数据集的格式,返回 PyTorch 张量,而不是列表:
tokenized_datasets.set_format("torch")
然后创建一个更小的数据集子集,如前面所示,以加速微调:
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))
为您的训练和测试数据集创建一个 DataLoader,以便您可以迭代批量数据:
from torch.utils.data import DataLoader
train_dataloader = DataLoader(small_train_dataset, shuffle=True, batch_size=8)
eval_dataloader = DataLoader(small_eval_dataset, batch_size=8)
在模型中加载预期的标签数量:
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained("bert-base-cased", num_labels=5)
创建一个优化器和学习速率调度器来微调模型:
from torch.optim import AdamW
optimizer = AdamW(model.parameters(), lr=5e-5)
从 Trainer 创建默认的学习速率调度器:
from transformers import get_scheduler
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
name="linear", optimizer=optimizer, num_warmup_steps=0, num_training_steps=num_training_steps
)
最后,指定设备使用一个 GPU,如果你有访问。否则,在 CPU 上的训练可能需要几个小时而不是几分钟。
import torch
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)
获得免费访问云 GPU,如果你没有一个托管笔记本电脑像 coloboratory 或 SageMaker StudioLab。
太好了,现在你准备好训练了
为了跟踪您的训练进度,可以使用 tqdm 库在训练步骤的数量上添加一个进度条:
from tqdm.auto import tqdm
progress_bar = tqdm(range(num_training_steps))
model.train()
for epoch in range(num_epochs):
for batch in train_dataloader:
batch = {k: v.to(device) for k, v in batch.items()}
outputs = model(**batch)
loss = outputs.loss
loss.backward()
optimizer.step()
lr_scheduler.step()
optimizer.zero_grad()
progress_bar.update(1)
就像您需要如何向 Trainer 添加评估函数一样,在编写自己的训练循环时也需要这样做。但是,这次不是在每个历元结束时计算和报告度量,而是使用 add_batch 对所有批进行累计,并在最后计算度量。
metric = load_metric("accuracy")
model.eval()
for batch in eval_dataloader:
batch = {k: v.to(device) for k, v in batch.items()}
with torch.no_grad():
outputs = model(**batch)
logits = outputs.logits
predictions = torch.argmax(logits, dim=-1)
metric.add_batch(predictions=predictions, references=batch["labels"])
metric.compute()
TensorFlow
有关更多微调示例,请参阅:
转换器示例包括用于在 PyTorch 和 TensorFlow 中训练常见 NLP 任务的脚本。
Transformers notebook 包含了各种关于如何在 PyTorch 和 TensorFlow 中微调特定任务模型的笔记本电脑。
本文是抱抱脸(Hugging Face)教程中文翻译,仅学习使用
原文链接