USING TRANSFORMERS(二) | 训练和微调

本指南介绍如何使用🤗Transformers库中的标准工具,在PyTorch和TensorFlow2中微调或从头开始训练模型。涵盖使用Trainer类简化训练流程,包括优化器设置、学习率调度及评估。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🤗 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 来查看结果,包括任何计算的指标。

其他资源

使用 HuggingFace 加载微调训练模型非常方便,HuggingFace 提供了 `transformers` 库,支持大量的预训练模型(如 BERT、RoBERTa、GPT、T5 等),并提供简单接口用于加载模型、分词器进行训练。 --- ## ✅ 一、加载预训练模型与分词器 HuggingFace 的 `AutoModel` `AutoTokenizer` 类可以自动识别模型对应的分词器。 ```python from transformers import AutoTokenizer, AutoModelForSequenceClassification # 指定模型名称(如 HuggingFace 上的模型 ID) model_name = "bert-base-uncased" # 加载分词器 tokenizer = AutoTokenizer.from_pretrained(model_name) # 加载预训练模型,并指定输出类别数量(例如分类) model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2) ``` --- ## ✅ 、准备数据集 使用 `datasets` 库加载数据,并进行预处理。 ```python from datasets import load_dataset # 加载一个公开数据集(如 IMDB 电影评论) dataset = load_dataset("imdb") # 对数据进行编码 def tokenize_function(examples): return tokenizer(examples["text"], padding="max_length", truncation=True) tokenized_datasets = dataset.map(tokenize_function, batched=True) # 选择训练测试集 train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000)) eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(100)) ``` --- ## ✅ 三、定义训练参数训练器 使用 `TrainingArguments` `Trainer` 来简化训练流程。 ```python from transformers import TrainingArguments, Trainer training_args = TrainingArguments( output_dir="./results", evaluation_strategy="epoch", learning_rate=2e-5, per_device_train_batch_size=8, num_train_epochs=3, weight_decay=0.01, logging_dir="./logs", logging_steps=10, save_strategy="epoch" ) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, ) ``` --- ## ✅ 四、开始训练 ```python trainer.train() ``` --- ## ✅ 五、保存模型 训练完成后,可以将模型保存到本地或上传到 HuggingFace Hub。 ```python model.save_pretrained("./my_finetuned_model") tokenizer.save_pretrained("./my_finetuned_model") ``` --- ## ✅ 六、使用模型进行预测 ```python from transformers import pipeline # 使用 pipeline 快速推理 classifier = pipeline("text-classification", model="./my_finetuned_model", tokenizer=tokenizer) # 测试一个句子 result = classifier("I love using HuggingFace Transformers!") print(result) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值