0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用LoRA和Hugging Face高效训练大语言模型

深度学习自然语言处理 来源:Hugging Face 2023-04-14 17:37 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在本文中,我们将展示如何使用 大语言模型低秩适配 (Low-Rank Adaptation of Large Language Models,LoRA) 技术在单 GPU 上微调 110 亿参数的 FLAN-T5 XXL 模型。在此过程中,我们会使用到 Hugging Face 的 TransformersAccelerate 和 PEFT 库。

快速入门: 轻量化微调 (Parameter Efficient Fine-Tuning,PEFT)

PEFT 是 Hugging Face 的一个新的开源库。使用 PEFT 库,无需微调模型的全部参数,即可高效地将预训练语言模型 (Pre-trained Language Model,PLM) 适配到各种下游应用。

注意: 本教程是在 g5.2xlarge AWS EC2 实例上创建和运行的,该实例包含 1 个 NVIDIA A10G

1. 搭建开发环境

在本例中,我们使用 AWS 预置的 PyTorch 深度学习 AMI,其已安装了正确的 CUDA 驱动程序和 PyTorch。在此基础上,我们还需要安装一些 Hugging Face 库,包括 transformers 和 datasets。运行下面的代码就可安装所有需要的包。

#installHuggingFaceLibraries
!pipinstallgit+https://github.com/huggingface/peft.git
!pipinstall"transformers==4.27.1""datasets==2.9.0""accelerate==0.17.1""evaluate==0.4.0""bitsandbytes==0.37.1"loralib--upgrade--quiet
#installadditionaldependenciesneededfortraining
!pipinstallrouge-scoretensorboardpy7zr

2. 加载并准备数据集

这里,我们使用 samsum 数据集,该数据集包含大约 16k 个含摘要的聊天类对话数据。这些对话由精通英语的语言学家制作。

{
"id":"13818513",
"summary":"AmandabakedcookiesandwillbringJerrysometomorrow.",
"dialogue":"Amanda:Ibakedcookies.Doyouwantsome?
Jerry:Sure!
Amanda:I'llbringyoutomorrow:-)"
}

我们使用 Datasets 库中的 load_dataset() 方法来加载 samsum 数据集。

fromdatasetsimportload_dataset

#Loaddatasetfromthehub
dataset=load_dataset("samsum")

print(f"Traindatasetsize:{len(dataset['train'])}")
print(f"Testdatasetsize:{len(dataset['test'])}")

#Traindatasetsize:14732
#Testdatasetsize:819

为了训练模型,我们要用 Transformers Tokenizer 将输入文本转换为词元 ID。

fromtransformersimportAutoTokenizer,AutoModelForSeq2SeqLM

model_id="google/flan-t5-xxl"

#LoadtokenizerofFLAN-t5-XL
tokenizer=AutoTokenizer.from_pretrained(model_id)

在开始训练之前,我们还需要对数据进行预处理。生成式文本摘要属于文本生成任务。我们将文本输入给模型,模型会输出摘要。我们需要了解输入和输出文本的长度信息,以利于我们高效地批量处理这些数据。

fromdatasetsimportconcatenate_datasets
importnumpyasnp
#Themaximumtotalinputsequencelengthaftertokenization.
#Sequenceslongerthanthiswillbetruncated,sequencesshorterwillbepadded.
tokenized_inputs=concatenate_datasets([dataset["train"],dataset["test"]]).map(lambdax:tokenizer(x["dialogue"],truncation=True),batched=True,remove_columns=["dialogue","summary"])
input_lenghts=[len(x)forxintokenized_inputs["input_ids"]]
#take85percentileofmaxlengthforbetterutilization
max_source_length=int(np.percentile(input_lenghts,85))
print(f"Maxsourcelength:{max_source_length}")

#Themaximumtotalsequencelengthfortargettextaftertokenization.
#Sequenceslongerthanthiswillbetruncated,sequencesshorterwillbepadded."
tokenized_targets=concatenate_datasets([dataset["train"],dataset["test"]]).map(lambdax:tokenizer(x["summary"],truncation=True),batched=True,remove_columns=["dialogue","summary"])
target_lenghts=[len(x)forxintokenized_targets["input_ids"]]
#take90percentileofmaxlengthforbetterutilization
max_target_length=int(np.percentile(target_lenghts,90))
print(f"Maxtargetlength:{max_target_length}")

