在开始之前,请确保安装了所有必要的库:
pip install transformers datasets evaluate accelerate
在这一步,需要登录你的 Hugging Face 帐户,出现相关的登陆提示时,输入你的令牌以登录:
from huggingface_hub import notebook_login
notebook_login()
加载 IMDB 数据集¶
首先,从 IMDB 数据库中加载 IMDB 数据集:
from datasets import load_dataset
imdb = load_dataset("imdb")
再看一个例子:
imdb["test"][0]
此数据集中有两个字段:
text:电影评论的文本。label:一个整数值,0表示负面评价,1表示正面评价。
预处理数据¶
下一步是加载一个 DistilBERT Tokenizer 来预处理text字段:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")
创建一个预处理函数来标记文本并截断序列,使其不超过 DistilBERT 的最大输入长度:
def preprocess_function(examples):
return tokenizer(examples["text"], truncation=True)
若要对整个数据集应用预处理函数,请使用函数 Datasets.map()。你可以通过设置batched=True来一次性处理数据集的多个元素来加速 map:
tokenized_imdb = imdb.map(preprocess_function, batched=True)
现在使用DataCollatorWithPadding创建一批示例。
在排序过程中,会动态地将句子填充到与这一批数据中最长序列相同的长度,而不是将整个数据集都填充到最大长度,这样会更有效率。
# PyTorch
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
# TensorFlow
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer, return_tensors="tf")
评估模型¶
在训练模型时,选择一个合适的指标来评估模型的表现非常重要。
你可以使用“Evaluate”这个工具库,轻松地加载和使用各种评估方法。对于这个任务,我们需要加载一个叫做“accuracy 准确度”的度量指标。
你可以参考Evaluate 快速指南,那里有详细的步骤教你如何加载和计算这些指标。
import evaluate
accuracy = evaluate.load("accuracy")
然后,创建一个函数,将你的预测和标签传递给 computing 来计算准确度:
import numpy as np
def compute_metrics(eval_pred):
predictions, labels = eval_pred
predictions = np.argmax(predictions, axis=1)
return accuracy.compute(predictions=predictions, references=labels)
compute_metrics这个函数现在已经准备好了。当你开始设置训练过程时,你会再次用到它。
训练模型¶
在开始训练模型之前,我们需要用id2label和label2id来建立一个映射关系,这样就能把模型的输出编号转换成我们看得懂的标签了。
id2label = {0: "NEGATIVE", 1: "POSITIVE"}
label2id = {"NEGATIVE": 0, "POSITIVE": 1}
from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert/distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id
)
此时,只剩下三个步骤:
- 设置训练参数:在
TrainingArguments中定义训练的超参数。这里最重要的是output_dir参数,它用来指定保存模型的位置。如果你想把模型上传到Hugging Face,需要设置push_to_hub=True(记得先登录Hugging Face账号)。在每个训练周期(epoch)结束时,Trainer会自动评估模型的准确性,并保存训练的检查点。 - 配置
Trainer:把训练参数、模型、数据集、分词器(tokenizer)、数据整理器(data collator)以及compute_metrics函数一起传递给 Trainer。 - 开始训练:调用
train()方法来微调你的模型。
training_args = TrainingArguments(
output_dir="my_awesome_model",
learning_rate=2e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
num_train_epochs=2,
weight_decay=0.01,
eval_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
push_to_hub=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_imdb["train"],
eval_dataset=tokenized_imdb["test"],
processing_class=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
trainer.train()
当你传递tokenizer给Trainer的时候,它会默认使用动态填充功能。在这种情况下,你不需要手动地指定一个数据整理器。
训练完成后,可以使用 push_to_hub() 方法将你的模型共享到 Hub,以便每个人都可以使用你的模型:
trainer.push_to_hub()
from transformers import create_optimizer
import tensorflow as tf
batch_size = 16
num_epochs = 5
batches_per_epoch = len(tokenized_imdb["train"]) // batch_size
total_train_steps = int(batches_per_epoch * num_epochs)
optimizer, schedule = create_optimizer(init_lr=2e-5, num_warmup_steps=0, num_train_steps=total_train_steps)
接下来,你可以使用TFAutoModelForSequenceClassification来加载DistilBERT模型,同时指定预期的标签数量和标签映射关系:
from transformers import TFAutoModelForSequenceClassification
model = TFAutoModelForSequenceClassification.from_pretrained(
"distilbert/distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id
)
使用prepare_tf_dataset()将数据集转换为tf.data.Dataset格式:
tf_train_set = model.prepare_tf_dataset(
tokenized_imdb["train"],
shuffle=True,
batch_size=16,
collate_fn=data_collator,
)
tf_validation_set = model.prepare_tf_dataset(
tokenized_imdb["test"],
shuffle=False,
batch_size=16,
collate_fn=data_collator,
)
使用compile方法来配置模型进行训练。需要注意的是,Transformers库中的模型已经内置了与任务相关的默认损失函数,所以通常情况下你不需要手动指定损失函数,除非你有特别的需要:
import tensorflow as tf
model.compile(optimizer=optimizer) # 没有指定损失函数
在开始训练之前,还需要完成最后两个步骤:
- 计算预测的准确性:我们需要评估模型预测的准确性。
- 提供模型上传到Hub的方法:这样可以将训练好的模型分享到Hugging Face的Hub。
这两个步骤都可以通过使用Keras回调来实现。
具体来说,你可以将compute_metrics函数传递给KerasMetricCallback:
from transformers.keras_callbacks import KerasMetricCallback
metric_callback = KerasMetricCallback(metric_fn=compute_metrics, eval_dataset=tf_validation_set)
在PushToHubCallback中指定将模型和 tokenizer 推送到何处:
from transformers.keras_callbacks import PushToHubCallback
push_to_hub_callback = PushToHubCallback(
output_dir="my_awesome_model",
tokenizer=tokenizer,
)
接下来,把你的回调函数组合在一起:
callbacks = [metric_callback, push_to_hub_callback]
最后,可以开始训练你的模型啦!调用fit方法,传入你的训练和验证数据集、训练周期(epoch)的数量以及你设置的回调函数,这样就能微调你的模型了:
model.fit(x=tf_train_set, validation_data=tf_validation_set, epochs=3, callbacks=callbacks)
训练完成后,你的模型将自动上传到Hub,以便每个人都可以使用它!
text = "This was a masterpiece. Not completely faithful to the books, but enthralling from beginning to end. Might be my favorite of the three."
要尝试使用微调后的模型进行推理,最简单的方法是通过 pipeline 来操作。你可以用你的模型创建一个专门用于情感分析的 pipeline,然后把你的文本输入进去:
from transformers import pipeline
classifier = pipeline("sentiment-analysis", model="stevhliu/my_awesome_model")
classifier(text)
如果有需要,你还可以手动复制 pipeline 的结果:
PyTorch¶
- 标记文本并返回PyTorch张量:对输入文本进行分词处理,并将其转换为PyTorch张量格式。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model")
inputs = tokenizer(text, return_tensors="pt")
- 将输入传递给模型并返回logits:把处理好的张量输入到模型中,获取模型的输出
logits。
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model")
with torch.no_grad():
logits = model(**inputs).logits
- 获取概率最高的类别,并使用模型的
id2label映射将其转换为文本标签:从logits中找出概率最高的类别,然后利用模型的id2label映射关系,将其转换成对应的文本标签。
predicted_class_id = logits.argmax().item()
model.config.id2label[predicted_class_id]
TensorFlow¶
- 标记文本并返回PyTorch张量:对输入文本进行分词处理,并将其转换为PyTorch张量格式。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model")
inputs = tokenizer(text, return_tensors="tf")
- 将输入传递给模型并返回logits:把处理好的张量输入到模型中,获取模型的输出
logits。
from transformers import TFAutoModelForSequenceClassification
model = TFAutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model")
logits = model(**inputs).logits
- 获取概率最高的类别,并使用模型的
id2label映射将其转换为文本标签:从logits中找出概率最高的类别,然后利用模型的id2label映射关系,将其转换成对应的文本标签。
predicted_class_id = int(tf.math.argmax(logits, axis=-1)[0])
model.config.id2label[predicted_class_id]