学习笔记:Hugging Face LLM Course - 微调一个预训练模型
https://huggingface.co/learn/llm-course/zh-CN/chapter6/2?fw=pt
引言1
想象你是一位厨师,已经学会了很多基本的烹饪技巧(切菜、炒菜、调味等)。这些技巧就是一个预训练模型,因为可以应用到各种菜肴中。现在你想做一道宫保鸡丁了,虽然你会基本技巧,但是为了能把宫保鸡丁做好,需要根据它的特点做一些调整,比如调整火候,加花生米,调料配比等等。这个过程就是微调。
- 预训练模型:已经学会了很多通用知识的“全能选手”。
- 微调:针对特定任务,让这个“全能选手”变成“专业选手”。
引言2
“微调(Fine-tuning)是自然语言处理(NLP)中的核心技术之一,它允许我们在预训练模型的基础上,针对特定任务进行优化。如何使用Hugging Face的Transformers库微调预训练模型,包括数据准备、模型配置、训练和评估等步骤。”
- 如何从模型中心(hub)加载大型数据集
- 如何使用高级的
Trainer
API 微调一个模型 - 如何使用自定义训练过程
- 如何利用 Accelerate 库在所有分布式设备上轻松运行自定义训练过程
1. 数据集从哪来?
模型中心(hub)不仅仅包含模型,还有许多别的语言的数据集。后续使用 MRPC 数据集(由 5801 对句子组成,每个句子对带有一个标签来指示它们是否为同义)中的 GLUE 基准测试数据集 (通用语言理解评估 (GLUE) 基准是用于训练、评估和分析自然语言理解系统的资源集合)作为我们训练所使用的数据集,它是构成 MRPC 数据集的 10 个数据集之一,作为一个用于衡量机器学习模型在 10 个不同文本分类任务中性能的学术基准。
# pip install datasets
from datasets import load_dataset
raw_datasets = load_dataset("glue", "mrpc") # 该命令(load_dataset)会下载数据集并缓存到 ~/.cache/huggingface/datasets,可以通过设置 HF_HOME 环境变量来自定义缓存的文件夹
raw_datasets
# 可以看到raw_datasets是一个DatasetDict 对象,包含4列。该训练集中有 3668 对句子,验证集中有 408 对,测试集中有 1725 对。
DatasetDict({
train: Dataset({
features: ['sentence1', 'sentence2', 'label', 'idx'],
num_rows: 3668
})
validation: Dataset({
features: ['sentence1', 'sentence2', 'label', 'idx'],
num_rows: 408
})
test: Dataset({
features: ['sentence1', 'sentence2', 'label', 'idx'],
num_rows: 1725
})
})
# 访问训练数据集中的每一个对象:
raw_train_dataset = raw_dataset["train"]
raw_train_dataset[0]
# 输出
{
"idx": 0,
"label": 1,
"sentence1": 'Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
"sentence2": 'Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .',
}
# 查看每列类型
{
"sentence1": Value(dtype="string", id=None),
"sentence2": Value(dtype="string", id=None),
"label": ClassLabel(
num_classes=2, names=["not_equivalent", "equivalent"], names_file=None, id=None
),
"idx": Value(dtype="int32", id=None),
}
raw_train_dataset.features
2. 数据准备
- 需要将文本转换为模型能够理解的数字(通过一个 Tokenizer 完成)
- 示例代码:
from transformers import AutoTokenizer checkpoint = load_dataset("imdb") print(dataset["train"][0]) # 查看第一条数据
定义一个对输入进行tonkenize的函数
def tokenize_function(example):
return tokenizer(example["sentence1"] , example["sentence2"], truncation=True)
raw_datasets.map(tokenize_function, batched=True) # batched=True ,因此该函数会一次性处理数据集的多个元素
# 输出如下
#attention_mask, input_ids,token_type_ids 这三个字段被添加到数据集的三个集合里(训练集、验证集和测试集)
DatasetDict({
train: Dataset({
features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
num_rows: 3668
})
validation: Dataset({
features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
num_rows: 408
})
test: Dataset({
features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
num_rows: 1725
})
})
- 动态填充,DataCollatorWithPadding
# 用法
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
# 例子
samples = tokenized_datasets["train"][:8]
samples = {k:v for k,v in samples.items() if k not in ["idx", "sentence1", "sentence2"]}
[len(x) for x in samples["imputs_idf"]]
# [50, 59, 47, 67, 59, 50, 62, 32]
batch = data_collartor(samples)
{k: v.shape for k, v in batch.items()}
{
"attention_mask": torch.Size([8, 67]),
"input_ids": torch.Size([8, 67]),
"token_type_ids": torch.Size([8, 67]),
"labels": torch.Size([8]),
}
3. 使用 Trainer API 微调模型
- Transformer 提供的 Trainer类可以在数据集上微调任何预训练模型
- 先运行:
from datasets import load_dataset from transformers import AutoTokenizer, DataCollatorWithPadding raw_datasets = load_dataset("glue", "mrpc") checkpoint = "bert-base-uncase" tokenizer = Autookenizer.from_pretrained(checkpoint) def tokenize_function(example): return tokenizer(example["sentence1"],example["sentence2"],truncaton=Ture) tokenized_datasets = raw_datasets.map(tokenize_function,batched=True) data_collator = DataCollatorWithpadding(tokenizer=tokenizer)
Training
# 定义Trainer 之前要定义一个TrainingArguments类,它包含Trainer在训练和评估中使用的所有超参数
#
from transformers import TrainingArguments
training_args = TrainingArguments("test-trainer")
# 使用AutoModelForSequenceClassification定义模型
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(chenckpoint, num_labels=2)
# 有了模型之后定义一个Trainer把到目前为止构建的所有对象——model,training_args, 训练和验证数据集,data_collator 和tokenizer传递给Trainer:
from transormers import Trainer
trainer = Trainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
data_collator=data_collator,
tokenizer=tokenizer,
)
# 在此数据集上进行微调,只需要调用Trainer 的 train()方法
trainer.train()
- 评估
-
preditions = trainer.predict(tokenized_datasets["validation"]) print(predictions.predictions.shape, predictions.label_ids.shape) import numpy as np preds = np.argmax(predictions.predictions, axis=-1) import evaluate metric = evaluate.load("glue" , "mrpc") metric.compute(predictions=preds, references=predictions.label_ids) {'accuracy': 0.8578431372549019, 'f1': 0.8996539792387542} ## def compute_metrics(eval_preds): metrics = eval.load("glue","mrpc") logits,labels = eval_preds predictions = ng.argmax(logits, axis=-1) return metric.compute(predictions=predictions, references=labels) trainer = Trainer( model, ... compute_metrics=compute_metics, )
4. 一个完整的训练
总结
总结本章的核心知识点:
- 微调是利用预训练模型针对特定任务进行优化的高效方法。
- 数据准备、模型配置、训练和评估是微调的关键步骤。
- Hugging Face的
Trainer
类简化了微调过程,提供了灵活的配置选项。
互动与反馈
鼓励读者在评论区分享他们的学习心得或提出问题。例如:
“你在微调预训练模型时遇到过哪些挑战?欢迎在评论区分享你的经验!”
参考资料
列出本章课程的相关链接和文档,方便读者进一步学习:
通过以上结构,你的学习博客将内容清晰、逻辑严谨,同时兼具实用性和互动性,能够有效帮助其他学习者理解和掌握相关知识。
更多推荐
所有评论(0)