我们将在训练前统一对数据集进行预处理并将预处理后的数据集保存到磁盘。你可以在本地机器或 CPU 上运行此步骤并将其上传到 Hugging Face Hub。

defpreprocess_function(sample,padding="max_length"):
#addprefixtotheinputfort5
inputs=["summarize:"+itemforiteminsample["dialogue"]]

#tokenizeinputs
model_inputs=tokenizer(inputs,max_length=max_source_length,padding=padding,truncation=True)

#Tokenizetargetswiththe`text_target`keywordargument
labels=tokenizer(text_target=sample["summary"],max_length=max_target_length,padding=padding,truncation=True)

#Ifwearepaddinghere,replacealltokenizer.pad_token_idinthelabelsby-100whenwewanttoignore
#paddingintheloss.
ifpadding=="max_length":
labels["input_ids"]=[
[(lifl!=tokenizer.pad_token_idelse-100)forlinlabel]forlabelinlabels["input_ids"]
]

model_inputs["labels"]=labels["input_ids"]
returnmodel_inputs

tokenized_dataset=dataset.map(preprocess_function,batched=True,remove_columns=["dialogue","summary","id"])
print(f"Keysoftokenizeddataset:{list(tokenized_dataset['train'].features)}")

#savedatasetstodiskforlatereasyloading
tokenized_dataset["train"].save_to_disk("data/train")
tokenized_dataset["test"].save_to_disk("data/eval")

3. 使用 LoRA 和 bnb int-8 微调 T5

除了 LoRA 技术,我们还使用 bitsanbytes LLM.int8() 把冻结的 LLM 量化为 int8。这使我们能够将 FLAN-T5 XXL 所需的内存降低到约四分之一。

训练的第一步是加载模型。我们使用 philschmid/flan-t5-xxl-sharded-fp16 模型,它是 google/flan-t5-xxl 的分片版。分片可以让我们在加载模型时不耗尽内存。

fromtransformersimportAutoModelForSeq2SeqLM

#huggingfacehubmodelid
model_id="philschmid/flan-t5-xxl-sharded-fp16"

#loadmodelfromthehub
model=AutoModelForSeq2SeqLM.from_pretrained(model_id,load_in_8bit=True,device_map="auto")

现在,我们可以使用 peft 为 LoRA int-8 训练作准备了。

frompeftimportLoraConfig,get_peft_model,prepare_model_for_int8_training,TaskType

#DefineLoRAConfig
lora_config=LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q","v"],
lora_dropout=0.05,
bias="none",
task_type=TaskType.SEQ_2_SEQ_LM
)
#prepareint-8modelfortraining
model=prepare_model_for_int8_training(model)

#addLoRAadaptor
model=get_peft_model(model,lora_config)
model.print_trainable_parameters()

#trainableparams:18874368||allparams:11154206720||trainable%:0.16921300163961817

如你所见,这里我们只训练了模型参数的 0.16%!这个巨大的内存增益让我们安心地微调模型,而不用担心内存问题。

接下来需要创建一个 DataCollator,负责对输入和标签进行填充,我们使用 Transformers 库中的 DataCollatorForSeq2Seq 来完成这一环节。

fromtransformersimportDataCollatorForSeq2Seq

#wewanttoignoretokenizerpadtokenintheloss
label_pad_token_id=-100
#Datacollator
data_collator=DataCollatorForSeq2Seq(
tokenizer,
model=model,
label_pad_token_id=label_pad_token_id,
pad_to_multiple_of=8
)

最后一步是定义训练超参 ( TrainingArguments)。

fromtransformersimportSeq2SeqTrainer,Seq2SeqTrainingArguments

output_dir="lora-flan-t5-xxl"

