咱们最近发表了,来自 Google Deepmind 凋谢权重的语言模型 Gemma 现已通过 Hugging Face 面向更宽泛的开源社区凋谢。该模型提供了两个规模的版本:20 亿和 70 亿参数,包含预训练版本和通过指令调优的版本。它在 Hugging Face 平台上提供反对,可在 Vertex Model Garden 和 Google Kubernetes Engine 中轻松部署和微调。
Gemma 模型系列同样非常适合利用 Colab 提供的收费 GPU 资源进行原型设计和试验。在这篇文章中,咱们将简要介绍如何在 GPU 和 Cloud TPU 上,应用 Hugging Face Transformers 和 PEFT 库对 Gemma 模型进行参数高效微调(PEFT),这对想要在本人的数据集上微调 Gemma 模型的用户尤其有用。
为什么抉择 PEFT?
即便对于中等大小的语言模型,惯例的全参数训练也会十分占用内存和计算资源。对于依赖公共计算平台进行学习和试验的用户来说,如 Colab 或 Kaggle,老本可能过高。另一方面,对于企业用户来说,调整这些模型以适应不同畛域的老本也是一个须要优化的重要指标。参数高效微调(PEFT)是一种以低成本实现这一指标的风行办法。
理解更多 PEFT 请参考文章:🤗 PEFT: 在低资源硬件上对十亿规模模型进行参数高效微调
在 GPU 和 TPU 上应用 PyTorch 进行 Gemma 模型的高效微调
在 Hugging Face 的 transformers
中,Gemma 模型已针对 PyTorch 和 PyTorch/XLA 进行了优化,使得无论是 TPU 还是 GPU 用户都能够依据须要轻松地拜访和试验 Gemma 模型。随着 Gemma 的公布,咱们还改善了 PyTorch/XLA 在 Hugging Face 上的 FSDP 应用体验。这种 FSDP 通过 SPMD 的集成还让其余 Hugging Face 模型可能通过 PyTorch/XLA 利用 TPU 减速。本文将重点介绍 Gemma 模型的 PEFT 微调,特地是低秩适应(LoRA)。
想要深刻理解 LoRA 技术,咱们举荐浏览 Lialin 等人的 “Scaling Down to Scale Up” 以及 Belkada 等人的 精彩文章。
应用低秩适应技术 (LoRA) 对大语言模型进行微调
低秩适应(LoRA)是一种用于大语言模型(LLM)的参数高效微调技术。它只针对模型参数的一小部分进行微调,通过解冻原始模型并只训练被合成为低秩矩阵的适配器层。PEFT 库 提供了一个繁难的形象,容许用户抉择利用适配器权重的模型层。
from peft import LoraConfig
lora_config = LoraConfig(
r=8,
target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],
task_type="CAUSAL_LM",
)
在这个代码片段中,咱们将所有的 nn.Linear
层视为要适应的指标层。
在以下示例中,咱们将利用 QLoRA,出自 Dettmers 等人,通过 4 位精度量化根底模型,以实现更高的内存效率微调协定。通过首先在您的环境中装置 bitsandbytes
库,而后在加载模型时传递 BitsAndBytesConfig
对象,即可加载具备 QLoRA 的模型。
开始之前
要拜访 Gemma 模型文件,用户需先填写 批准表格。
咱们持续。
微调 Gemma,让它学会并生成一些“名言金句”
假如您已提交批准表格,您能够从 Hugging Face Hub 获取模型文件。
咱们首先下载模型和分词器 (tokenizer),其中蕴含了一个 BitsAndBytesConfig
用于仅限权重的量化。
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
model_id = "google/gemma-2b"
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
tokenizer = AutoTokenizer.from_pretrained(model_id, token=os.environ['HF_TOKEN'])
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map={"":0}, token=os.environ['HF_TOKEN'])
在开始微调前,咱们先应用一个相当熟知的名言来测试一下 Gemma 模型:
text = "Quote: Imagination is more"
device = "cuda:0"
inputs = tokenizer(text, return_tensors="pt").to(device)
outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
模型实现了一个正当的补全,只管有一些额定的 token:
Quote: Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.
-Albert Einstein
I
但这并不齐全是咱们心愿看到的答案格局。咱们将尝试通过微调让模型学会以咱们冀望的格局来产生答案:
Quote: Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.
Author: Albert Einstein
首先,咱们抉择一个英文“名人名言”数据集:
from datasets import load_dataset
data = load_dataset("Abirate/english_quotes")
data = data.map(lambda samples: tokenizer(samples["quote"]), batched=True)
接下来,咱们应用上述 LoRA 配置对模型进行微调:
import transformers
from trl import SFTTrainer
def formatting_func(example):
text = f"Quote: {example['quote'][0]}\nAuthor: {example['author'][0]}"
return
trainer = SFTTrainer(
model=model,
train_dataset=data["train"],
args=transformers.TrainingArguments(
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
warmup_steps=2,
max_steps=10,
learning_rate=2e-4,
fp16=True,
logging_steps=1,
output_dir="outputs",
optim="paged_adamw_8bit"
),
peft_config=lora_config,
formatting_func=formatting_func,
)
trainer.train()
最终,咱们再次应用先前的提醒词,来测试模型:
text = "Quote: Imagination is"
device = "cuda:0"
inputs = tokenizer(text, return_tensors="pt").to(device)
outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
这次,咱们失去了咱们期待的答案格局:
Quote: Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.
Author: Albert Einstein
名言:想象力比常识更重要,因为常识是无限的,而想象力概括着世界的所有.
作者:阿尔伯特·爱因斯坦
在 TPU 环境下微调,可通过 SPMD 上的 FSDP 减速
如前所述,Hugging Face transformers
现反对 PyTorch/XLA 的最新 FSDP 实现,这能够显著放慢微调速度。
只需在 transformers.Trainer
中增加 FSDP 配置即可启用此性能:
from transformers import DataCollatorForLanguageModeling, Trainer, TrainingArguments
# Set up the FSDP config. To enable FSDP via SPMD, set xla_fsdp_v2 to True.
fsdp_config = {"fsdp_transformer_layer_cls_to_wrap": ["GemmaDecoderLayer"],
"xla": True,
"xla_fsdp_v2": True,
"xla_fsdp_grad_ckpt": True
}
# Finally, set up the trainer and train the model.
trainer = Trainer(
model=model,
train_dataset=data,
args=TrainingArguments(
per_device_train_batch_size=64, # This is actually the global batch size for SPMD.
num_train_epochs=100,
max_steps=-1,
output_dir="./output",
optim="adafactor",
logging_steps=1,
dataloader_drop_last = True, # Required for SPMD.
fsdp="full_shard",
fsdp_config=fsdp_config,
),
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
trainer.train()
下一步
通过这个从源笔记本改编的简略示例,咱们展现了利用于 Gemma 模型的 LoRA 微调办法。残缺的 GPU colab 在 这里 能够找到,残缺的 TPU 脚本在 这里能够找到。咱们对于这一最新退出咱们开源生态系统的成员所带来的有限钻研和学习机会感到兴奋。咱们激励用户也浏览 Gemma 文档 和咱们的 公布博客,以获取更多对于训练、微调和部署 Gemma 模型的示例。