使用GaLore在本地GPU进行高效的LLM调优

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: GaLore是一种新的优化策略,它通过梯度低秩投影减少VRAM需求,使得大型语言模型(如70亿参数的模型)能在消费级GPU上进行微调,而不减少参数数量。与LoRA相比,GaLore内存效率更高,且性能相当或更优。它在反向传播期间逐层更新参数,降低了计算负荷。虽然GaLore训练时间较长,但它为个人爱好者提供了在有限资源下训练大模型的可能性。相关代码示例和性能对比显示了其优势。

训练大型语言模型(llm),即使是那些“只有”70亿个参数的模型,也是一项计算密集型的任务。这种水平的训练需要的资源超出了大多数个人爱好者的能力范围。为了弥补这一差距,出现了低秩适应(LoRA)等参数高效方法,可以在消费级gpu上对大量模型进行微调。

GaLore是一种新的方法,它不是通过直接减少参数的数量,而是通过优化这些参数的训练方式来降低VRAM需求,也就是说GaLore是一种新的模型训练策略,可让模型使用全部参数进行学习,并且比LoRA更省内存。

GaLore将这些梯度投影到低秩空间上,显著减少了计算负荷,同时保留了训练所需的基本信息。与传统的优化器在反向传播后同时更新所有层的方法不同,GaLore在反向传播期间实现逐层更新。这种方法进一步减少了整个训练过程中的内存占用。

就像LoRA一样,GaLore可以让我们在具有24 GB VRAM的消费级GPU上微调7B模型。结果模型的性能与全参数微调相当,并且似乎优于LoRA。

优于目前Hugging Face还没有官方代码,我们就来手动使用论文的代码进行训练,并与LoRA进行对比

安装依赖

首先就要安装GaLore

 pip install galore-torch

然后我们还要一下这些库,并且请注意版本

 datasets==2.18.0
 transformers==4.39.1
 trl==0.8.1
 accelerate==0.28.0
 torch==2.2.1

调度器和优化器的类

Galore分层优化器是通过模型权重挂钩激活的。由于我们使用Hugging Face

Trainer

,还需要自己实现一个优化器和调度器的抽象类。这些类的结构不执行任何操作。

 from typing import Optional
 import torch

 # Approach taken from Hugging Face transformers https://github.com/huggingface/transformers/blob/main/src/transformers/optimization.py
 class LayerWiseDummyOptimizer(torch.optim.Optimizer):
     def __init__(self, optimizer_dict=None, *args, **kwargs):
         dummy_tensor = torch.randn(1, 1)
         self.optimizer_dict = optimizer_dict
         super().__init__([dummy_tensor], {"lr": 1e-03})

     def zero_grad(self, set_to_none: bool = True) -> None: 
       pass

     def step(self, closure=None) -> Optional[float]: 
       pass

 class LayerWiseDummyScheduler(torch.optim.lr_scheduler.LRScheduler):
     def __init__(self, *args, **kwargs):
         optimizer = LayerWiseDummyOptimizer()
         last_epoch = -1
         verbose = False
         super().__init__(optimizer, last_epoch, verbose)

     def get_lr(self): 
       return [group["lr"] for group in self.optimizer.param_groups]

     def _get_closed_form_lr(self): 
       return self.base_lrs

加载GaLore优化器

GaLore优化器的目标是特定的参数,主要是那些在线性层中以attn或mlp命名的参数。通过系统地将函数与这些目标参数挂钩,GaLore 8位优化器就会开始工作。

 from transformers import get_constant_schedule
 from functools import partial
 import torch.nn
 import bitsandbytes as bnb

 from galore_torch import GaLoreAdamW8bit

 def load_galore_optimizer(model, lr, galore_config):    
     # function to hook optimizer and scheduler to a given parameter 
     def optimizer_hook(p, optimizer, scheduler):
         if p.grad is not None: 
             optimizer.step()
             optimizer.zero_grad()
             scheduler.step()

     # Parameters to optimize with Galore
     galore_params = [
         (module.weight, module_name) for module_name, module in model.named_modules() 
         if isinstance(module, nn.Linear) and any(target_key in module_name for target_key in galore_config["target_modules_list"])
     ] 
     id_galore_params = {id(p) for p, _ in galore_params}

     # Hook Galore optim to all target params, Adam8bit to all others
     for p in model.parameters():
         if p.requires_grad:
             if id(p) in id_galore_params:
                 optimizer = GaLoreAdamW8bit([dict(params=[p], **galore_config)], lr=lr)
             else:
                 optimizer = bnb.optim.Adam8bit([p], lr = lr)
             scheduler = get_constant_schedule(optimizer)

             p.register_post_accumulate_grad_hook(partial(optimizer_hook, optimizer=optimizer, scheduler=scheduler))

     # return dummies, stepping is done with hooks 
     return LayerWiseDummyOptimizer(), LayerWiseDummyScheduler()

