PyTorch2.0 Transformers
PyTorch 2.0 完全向后兼容,不需要对现有 PyTorch 代码进行任何修改,但可以通过使用 model = torch.compile(model) 添加一行代码来优化你的代码。
如果你问为什么有一个新的主要版本而没有重大更改? PyTorch 团队在他们的常见问题解答中回答了这个问题:“我们正在发布大量新功能,我们相信这些功能会改变你有意义地使用 PyTorch 的方式,因此我们将其称为 2.0。”
这些新功能包括对 TorchDynamo、AOTAutograd、PrimTorch 和 TorchInductor 的顶级支持。
这使 PyTorch 2.0 能够实现 1.3 倍到 2 倍的训练时间加速,支持来自 HuggingFace Transformers 的当今 46 种模型架构
1、搭建环境 & 安装Pytorch 2.0
我们的第一步是安装 PyTorch 2.0 和 Hugging Face Libraries,包括transformers和数据集。
# Install PyTorch 2.0 with cuda 11.7
!pip install "torch>=2.0" --extra-index-url https://download.pytorch.org/whl/cu117 --upgrade --quiet
此外,我们正在从主 git 分支安装最新版本的transformers,其中包括将 PyTorch 2.0 原生集成到 Trainer 中。
# Install transformers and dataset
!pip install "transformers==4.27.1" "datasets==2.9.0" "accelerate==0.17.1" "evaluate==0.4.0" tensorboard scikit-learn
# Install git-fls for pushing model and logs to the hugging face hub
!sudo apt-get install git-lfs --yes
此示例将使用 Hugging Face Hub 作为远程模型版本控制服务。 要将我们的模型推送到 Hub,你必须在 Hugging Face 上注册。 如果你已经有一个帐户,则可以跳过此步骤。 拥有帐户后,我们将使用 huggingface_hub 包中的登录实用程序登录我们的帐户并将我们的令牌(访问密钥)存储在磁盘上。
from huggingface_hub import login
login(
token="", # ADD YOUR TOKEN HERE
add_to_git_credential=True
)
2、加载并准备数据集
为了使示例简单明了,我们正在 BANKING77 数据集上训练文本分类模型。 BANKING77 数据集在银行/金融领域提供一组细粒度的意图(类)。 它包含 13,083 个标有 77 个意图的客户服务查询。 它专注于细粒度的单域意图检测。
我们将使用 🤗 Datasets 库中的 load_dataset()
方法来加载 banking77。
from datasets import load_dataset
# Dataset id from huggingface.co/dataset
dataset_id = "banking77"
# Load raw dataset
raw_dataset = load_dataset(dataset_id)
print(f"Train dataset size: {len(raw_dataset['train'])}")
print(f"Test dataset size: {len(raw_dataset['test'])}")
让我们看看数据集的一个例子。
from random import randrange
random_id = randrange(len(raw_dataset['train']))
raw_dataset['train'][random_id]
# {'text': "I can't get google pay to work right.", 'label': 2}
为了训练模型,我们需要将我们的“自然语言”转换为令牌 ID。 这是由 Tokenizer 完成的,它对输入进行标记化(包括将标记转换为预训练词汇表中相应的 ID),如果想了解更多相关信息,请参阅 Hugging Face Course 的第 6 章。
from transformers import AutoTokenizer
# Model id to load the tokenizer
model_id = "bert-base-uncased"
# Load Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Tokenize helper function
def tokenize(batch):
return tokenizer(batch['text'], padding='max_length', truncation=True, return_tensors="pt")
# Tokenize dataset
raw_dataset = raw_dataset.rename_column("label", "labels") # to match Trainer
tokenized_dataset = raw_dataset.map(tokenize, batched=True,remove_columns=["text"])
print(tokenized_dataset["train"].features.keys())
# dict_keys(['input_ids', 'token_type_ids', 'attention_mask','lable'])
3、微调和评估 BERT 模型
处理完数据集后,我们就可以开始训练模型了。 我们将使用 bert-base-uncased 模型。 第一步是使用 Hugging Face Hub 中的 AutoModelForSequenceClassification 类加载我们的模型。 这将初始化预训练的 BERT 权重,并将分类头置于顶部。 在这里,我们从数据集中传递类数 (77) 和标签名称,以获得可读的推理输出。
from transformers import AutoModelForSequenceClassification
# Model id to load the tokenizer
model_id = "bert-base-uncased"
# Prepare model labels - useful for inference
labels = tokenized_dataset["train"].features["labels"].names
num_labels = len(labels)
label2id, id2label = dict(), dict()
for i, label in enumerate(labels):
label2id[label] = str(i)
id2label[str(i)] = label
# Download the model from huggingface.co/models
model = AutoModelForSequenceClassification.from_pretrained(
model_id, num_labels=num_labels, label2id=label2id, id2label=id2label
)
我们在训练期间评估模型。 Trainer 通过提供 compute_metrics 方法支持训练期间的评估。 我们使用评估库在测试拆分训练期间计算 f1 指标。
import evaluate
import numpy as np
# Metric Id
metric = evaluate.load("f1")
# Metric helper method
def compute_metrics(eval_pred):
predictions, labels = eval_pred
predictions = np.argmax(predictions, axis=1)
return metric.compute(predictions=predictions, references=labels, average="weighted")
最后一步是定义我们用于训练的超参数 (TrainingArguments)。 在这里,我们添加了 PyTorch 2.0 引入的功能以加快训练时间。 要使用 PyTorch 2.0 的最新改进,我们只需要在 TrainingArguments 中传递 torch_compile 选项。
我们还利用 Trainer 的 Hugging Face Hub 集成将训练期间的检查点、日志和指标推送到存储库中。
from huggingface_hub import HfFolder
from transformers import Trainer, TrainingArguments
# Id for remote repository
repository_id = "bert-base-banking77-pt2"
# Define training args
training_args = TrainingArguments(
output_dir=repository_id,
per_device_train_batch_size=16,
per_device_eval_batch_size=8,
learning_rate=5e-5,
num_train_epochs=3,
# PyTorch 2.0 specifics
bf16=True, # bfloat16 training
torch_compile=True, # optimizations
optim="adamw_torch_fused", # improved optimizer
# logging & evaluation strategies
logging_dir=f"{repository_id}/logs",
logging_strategy="steps",
logging_steps=200,
evaluation_strategy="epoch",
save_strategy="epoch",
save_total_limit=2,
load_best_model_at_end=True,
metric_for_best_model="f1",
# push to hub parameters
report_to="tensorboard",
push_to_hub=True,
hub_strategy="every_save",
hub_model_id=repository_id,
hub_token=HfFolder.get_token(),
)
# Create a Trainer instance
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset["train"],
eval_dataset=tokenized_dataset["test"],
compute_metrics=compute_metrics,
)
我们可以使用 Trainer 的 train 方法开始我们的训练。
# Start training
trainer.train()
使用 Pytorch 2.0 和转换器中支持的功能,我们可以在 457.7964 秒内用 10_000 个样本训练我们的 BERT 模型。
我们还在没有 torch_compile 选项的情况下运行训练来比较训练时间。 没有 torch_compile 的训练耗时 457 秒,train_samples_per_second 值为 65.55,f1 分数为 0.931。
{'train_runtime': 696.2701, 'train_samples_per_second': 43.1, 'eval_f1': 0.928788}
通过使用 torch_compile 选项和 adamw_torch_fused 优化,我们可以看到与没有 PyTorch 2.0 的训练相比,训练时间减少了 52.5%。
{'train_runtime': 457.7964, 'train_samples_per_second': 65.55, 'eval_f1': 0.931773}
我们的绝对训练时间从 696 秒减少到 457。train_samples_per_second 值从 43 增加到 65。f1 分数与没有 torch_compile 的训练相同/略好。
Pytorch 2.0 强大到难以置信! 🚀
让我们将结果和分词器保存到 Hugging Face Hub 并创建一个模型卡。
# Save processor and create model card
tokenizer.save_pretrained(repository_id)
trainer.create_model_card()
trainer.push_to_hub()
4、运行推理和测试模型
为了结束本教程,我们将对一些示例进行推理并测试我们的模型。 我们将使用 transformers 库中的管道方法对我们的模型进行推理。
from transformers import pipeline
# load model from huggingface.co/models using our repository id
classifier = pipeline("sentiment-analysis", model=repository_id, tokenizer=repository_id, device=0)
sample = "I have been waiting longer than expected for my bank card, could you provide information on when it will arrive?"
pred = classifier(sample)
print(pred)
# [{'label': 'card_arrival', 'score': 0.9903606176376343}]
5、结束语
在本教程中,我们学习了如何使用 PyTorch 2.0 在 BANKING77 数据集上训练文本分类模型。 我们看到 PyTorch 2.0 是一个强大的工具,可以加快你的训练时间。 在我们在 NVIDIA A10G 上运行的示例中,我们设法实现了 52.5% 的性能提升。
Hugging Face Trainer 允许你通过简单地将 torch_compile 选项添加到 TrainingArguments 来轻松地将 PyTorch 2.0 集成到您的训练管道中。 当 bf16 可用时,我们可以通过使用新的融合 AdamW 优化器进一步受益于 PyTorch 2.0。
此外,我想提一下,我们将训练时间减少了 52%,这可以解释为培训成本节省了 52%,或者迭代周期和生产时间缩短了 52%。 通过使用 A100 GPU 或减少“Trainer”开销,你应该能够看到更好的改进,例如 删除评估和日志记录。
原文链接:Getting started with Pytorch 2.0 and Hugging Face Transformers
BimAnt翻译整理,转载请标明出处