微调 LLaMA 2:定制大型语言模型的分步指南
深入了解如何运用新技术在 Google Colab 平台上对 Llama-2 进行微调操作,从而有效克服内存与计算方面的限制,让开源大型语言模型变得更加易于获取和使用。自从 Meta 发布了 LLaMA 的首个版本后,一场旨在构建更为强大、能够与 GPT-3.5(ChatGPT)等模型相抗衡的大型语言模型(LLM)的竞赛便正式开启。开源社区迅速行动起来,不断发布性能愈发强大的模型。对于人工智能领域的爱好者而言,这段时间就如同圣诞节一般充满惊喜,新的技术进展接连不断地涌现。
然而,这些显著的进步也带来了一些不可忽视的弊端。一方面,大多数开源模型的使用许可存在诸多限制,这就意味着它们仅仅能够被应用于研究领域。另一方面,只有那些资金充裕的大型企业或专业的研究机构,才具备足够的实力对模型进行微调或训练操作。此外,部署和维护最前沿的大型模型所需的成本相当高昂。全新版本的 LLaMA 模型正是为了解决上述这些问题而诞生的。它提供了商业许可证,使得更多的组织都有机会使用该模型。而且,现在出现了一些新的方法,能够让用户在内存有限的消费级 GPU 上实现对模型的微调。
人工智能的民主化对于其实现广泛应用来说至关重要。通过打破进入的壁垒,即便是规模较小的公司,也能够依据自身的实际需求和预算,构建出符合自身特点的定制化模型。在本教程当中,我们将会深入探索 Llama-2 模型,并实际演示如何借助 Google Colab 平台,在新的数据集上对其进行微调。此外,我们还会介绍一些有助于降低内存占用量,并加快训练速度的新方法和微调技巧。
了解 Llama 2 和模型微调
Llama 2 是 Meta 公司推出的第二代开源大型语言模型(LLM)集合,并且附带了商业使用许可证。该模型旨在处理各类自然语言处理任务,其模型规模有所不同,参数数量从 70 亿到 700 亿不等。如果您想深入了解更多关于 LLaMA 模型的详细信息,欢迎阅读我们的文章《Meta AI LLaMA 简介:赋能 AI 创新》。Llama-2-Chat 模型针对对话场景进行了专门优化,其性能目前已经能够与 ChatGPT、PaLM 等备受关注的闭源模型相媲美。实际上,我们还可以通过在高质量的对话数据集上对该模型进行微调操作,进一步提升其性能表现。
机器学习领域中,微调指的是根据新的数据对预训练模型的权重和参数进行调整,以此来提高模型在特定任务上的表现的过程。这一过程需要在与当前任务相关的新数据集上对模型进行训练,同时更新模型的权重,使其更好地适应新的数据特征。若您希望了解更多关于微调的相关信息,欢迎阅读我们的《GPT 3.5 微调指南》。以往,由于显存(VRAM)和计算能力的限制,在消费级硬件设备上无法实现对大型语言模型(LLM)的微调操作。不过,在本教程里,我们将着力克服这些在内存和计算方面所面临的挑战,并使用免费版本的 Google Colab Notebook 来完成对我们模型的训练工作。
如何微调 Llama 2:分步指南
在本部分内容中,我们将一同学习在配备 T4 GPU 的环境下,对拥有 70 亿个参数的 Llama 2 模型进行微调操作所需要的全部步骤。您可以自由选择使用 Google Colab 或者 Kaggle 平台上提供的免费 GPU 资源。需要注意的是,相应的代码在这两个平台上均能够正常运行。
Google Colab 所配备的 T4 GPU 的显存(VRAM)存在一定限制,仅有 16GB。这一容量仅仅勉强能够存储 Llama 2-7b 模型的权重数据,这也就表明我们无法对其进行完整的微调操作,因此,我们必须采用诸如 LoRA 或者 QLoRA 这类参数高效的微调技术。
在接下来的操作中,我们将运用 QLoRA 技术,以 4 位精度对模型展开微调工作,并且对显存(VRAM)的使用进行优化。为了达成这一目标,我们会使用 Hugging Face 生态系统中的大型语言模型(LLM)库,具体包括:transformers、accelerate、peft、trl 以及 bitsandbytes。
入门
我们将从安装所需的库开始
%%capture
%pip install accelerate peft bitsandbytes transformers trl
之后,我们将从这些库中加载必要的模块。
import os
import torch
from datasets import load_dataset
from transformers import (AutoModelForCausalLM,AutoTokenizer,BitsAndBytesConfig,TrainingArguments,pipeline,logging,
)
from peft import LoraConfig
from trl import SFTTrainer
模型配置
Meta 公司官方的 Llama-2 模型可以从 Hugging Face 平台获取,不过需要进行申请,并且在申请后通常得等待几天时间才能收到确认回复。为了避免这种等待的时间成本,将选择使用 NousResearch 的 Llama-2-7b-chat-hf 模型作为基础模型。该模型与原始的 Llama-2 模型在性能等方面是一致的,而且相对来说更容易获取到。
将使用名为mlabonne/guanaco-llama2-1k的较小数据集对的基础模型进行微调,并为微调后的模型写下名称。
# Model from Hugging Face hub
base_model = "NousResearch/Llama-2-7b-chat-hf"# New instruction dataset
guanaco_dataset = "mlabonne/guanaco-llama2-1k"# Fine-tuned model
new_model = "llama-2-7b-chat-guanaco"
加载数据集、模型和标记器
将从 Hugging Face 中心加载“guanaco-llama2-1k”数据集。该数据集包含 1000 个样本,已处理为符合 Llama 2 提示格式,并且是优秀的timdettmers/openassistant-guanaco数据集的子集。
dataset = load_dataset(guanaco_dataset, split="train")
dataset = load_dataset(guanaco_dataset, split="train")
位量化配置
QLoRA 实现的 4 位量化,能在消费级硬件上高效微调大型 LLM 模型,还能维持高性能。这极大提升了实际应用的可及性与可用性。
QLoRA 把预训练的语言模型量化为 4 位并冻结参数,接着往模型中添加少量可训练的低秩适配器层。
微调时,梯度会经冻结的 4 位量化模型反向传播至低秩适配器层。所以,整个预训练模型的梯度固定为 4 位,仅适配器层会更新。而且,4 位量化不会对模型性能造成影响。
可以阅读该论文以更好地理解它。在例子中,使用 BitsAndBytes 创建具有 NF4 类型配置的 4 位量化。
compute_dtype = getattr(torch, "float16")quant_config = BitsAndBytesConfig(load_in_4bit=True,bnb_4bit_quant_type="nf4",bnb_4bit_compute_dtype=compute_dtype,bnb_4bit_use_double_quant=False,
)
加载Llama 2模型
接下来,我们将从 Hugginface 加载标记器并设置padding_side为“正确”以修复 fp16 的问题
model = AutoModelForCausalLM.from_pretrained(base_model,quantization_config=quant_config,device_map={"": 0}
)
model.config.use_cache = False
model.config.pretraining_tp = 1
加载标记器
接下来,将从Hugginface加载标记器,并设置padding_side为“正确”,以修复fp16的问题。
tokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
PEFT参数
预训练语言模型 (PLM) 的传统微调需要更新模型的所有参数,这在计算方面成本高昂,并且需要大量的数据。
参数高效微调 (PEFT) 的运作方式是仅更新模型中影响力最大的一小部分参数,借此显著提升模型的效率。可以阅读 PEFT 官方文档来了解相关参数。
peft_params = LoraConfig(lora_alpha=16,lora_dropout=0.1,r=64,bias="none",task_type="CAUSAL_LM",
)
训练参数
以下是可用于优化训练过程的超参数列表:
- output_dir:输出目录是存储模型预测和检查点的地方。
- num_train_epochs:一个训练时期。
- fp16/bf16:禁用 fp16/bf16 训练。
- per_device_train_batch_size:每个 GPU 的训练批次大小。
- per_device_eval_batch_size:用于评估的每个 GPU 的批次大小。
- Gradient_accumulation_steps:这指的是更新过程中累积梯度所需的步数。
- Gradient_checkpointing:启用梯度检查点。
- max_grad_norm:梯度剪裁。
- learning_rate:初始学习率。
- weight_decay:权重衰减适用于除偏差/LayerNorm权重之外的所有层。
- Optim:模型优化器(AdamW 优化器)。
- lr_scheduler_type:学习率计划。
- max_steps:训练步数。
- warmup_ratio:线性预热的步骤比率。
- group_by_length:这可以显著提高性能并加速训练过程。
- save_steps:每 25 个更新步骤保存检查点。
- logging_steps:每 25 个更新步骤记录一次。
training_params = TrainingArguments(output_dir="./results",num_train_epochs=1,per_device_train_batch_size=4,gradient_accumulation_steps=1,optim="paged_adamw_32bit",save_steps=25,logging_steps=25,learning_rate=2e-4,weight_decay=0.001,fp16=False,bf16=False,max_grad_norm=0.3,max_steps=-1,warmup_ratio=0.03,group_by_length=True,lr_scheduler_type="constant",report_to="tensorboard"
)
模型微调
监督微调 (SFT) 是强化学习(基于人类反馈)的关键步骤。HuggingFace 的 TRL 库提供了一个使用便捷的 API,仅需几行代码就能创建 SFT 模型,并在数据集上开展训练。它附带了一些工具,可用来通过强化学习训练语言模型,流程是先从监督微调起步,接着进行奖励建模,最后实施近端策略优化 (PPO)。
将为 SFT Trainer 提供模型、数据集、Lora 配置、标记器以及训练参数。
trainer = SFTTrainer(model=model,train_dataset=dataset,peft_config=peft_params,dataset_text_field="text",max_seq_length=None,tokenizer=tokenizer,args=training_params,packing=False,
)
将使用.train()新的数据集对 Llama 2 模型进行微调。该模型完成 1 个 epoch 需要一个半小时。
模型训练完成后,将保存模型采用器和分词器,也可以使用类似的 API 将模型上传到 Hugging Face。
trainer.model.save_pretrained(new_model)
trainer.tokenizer.save_pretrained(new_model)
评估
现在可以在 Tensorboard 的交互式会话中查看训练结果。
from tensorboard import notebook
log_dir = "results/runs"
notebook.start("--logdir {} --port 4000".format(log_dir))
为了测试我们微调的模型,将使用transformers文本生成管道并提出一些简单的问题,例如“列奥纳多达芬奇是谁?”。
logging.set_verbosity(logging.CRITICAL)prompt = "Who is Leonardo Da Vinci?"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])
输出:
正如我们所见,得到了惊人的结果。
<s>[INST] Who is Leonardo Da Vinci? [/INST] Leonardo da Vinci (1452-1519) was an Italian polymath, artist, inventor, and engineer.Da Vinci is widely considered one of the greatest painters of all time, and his works include the famous Mona Lisa. He was also an accomplished engineer, inventor, and anatomist, and his designs for machines and flight were centuries ahead of his time.Da Vinci was born in the town of Vinci, Italy, and he was the illegitimate son of a local notary. Despite his humble origins, he was able to study art and engineering in Florence, and he became a renowned artist and inventor.Da Vinci's work had a profound impact on the Renaissance, and his legacy continues to inspire artists, engineers, and inventors to this day. He
再问一个问题
prompt = "What is Datacamp Career track?"
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])
输出:
Guanaco 是一个高质量的数据集,过去曾用于微调最先进的 LLM。Hugging Face 上提供了完整的 Guanaco 数据集,它有潜力在各种自然语言任务上取得更优异的表现。
<s>[INST] What is Datacamp Career track? [/INST] DataCamp Career Track is a program that offers a comprehensive learning experience to help you build your skills and prepare for a career in data science.The program includes a range of courses, projects, and assessments that are designed to help you build your skills in data science. You will learn how to work with data, create visualizations, and build predictive models.In addition to the technical skills, you will also learn how to communicate your findings to stakeholders and how to work with a team to solve complex problems.The program is designed to be flexible, so you can learn at your own pace and on your own schedule. You will also have access to a community of learners and mentors who can provide support and guidance throughout the program.Overall, DataCamp Career Track is a great way to build your skills and prepare for a career in
这是Colab Notebook,其中包含代码和输出,可帮助您完成编码之旅。
结论
本教程提供了全面的指南,指导您如何使用 QLoRA、PEFT 和 SFT 等技术对 LLaMA 2 模型进行微调,以克服内存和计算能力的限制。通过利用 Hugging Face 库(例如transformers、accelerate、peft、trl和bitsandbytes),我们能够在消费级 GPU 上成功微调 7B 参数的 LLaMA 2 模型。
总的来说,本教程举例说明了最近的进展如何实现大型语言模型的民主化和可访问性,甚至允许业余爱好者利用有限的资源构建最先进的人工智能。