HF Trainer

准备好优化器后,我们开始使用Trainer进行训练。下面是一个简单的例子,使用TRL的SFTTrainer (Trainer的子类)在Open Assistant数据集上微调llama2-7b,并在RTX 3090/4090等24 GB VRAM GPU上运行。

 from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, set_seed, get_constant_schedule
 from trl import SFTTrainer, setup_chat_format, DataCollatorForCompletionOnlyLM
 from datasets import load_dataset
 import torch, torch.nn as nn, uuid, wandb

 lr = 1e-5

 # GaLore optimizer hyperparameters
 galore_config = dict(
     target_modules_list = ["attn", "mlp"], 
     rank = 1024, 
     update_proj_gap = 200, 
     scale = 2, 
     proj_type="std"
 )

 modelpath = "meta-llama/Llama-2-7b"
 model = AutoModelForCausalLM.from_pretrained(
     modelpath,    
     torch_dtype=torch.bfloat16,
     attn_implementation = "flash_attention_2",  
     device_map = "auto",
     use_cache = False,
 )
 tokenizer = AutoTokenizer.from_pretrained(modelpath, use_fast = False)

 # Setup for ChatML
 model, tokenizer = setup_chat_format(model, tokenizer)
 if tokenizer.pad_token in [None, tokenizer.eos_token]: 
     tokenizer.pad_token = tokenizer.unk_token

 # subset of the Open Assistant 2 dataset, 4000 of the top ranking conversations
 dataset = load_dataset("g-ronimo/oasst2_top4k_en")

 training_arguments = TrainingArguments(
     output_dir = f"out_{run_id}",
     evaluation_strategy = "steps",
     label_names = ["labels"],
     per_device_train_batch_size = 16,
     gradient_accumulation_steps = 1,
     save_steps = 250,
     eval_steps = 250,
     logging_steps = 1, 
     learning_rate = lr,
     num_train_epochs = 3,
     lr_scheduler_type = "constant",
     gradient_checkpointing = True,
     group_by_length = False,
 )

 optimizers = load_galore_optimizer(model, lr, galore_config)

 trainer = SFTTrainer(
     model = model,
     tokenizer = tokenizer,
     train_dataset = dataset["train"],
     eval_dataset = dataset['test'],
     data_collator = DataCollatorForCompletionOnlyLM(
         instruction_template = "<|im_start|>user", 
         response_template = "<|im_start|>assistant", 
         tokenizer = tokenizer, 
         mlm = False),
     max_seq_length = 256,
     dataset_kwargs = dict(add_special_tokens = False),
     optimizers = optimizers,
     args = training_arguments,
 )

 trainer.train()

GaLore优化器带有一些需要设置的超参数如下:

target_modules_list:指定GaLore针对的层

rank:投影矩阵的秩。与LoRA类似,秩越高,微调就越接近全参数微调。GaLore的作者建议7B使用1024

update_proj_gap:更新投影的步骤数。这是一个昂贵的步骤,对于7B来说大约需要15分钟。定义更新投影的间隔,建议范围在50到1000步之间。

scale:类似于LoRA的alpha的比例因子,用于调整更新强度。在尝试了几个值之后,我发现scale=2最接近于经典的全参数微调。

微调效果对比

给定超参数的训练损失与全参数调优的轨迹非常相似,表明GaLore分层方法确实是等效的。

用GaLore训练的模型得分与全参数微调非常相似。

GaLore可以节省大约15 GB的VRAM,但由于定期投影更新,它需要更长的训练时间。

上图为2个3090的内存占用对比

训练事件对比,微调:~58分钟。GaLore:约130分钟

最后我们再看看GaLore和LoRA的对比

上图为LoRA微调所有线性层,rank64,alpha 16的损失图

从数值上可以看到GaLore是一种近似全参数训练的新方法,性能与微调相当,比LoRA要好得多。

总结

GaLore可以节省VRAM,允许在消费级GPU上训练7B模型,但是速度较慢,比微调和LoRA的时间要长差不多两倍的时间。

GaLore: Memory-Efficient LLM Training by Gradient Low-Rank Projection.

https://avoid.overfit.cn/post/0b15de8db27040f0abcaa7e554b0b993