#Definetrainingargs
training_args=Seq2SeqTrainingArguments(
output_dir=output_dir,
auto_find_batch_size=True,
learning_rate=1e-3,#higherlearningrate
num_train_epochs=5,
logging_dir=f"{output_dir}/logs",
logging_strategy="steps",
logging_steps=500,
save_strategy="no",
report_to="tensorboard",
)

#CreateTrainerinstance
trainer=Seq2SeqTrainer(
model=model,
args=training_args,
data_collator=data_collator,
train_dataset=tokenized_dataset["train"],
)
model.config.use_cache=False#silencethewarnings.Pleasere-enableforinference!

运行下面的代码,开始训练模型。请注意,对于 T5,出于收敛稳定性考量,某些层我们仍保持 float32 精度。

#trainmodel
trainer.train()

训练耗时约 10 小时 36 分钟,训练 10 小时的成本约为 13.22 美元。相比之下,如果 在 FLAN-T5-XXL 上进行全模型微调 10 个小时,我们需要 8 个 A100 40GB,成本约为 322 美元。

我们可以将模型保存下来以用于后面的推理和评估。我们暂时将其保存到磁盘,但你也可以使用 model.push_to_hub 方法将其上传到 Hugging Face Hub。

#SaveourLoRAmodel&tokenizerresults
peft_model_id="results"
trainer.model.save_pretrained(peft_model_id)
tokenizer.save_pretrained(peft_model_id)
#ifyouwanttosavethebasemodeltocall
#trainer.model.base_model.save_pretrained(peft_model_id)

最后生成的 LoRA checkpoint 文件很小,仅需 84MB 就包含了从 samsum 数据集上学到的所有知识。

4. 使用 LoRA FLAN-T5 进行评估和推理

我们将使用 evaluate 库来评估 rogue 分数。我们可以使用 PEFT 和 transformers 来对 FLAN-T5 XXL 模型进行推理。对 FLAN-T5 XXL 模型,我们至少需要 18GB 的 GPU 显存。

importtorch
frompeftimportPeftModel,PeftConfig
fromtransformersimportAutoModelForSeq2SeqLM,AutoTokenizer

#Loadpeftconfigforpre-trainedcheckpointetc.
peft_model_id="results"
config=PeftConfig.from_pretrained(peft_model_id)

#loadbaseLLMmodelandtokenizer
model=AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path,load_in_8bit=True,device_map={"":0})
tokenizer=AutoTokenizer.from_pretrained(config.base_model_name_or_path)

#LoadtheLoramodel
model=PeftModel.from_pretrained(model,peft_model_id,device_map={"":0})
model.eval()

print("Peftmodelloaded")

我们用测试数据集中的一个随机样本来试试摘要效果。

fromdatasetsimportload_dataset
fromrandomimportrandrange

#Loaddatasetfromthehubandgetasample
dataset=load_dataset("samsum")
sample=dataset['test'][randrange(len(dataset["test"]))]

