独步潮流!如何在私有数据集上塑造GPT式大型语言模型的独特风格!( 三 )


现在让我们一起看下耗时:
如上图所示,使用参数高效的微调方法比微调所有层(“full”)快约 9 倍!此外,由于内存限制,微调所有层需要 6 个GPU,而适配器方法和 LoRA 方法仅需要单个 GPU。
因此,关于 GPU 内存要求,峰值内存要求如下图所示:
如上,对于7B 的全参数微调,每个 GPU 需要约 40 GB的内存(还是使用进行张量分片之后的~~~) 。因此实际总共需要 240 GB的内存 。相比之下,参数高效的微调方法只需要约 16 GB的RAM,这使得用户甚至可以在单个消费级 GPU 上微调这些模型 。
顺便提一下,需要更新的参数数量直接影响内存要求:
模型参数数量
全参数微调
7,217,189,760
1,365,330
v2
3,839,186
LoRA
3,506,176
是的,你没看错,全参数微调(更新所有层)需要更新的参数数量是v2 或 LoRA 方法的 2000 倍,而后者的建模性能却与全层微调相等(有时甚至更好) 。

独步潮流!如何在私有数据集上塑造GPT式大型语言模型的独特风格!

文章插图
关于推理速度,我们可以简单看下如下的性能数据:
模型每秒标记数量内存使用
LoRA
21.33
14.59 GB
26.22
14.59 GB
v2
24.73
14.59 GB
超参数设置
如果您想复现上述结果,以下是建议的超参数设置:
采用混合精度训练,以加快训练速度并减少内存需求;迭代 52,000 次,刚好与本次基准测试中使用的数据集大小相对应; 设置为 128,并采用梯度累积技术 。( 是一种可以在执行权重更新之前将梯度累积在多个较小的批次上 。这有助于克服内存限制,并允许使用更大的批次大小进行训练 。)对于 LoRA,使用了秩为 8,以大致匹配v2 额外添加的参数数量 。
最后,本文数据是在一张 A100 GPU 上进行训练的 。同理,full.py 脚本则需要 6 张 A100 GPU 和的张量分片技术来处理内存需求 。大家可以在上找到具有上述设置的修改后的脚本 。
附带下测试命令:
python generate/lora.py --checkpoint_dir checkpoints/tiiuae/falcon-7b --lora_path out/lora/alpaca/lit_model_lora_finetuned.pth
技术原理
LLaMA- 方法简单来说,就是在现有的 LLM 中添加了一小部分可训练的张量(参数) 。在这种方法中,只有新的参数被训练,原始参数保持不变 。这样可以在反向传播过程中节省大量的计算和内存资源 。
具体来说,LLaMA- 方法在嵌入的输入之前添加了可调整的提示张量(前缀) 。在 LLaMA-方法中,这些前缀是在一个嵌入表中学习和维护的,而不是从外部提供 。模型中的每个块都有自己独特的学习前缀,可以实现对不同模型层的更具针对性的适应 。
此外,LLaMA- 引入了一个以零初始化的注意力机制,并与门控机制相结合 。所谓的零初始化注意力和门控机制的动机是,适配器和前缀调整可能会通过整合随机初始化的张量(前缀提示或适配器层)来破坏预训练 LLM 的语言知识,导致在初始训练阶段出现不稳定的微调和较高的损失值 。
LLaMA- 方法的主要概念如下图所示,在正常块的修改部分以紫色突出显示:
一个关键的想法是添加一小部分可训练的参数 。另一个重要的事情要注意的是,这种方法并不限于LLaMA LLMs,这就是为什么我们可以将其用于 模型的原因 。
对 LLaMA- 方法的更多细节感兴趣的同学,可以阅读这篇文章《 -of Large: Fromto LLaMA-》 。
v2
LLaMA- v2 是 LLaMA- 的进化版,在对 LLMs 进行文本和指令微调时,它增加了可调参数的数量 。第一个区别是在全连接(线性)层中添加了偏置单元 。由于它只是修改了现有的线性层,从输入权重变为输入权重+偏置,因此对微调和推理性能只有很小的影响 。