作者:Geronimo

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
2月前
|
安全 异构计算
为大型语言模型 (LLM) 提供服务需要多少 GPU 内存?
为大型语言模型 (LLM) 提供服务需要多少 GPU 内存?
94 0
为大型语言模型 (LLM) 提供服务需要多少 GPU 内存?
|
10月前
|
自然语言处理 测试技术 异构计算
使用Accelerate库在多GPU上进行LLM推理
大型语言模型(llm)已经彻底改变了自然语言处理领域。随着这些模型在规模和复杂性上的增长,推理的计算需求也显著增加。为了应对这一挑战利用多个gpu变得至关重要。
1496 0
|
弹性计算 API 数据库
大模型规模化落地,企业AIGC应用支持多个大语言模型(LLM)切换及GPU规划化管理(PAI-EAS + ADB-PG)
随着年初的ChatGPT引爆大语言模型市场, LLM的集中爆发,大部分企业已经完成了AIGC产品的调研,并进入第二阶段, 即寻求大规模落地的AIGC产品解决方案。本文介绍了如何企业规模化大语言模型落地,支持多个模型的快速使用,包括通义千问-7b,ChatGLM-6b,Llama2-7b ,Llama2-13b,百川-13b和Falcon-7b。
大模型规模化落地,企业AIGC应用支持多个大语言模型(LLM)切换及GPU规划化管理(PAI-EAS + ADB-PG)
|
机器学习/深度学习 存储 编解码
在消费级GPU调试LLM的三种方法:梯度检查点,LoRA和量化
LLM的问题就是权重参数太大,无法在我们本地消费级GPU上进行调试,所以我们将介绍3种在训练过程中减少内存消耗,节省大量时间的方法:梯度检查点,LoRA和量化。
568 0
|
弹性计算 API 数据库
规模化落地AIGC应用,支持多个大语言模型(LLM)切换及GPU规划化管理(PAI-EAS + ADB-PG)
随着年初的ChatGPT引爆大语言模型市场, LLM的集中爆发,大部分企业已经完成了AIGC产品的调研,并进入第二阶段, 即寻求大规模落地的AIGC产品解决方案。本文介绍了如何企业规模化大语言模型落地,支持多个模型的快速使用,包括通义千问-7b,ChatGLM-6b,Llama2-7b 和 Llama2-13b。
2142 0
|
缓存 人工智能 并行计算
小羊驼背后的英雄,伯克利开源LLM推理与服务库:GPU减半、吞吐数十倍猛增
小羊驼背后的英雄,伯克利开源LLM推理与服务库:GPU减半、吞吐数十倍猛增
486 0
|
2月前
|
机器学习/深度学习 编解码 人工智能
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
随着人工智能、大数据和深度学习等领域的快速发展,GPU服务器的需求日益增长。阿里云的GPU服务器凭借强大的计算能力和灵活的资源配置,成为众多用户的首选。很多用户比较关心gpu云服务器的收费标准与活动价格情况,目前计算型gn6v实例云服务器一周价格为2138.27元/1周起,月付价格为3830.00元/1个月起;计算型gn7i实例云服务器一周价格为1793.30元/1周起,月付价格为3213.99元/1个月起;计算型 gn6i实例云服务器一周价格为942.11元/1周起,月付价格为1694.00元/1个月起。本文为大家整理汇总了gpu云服务器的最新收费标准与活动价格情况,以供参考。
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
|
1月前
|
机器学习/深度学习 存储 人工智能
阿里云GPU云服务器实例规格gn6v、gn7i、gn6i实例性能及区别和选择参考
阿里云的GPU云服务器产品线在深度学习、科学计算、图形渲染等多个领域展现出强大的计算能力和广泛的应用价值。本文将详细介绍阿里云GPU云服务器中的gn6v、gn7i、gn6i三个实例规格族的性能特点、区别及选择参考,帮助用户根据自身需求选择合适的GPU云服务器实例。
阿里云GPU云服务器实例规格gn6v、gn7i、gn6i实例性能及区别和选择参考
|
2月前
|
编解码 分布式计算 Linux
最新阿里云服务器、轻量应用服务器、GPU云服务器活动价格参考
阿里云服务器产品包含云服务器、轻量应用服务器、GPU云服务器等,本文汇总了这些云服务器当下最新的实时活动价格情况,包含经济型e实例云服务器价格、通用算力型u1实例云服务器价格、第七代云服务器价格、轻量应用服务器最新价格、GPU云服务器价格,以供大家参考。
最新阿里云服务器、轻量应用服务器、GPU云服务器活动价格参考
|
2月前
|
机器学习/深度学习 人工智能 弹性计算
阿里云AI服务器价格表_GPU服务器租赁费用_AI人工智能高性能计算推理
阿里云AI服务器提供多样化的选择,包括CPU+GPU、CPU+FPGA等多种配置,适用于人工智能、机器学习和深度学习等计算密集型任务。其中,GPU服务器整合高性能CPU平台,单实例可实现最高5PFLOPS的混合精度计算能力。根据不同GPU类型(如NVIDIA A10、V100、T4等)和应用场景(如AI训练、推理、科学计算等),价格从数百到数千元不等。详情及更多实例规格可见阿里云官方页面。
182 1