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

    文章

    140

    浏览量

    21511
  • AWS
    AWS
    +关注

    关注

    0

    文章

    438

    浏览量

    25376
  • LoRa模块
    +关注

    关注

    5

    文章

    142

    浏览量

    14728
  • pytorch
    +关注

    关注

    2

    文章

    810

    浏览量

    14013

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

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    小白学大模型训练语言模型的深度指南

    在当今人工智能飞速发展的时代,大型语言模型(LLMs)正以其强大的语言理解和生成能力,改变着我们的生活和工作方式。在最近的一项研究中,科学家们为了深入了解如何高效
    的头像 发表于 03-03 11:51 ?780次阅读
    小白学大<b class='flag-5'>模型</b>:<b class='flag-5'>训练</b>大<b class='flag-5'>语言</b><b class='flag-5'>模型</b>的深度指南

    DeepSeek 推理型AI尽显高效训练的小模型之威

    工智能模型,不久前,在人工智能开源平台?Hugging Face?上发布数小时,便跃居下载量和活跃度最高模型的榜首;同时因其促使投资者重新考虑英
    的头像 发表于 02-10 15:04 ?356次阅读

    腾讯公布大语言模型训练新专利

    近日,腾讯科技(深圳)有限公司公布了一项名为“大语言模型训练方法、装置、计算机设备及存储介质”的新专利。该专利的公布,标志着腾讯在大语言模型
    的头像 发表于 02-10 09:37 ?468次阅读

    Hugging Face推出最小AI视觉语言模型

    Hugging Face平台于1月23日发布博文,推出了两款令人瞩目的轻量级AI模型——SmolVLM-256M-Instruct和SmolVLM-500M-Instruct。 其中
    的头像 发表于 01-24 14:15 ?1040次阅读

    模型训练框架(五)之Accelerate

    Hugging Face 的 Accelerate1是一个用于简化和加速深度学习模型训练的库,它支持在多种硬件配置上进行分布式训练,包括 C
    的头像 发表于 01-14 14:24 ?802次阅读

    AI大语言模型开发步骤

    开发一个高效、准确的大语言模型是一个复杂且多阶段的过程,涉及数据收集与预处理、模型架构设计、训练与优化、评估与调试等多个环节。接下来,AI部
    的头像 发表于 12-19 11:29 ?950次阅读

    语言模型开发框架是什么

    语言模型开发框架是指用于训练、推理和部署大型语言模型的软件工具和库。下面,AI部落小编为您介绍大语言
    的头像 发表于 12-06 10:28 ?568次阅读

    语言模型开发语言是什么

    在人工智能领域,大语言模型(Large Language Models, LLMs)背后,离不开高效的开发语言和工具的支持。下面,AI部落小编为您介绍大
    的头像 发表于 12-04 11:44 ?748次阅读

    云端语言模型开发方法

    云端语言模型的开发是一个复杂而系统的过程,涉及数据准备、模型选择、训练优化、部署应用等多个环节。下面,AI部落小编为您分享云端语言
    的头像 发表于 12-02 10:48 ?719次阅读

    什么是大模型、大模型是怎么训练出来的及大模型作用

    ,基础模型。 ? 大模型是一个简称,完整的叫法,应该是“人工智能预训练模型”。预训练,是一项技术,我们后面再解释。 ? 我们现在口头上常说
    的头像 发表于 11-25 09:29 ?1.3w次阅读
    什么是大<b class='flag-5'>模型</b>、大<b class='flag-5'>模型</b>是怎么<b class='flag-5'>训练</b>出来的及大<b class='flag-5'>模型</b>作用

    从零开始训练一个大语言模型需要投资多少钱?

    一,前言 ? 在AI领域,训练一个大型语言模型(LLM)是一个耗时且复杂的过程。几乎每个做大型语言模型(LLM)
    的头像 发表于 11-08 14:15 ?818次阅读
    从零开始<b class='flag-5'>训练</b>一个大<b class='flag-5'>语言</b><b class='flag-5'>模型</b>需要投资多少钱?

    如何训练自己的LLM模型

    训练自己的大型语言模型(LLM)是一个复杂且资源密集的过程,涉及到大量的数据、计算资源和专业知识。以下是训练LLM模型的一般步骤,以及一些关
    的头像 发表于 11-08 09:30 ?1593次阅读

    语言模型如何开发

    语言模型的开发是一个复杂且细致的过程,涵盖了数据准备、模型架构设计、训练、微调和部署等多个阶段。以下是对大语言
    的头像 发表于 11-04 10:14 ?625次阅读

    如何训练自己的AI大模型

    训练AI大模型之前,需要明确自己的具体需求,比如是进行自然语言处理、图像识别、推荐系统还是其他任务。 二、数据收集与预处理 数据收集 根据任务需求,收集并准备好足够的数据集。 可以选择公开数据集、自有数据集或者通过数据标
    的头像 发表于 10-23 15:07 ?5170次阅读

    摩尔线程与羽人科技完成大语言模型训练测试

    近日,摩尔线程与羽人科技携手宣布,双方已成功实现夸娥(KUAE)千卡智算集群与羽人系列模型解决方案的训练兼容适配。在本次测试中,羽人科技通过摩尔线程夸娥千卡智算集群,高效完成了70亿参数羽人7B
    的头像 发表于 08-27 16:19 ?869次阅读