LLM训练的显存占用(LoRA、QLoRA)

混合精度训练:

为什么不全都用FP16?

FP16精度的范围比FP32窄了很多,这就会产生数据溢出舍入误差两个问题(全网最全-混合精度训练原理),这会导致梯度消失无法训练,所以我们不能全都用FP16,还需要FP32来进行精度保证。BF16不会产生数据溢出了,业界的实际使用也反馈出比起精度,大模型更在意范围。

例子(暂时不看激活值占用 )

对于llama3.1 8B模型,FP32和BF16混合精度训练,用的是AdamW优化器,请问模型训练时占用显存大概为多少?

解:

模型参数:16(BF16) + 32(PF32)= 48G

梯度参数:16(BF16)= 16G

优化器参数:32(PF32) + 32(PF32)= 64G

不考虑激活值的情况下,总显存大约占用 (48 + 16 + 64) = 128G

KVCache动图:

KV cache的目的是减少延迟,也就是为了推理的速度牺牲显存。

我们推理就是在不断重复地做”生成下一个token“的任务,生成当前token 仅仅与当前的QKV和之前所有KV有关,那么我们就可以去维护这个KV并不断更新。 

KVCache计算公式:

(第1个2是K+V,第2个2是BP16 2个字节)

举例,对于llama7B,hiddensize = 4096,seqlength = 2048 , batchsize = 64,layers = 32:

降低显存最直观的方式:减少batch-size,由64降至1,显存降至约1GB了。

MQA&GQA:

把上式的hiddensize,换成heads_num * head_dim

对于普通MHA,heads_num*head_dim就等于hiddensize

对于GQA, heads_num从64变为8 (每8个heads共享1个KV)

对于MQA, heads_num变为1

LoRA

用了LoRA之后,

模型权重本身的权重, BF16的话,是2W;LoRA矩阵占用显存量,很小,可忽略;

全参模型和Optimize的状态,不需要了,因为梯度更新不更新全参模型;梯度更新只更新LoRA矩阵,很小,可忽略;

梯度,不需要计算原始模型部分的梯度,也基本不占用显存。LoRA矩阵的梯度,很小,可忽略;

LLama Factor给的表格:

QLora在训练计算时用到的精度仍是16bit,只是加载的模型是4bit,会进行一个反量化到16bit的方法,用完即释放。前面说到的都是模型原始参数本身,不包括lora部分的参数,Lora部分的参数不需要量化,一直都是16bit。 

比Lora多了一个反量化的操作,训练时间会更长,一般Qlora训练会比Lora多用30%左右的时间。


 

### 大型语言模型 (LLM) 训练代码示例 为了展示如何训练大型语言模型(LLM),下面提供了一个简化版的PyTorch实现。此代码展示了预训练阶段的核心概念以及微调过程。 #### 预处理数据集 在开始之前,需要准备并加载用于训练的数据集: ```python from transformers import GPT2Tokenizer tokenizer = GPT2Tokenizer.from_pretrained('gpt2') train_dataset = [...] # 加载训练数据集 val_dataset = [...] # 加载验证数据集 def collate_fn(batch): inputs = tokenizer([item['text'] for item in batch], return_tensors='pt', padding=True, truncation=True) labels = inputs.input_ids.clone() return {'input_ids': inputs.input_ids, 'labels': labels} ``` #### 初始化模型与优化器 接下来定义要使用的模型架构及其对应的优化算法: ```python import torch.optim as optim from transformers import GPT2LMHeadModel model = GPT2LMHeadModel.from_pretrained('gpt2') optimizer = optim.AdamW(model.parameters(), lr=5e-5) scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.9) device = "cuda" if torch.cuda.is_available() else "cpu" model.to(device) ``` #### 定义训练循环 最后编写实际执行训练逻辑的部分: ```python from tqdm.auto import tqdm from torch.utils.data import DataLoader batch_size = 8 epochs = 3 train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, collate_fn=collate_fn) eval_loader = DataLoader(val_dataset, batch_size=batch_size, collate_fn=collate_fn) for epoch in range(epochs): progress_bar = tqdm(total=len(train_loader), desc=f'Epoch {epoch}') model.train() total_loss = 0 for batch in train_loader: optimizer.zero_grad() outputs = model(**{k:v.to(device) for k,v in batch.items()}) loss = outputs.loss loss.backward() optimizer.step() scheduler.step() total_loss += loss.item() progress_bar.update(1) progress_bar.set_postfix({'loss': f'{total_loss / len(train_loader):.4f}'}) # Evaluation phase omitted here... ``` 上述代码片段基于GPT-2进行了说明[^1]。对于更复杂的场景或特定任务需求,则可能还需要调整超参数设置、引入额外正则化手段等措施来提升最终效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值