input_ids=tokenizer(sample["dialogue"],return_tensors="pt",truncation=True).input_ids.cuda()
#withtorch.inference_mode():
outputs=model.generate(input_ids=input_ids,max_new_tokens=10,do_sample=True,top_p=0.9)
print(f"inputsentence:{sample['dialogue']}
{'---'*20}")

print(f"summary:
{tokenizer.batch_decode(outputs.detach().cpu().numpy(),skip_special_tokens=True)[0]}")

不错!我们的模型有效!现在,让我们仔细看看,并使用 test 集中的全部数据对其进行评估。为此,我们需要实现一些工具函数来帮助生成摘要并将其与相应的参考摘要组合到一起。评估摘要任务最常用的指标是 rogue_score,它的全称是 Recall-Oriented Understudy for Gisting Evaluation。与常用的准确率指标不同,它将生成的摘要与一组参考摘要进行比较。

importevaluate
importnumpyasnp
fromdatasetsimportload_from_disk
fromtqdmimporttqdm

#Metric
metric=evaluate.load("rouge")

defevaluate_peft_model(sample,max_target_length=50):
#generatesummary
outputs=model.generate(input_ids=sample["input_ids"].unsqueeze(0).cuda(),do_sample=True,top_p=0.9,max_new_tokens=max_target_length)
prediction=tokenizer.decode(outputs[0].detach().cpu().numpy(),skip_special_tokens=True)
#decodeevalsample
#Replace-100inthelabelsaswecan'tdecodethem.
labels=np.where(sample['labels']!=-100,sample['labels'],tokenizer.pad_token_id)
labels=tokenizer.decode(labels,skip_special_tokens=True)

#Somesimplepost-processing
returnprediction,labels

#loadtestdatasetfromdistk
test_dataset=load_from_disk("data/eval/").with_format("torch")

#runpredictions
#thiscantake~45minutes
predictions,references=[],[]
forsampleintqdm(test_dataset):
p,l=evaluate_peft_model(sample)
predictions.append(p)
references.append(l)

#computemetric
rogue=metric.compute(predictions=predictions,references=references,use_stemmer=True)

#printresults
print(f"Rogue1:{rogue['rouge1']*100:2f}%")
print(f"rouge2:{rogue['rouge2']*100:2f}%")
print(f"rougeL:{rogue['rougeL']*100:2f}%")
print(f"rougeLsum:{rogue['rougeLsum']*100:2f}%")

#Rogue1:50.386161%
#rouge2:24.842412%
#rougeL:41.370130%
#rougeLsum:41.394230%

我们 PEFT 微调后的 FLAN-T5-XXL 在测试集上取得了 50.38% 的 rogue1 分数。相比之下,flan-t5-base 的全模型微调获得了 47.23 的 rouge1 分数。rouge1 分数提高了 3%。

令人难以置信的是,我们的 LoRA checkpoint 只有 84MB,而且性能比对更小的模型进行全模型微调后的 checkpoint 更好。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • PLM
    PLM
    +关注

    关注

    2

    文章

    150

    浏览量

    22194
  • AWS
    AWS
    +关注

    关注

    0

    文章

    444

    浏览量

    26628
  • LoRa模块
    +关注

    关注

    5

    文章

    155

    浏览量

    15384
  • pytorch
    +关注

    关注

    2

    文章

    813

    浏览量

    14921

原文标题:使用 LoRA 和 Hugging Face 高效训练大语言模型

文章出处:【微信号:zenRRan,微信公众号:深度学习自然语言处理】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Edge Impulse 唤醒词模型训练 | 技术集结

    今天,将手把手带领学习如何训练一个语音关键词模型部署到嵌入式硬件上,采用Edgi-Talk平台适配EdgeImpulse,当然原理在其他的ARM嵌入式平台也是通用的。让我们看看如何让
    的头像 发表于 04-20 10:05 216次阅读
    Edge Impulse 唤醒词<b class='flag-5'>模型</b><b class='flag-5'>训练</b> | 技术集结

    NVIDIA Alpamayo 1模型Hugging Face平台下载量已突破10万次

    NVIDIA Alpamayo 1 在 Hugging Face 的下载量已突破 10 万次,且仍在持续增长,已成为 Hugging Face 平台下载量最高的机器人
    的头像 发表于 03-04 16:27 951次阅读

    训练到推理:大模型算力需求的新拐点已至

    在大模型产业发展的早期阶段,行业焦点主要集中在大模型训练所需的算力投入。一个万亿参数大模型训练可能需要数千张GPU芯片连续运行数月,成本高
    的头像 发表于 02-05 16:07 1008次阅读
    从<b class='flag-5'>训练</b>到推理:大<b class='flag-5'>模型</b>算力需求的新拐点已至

    什么是大模型,智能体...?大模型100问,快速全面了解!

    一、概念篇1.什么是大模型?大模型是指参数规模巨大(通常达到数十亿甚至万亿级别)、使用海量数据训练而成的人工智能模型。2.什么是大语言
    的头像 发表于 02-02 16:36 1117次阅读
    什么是大<b class='flag-5'>模型</b>,智能体...?大<b class='flag-5'>模型</b>100问,快速全面了解!

    NVIDIA推出面向语言、机器人和生物学的全新开源AI技术

    NVIDIA 秉持对开源的长期承诺,推出了面向语言、机器人和生物学的全新开源 AI 技术,为构建开源生态系统做出贡献,扩展 AI 的普及并推动创新。NVIDIA 正将这些模型、数据和训练框架贡献给
    的头像 发表于 11-06 11:49 1251次阅读

    在Ubuntu20.04系统中训练神经网络模型的一些经验

    本帖欲分享在Ubuntu20.04系统中训练神经网络模型的一些经验。我们采用jupyter notebook作为开发IDE,以TensorFlow2为训练框架,目标是训练一个手写数字识
    发表于 10-22 07:03

    NVIDIA开源Audio2Face模型及SDK

    NVIDIA 现已开源 Audio2Face 模型与 SDK,让所有游戏和 3D 应用开发者都可以构建并部署带有先进动画的高精度角色。NVIDIA 开源 Audio2Face训练
    的头像 发表于 10-21 11:11 1002次阅读
    NVIDIA开源Audio2<b class='flag-5'>Face</b><b class='flag-5'>模型</b>及SDK

    借助NVIDIA Megatron-Core大模型训练框架提高显存使用效率

    随着模型规模迈入百亿、千亿甚至万亿参数级别,如何在有限显存中“塞下”训练任务,对研发和运维团队都是巨大挑战。NVIDIA Megatron-Core 作为流行的大模型训练框架,提供了灵
    的头像 发表于 10-21 10:55 1374次阅读
    借助NVIDIA Megatron-Core大<b class='flag-5'>模型</b><b class='flag-5'>训练</b>框架提高显存使用效率

    什么是AI模型的推理能力

    NVIDIA 的数据工厂团队为 NVIDIA Cosmos Reason 等 AI 模型奠定了基础,该模型近日在 Hugging Face 的物理推理
    的头像 发表于 09-23 15:19 1448次阅读

    ai_cube训练模型最后部署失败是什么原因?

    ai_cube训练模型最后部署失败是什么原因?文件保存路径里也没有中文 查看AICube/AI_Cube.log,看看报什么错?
    发表于 07-30 08:15

    利用自压缩实现大型语言模型高效缩减

    随着语言模型规模日益庞大,设备端推理变得越来越缓慢且耗能巨大。一个直接且效果出人意料的解决方案是剪除那些对任务贡献甚微的完整通道(channel)。我们早期的研究提出了一种训练阶段的方法——自压
    的头像 发表于 07-28 09:36 647次阅读
    利用自压缩实现大型<b class='flag-5'>语言</b><b class='flag-5'>模型</b><b class='flag-5'>高效</b>缩减

    沐曦MXMACA软件平台在大模型训练方面的优化效果

    在如今的人工智能浪潮中,大规模语言模型(上百亿乃至千亿参数)正迅速改变着我们的工作和生活。然而,训练这些庞大的模型往往面临“算力不足、显存不够用、通信太慢”等诸多挑战。
    的头像 发表于 07-03 14:09 2399次阅读
    沐曦MXMACA软件平台在大<b class='flag-5'>模型</b><b class='flag-5'>训练</b>方面的优化效果

    龙芯中科与文心系列模型开展深度技术合作

    ”解决方案。 强强联合!自主架构赋能大模型训练 文心大模型 文心4.5系列模型均使用飞桨深度学习框架进行高效
    的头像 发表于 07-02 16:53 1468次阅读

    make sence成的XML文件能上传到自助训练模型上吗?

    make sence成的XML文件能上传到自助训练模型上吗
    发表于 06-23 07:38

    商汤科技日日新V6大模型斩获“双料第一” 一项国内榜首,一个全球第一

    卫冕“双冠”! 通用语言能力并列国内榜首、多模态能力全球最强,商汤「日日新V6」近期斩获“双料第一”。 5月28日,权威大模型测评机构SuperCLUE《中文大模型基准测评2025年5月报告》全新
    的头像 发表于 05-30 11:13 1721次阅读
    商汤科技日日新V6大<b class='flag-5'>模型</b>斩获“双料第一” 一项国内榜首,一个全球第一