Hugging Face 的 Transformers 库为我们提供了大量预训练的 Transformer 模型,以及一个易于使用的训练和微调工具——Trainer。在 Trainer 中,我们可以很容易地启用混合精度训练,也称为自动混合精度 (AMP) 训练。
要在 Hugging Face 的 Trainer 中启用混合精度训练,只需要在创建 Trainer 时设置 fp16=True
。以下是一个例子:
from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
output_dir='./results', # 输出目录
num_train_epochs=3, # 总的训练轮数
per_device_train_batch_size=16, # 每个 GPU 的训练批次大小
per_device_eval_batch_size=64, # 每个 GPU 的评估批次大小
fp16=True, # 启用混合精度训练
# ...
)
trainer = Trainer(
model=model, # 要训练的模型
args=training_args, # 训练参数
train_dataset=train_dataset, # 训练数据集
eval_dataset=test_dataset, # 评估数据集
# ...
)
trainer.train()
请注意,混合精度训练需要 GPU 支持,特别是 NVIDIA 的 Volta 和 Turing 架构以及更高版本的 GPU。如果您在没有这些硬件的环境中启用了混合精度训练,可能会遇到错误。
另外,混合精度训练可以与梯度累积一起使用以进一步提高训练效率。您可以通过设置 gradient_accumulation_steps
参数来实现这一点。
如果你不想使用 Hugging Face 的 Trainer
类,可以使用 PyTorch 的自动混合精度(AMP)功能来进行混合精度训练。以下是一个如何使用 AMP 进行训练的示例:
import torch
from torch.cuda.amp import GradScaler, autocast
from transformers import BertForSequenceClassification, BertTokenizer
# 初始化模型和分词器
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# 选择设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
# 初始化优化器和梯度缩放器
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5)
scaler = GradScaler()
# 假设我们有一个批次的输入数据和标签
inputs = tokenizer("Hello, my dog is cute", return_tensors="pt").to(device)
labels = torch.tensor([1]).unsqueeze(0).to(device) # 假设这是一个二分类问题
model.train() # 设置模型为训练模式
for epoch in range(10): # 训练 10 个周期
optimizer.zero_grad()
with autocast(): # 开启自动混合精度
outputs = model(**inputs, labels=labels)
loss = outputs.loss
scaler.scale(loss).backward() # 使用梯度缩放进行反向传播
scaler.step(optimizer) # 使用梯度缩放更新参数
scaler.update() # 更新梯度缩放器
在这个例子中,我们使用 torch.cuda.amp.autocast
和 torch.cuda.amp.GradScaler
来实现混合精度训练。autocast
上下文管理器将自动为兼容的操作选择合适的数据类型,而 GradScaler
则负责缩放梯度以防止数值下溢。
请注意,这个示例非常基础,真实的训练循环可能会包含更多的逻辑,例如处理多个批次的数据、进行模型评估、保存和加载模型等等。
Hugging Face 的 Accelerate 库提供了一个简单易用的 API,用于在各种硬件配置(如单个或多个 CPU、GPU,甚至是 TPU)上进行分布式和混合精度训练。下面是一个如何使用 Accelerate 库进行混合精度训练的例子:
from accelerate import Accelerator
from torch.utils.data import DataLoader
from transformers import AdamW, BertForSequenceClassification, BertTokenizer
accelerator = Accelerator(fp16=True) # 启用混合精度训练
device = accelerator.device
# 初始化模型和分词器
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = model.to(device)
# 设置优化器
optimizer = AdamW(model.parameters(), lr=1e-5)
optimizer, model = accelerator.prepare(optimizer, model) # 准备优化器和模型
# 假设我们有一个批次的输入数据和标签
inputs = tokenizer("Hello, my dog is cute", return_tensors="pt").to(device)
labels = torch.tensor([1]).unsqueeze(0).to(device) # 假设这是一个二分类问题
model.train() # 设置模型为训练模式
for epoch in range(10): # 训练 10 个周期
optimizer.zero_grad()
outputs = model(**inputs, labels=labels)
loss = outputs.loss
accelerator.backward(loss) # 使用 Accelerate 进行反向传播
optimizer.step()
在这个例子中,我们首先创建一个 Accelerator
对象,并通过设置 fp16=True
来启用混合精度训练。接着,我们使用 accelerator.prepare
函数来准备优化器和模型。最后,在计算损失后,我们使用 accelerator.backward
而不是常规的 loss.backward
来进行反向传播。这将自动应用混合精度训练,无需我们手动管理 autocast 或 GradScaler。
请注意,Accelerate 库的目标是简化分布式和混合精度训练,而不是提供一个完整的训练框架。因此,您可能需要结合 PyTorch(或其他类似的库)来处理数据加载、模型评估、权重保存和加载等任务。