官方服务微信:dat818 购买与出租对接

lora技术是什么,技术是什么学科,技术是龙头

3万

主题

2

回帖

9万

积分

管理员

积分
92591
发表于 3 小时前 | 显示全部楼层 |阅读模式
    揭秘LoRA与QLoRA:通过百次实验告诉你怎样微调LLM!

    LoRA即低秩适应,是当前应用极为广泛、参数效率很高的自定义大型语言模型微调技术之一。本文不但介绍了运用QLoRA节省内存的办法,还探讨了挑选最佳LoRA设置的实用窍门,为对应用此技术感兴趣的读者给予了实践见解

    如何充分利用LoRA

    过去几个月中我开展了数百次乃至上千次涉及LoRA的实验。几周之前我花费时间深入探究了一些超参数的选取。

    这篇文章类似按时间顺序展现的实验日记。我期望它对一些人有帮助。具体而言,我想解答关于QLoRA价值的问题。还要解答是否该用SGD替换AdamW的问题。以及潜在使用调度器的问题。还有如何调整LoRA超参数的问题

    关于实验方面有很多内容需要讨论,因此我会简短介绍LoRA。

    简而言之 LoRA是低秩适应 由Hu等人于2021年提出 通过向模型添加少量可训练参数 同时保持原始模型参数不变 从而实现了功能

    LoRA通过把一个大的权重矩阵分解成两个较小的权重矩阵来近似实现完全的有监督微调。实现方式如下图所示。其以更高的参数效率来达成这一目标。

    评估任务和数据集

    本文重点在于选择最优设置。为保持合理范围。我固定了数据集。仅专注于大型语言模型的有监督指令微调。

    对于模型评估 我从AI的评估工具包中选取了一小部分任务 其中包括BLiMP因果关系 MMLU全球事实 还有两位数的简单算术任务 即算术2ds 以及四位数的简单算术任务 即算术4ds

    在每项基准测试里,模型性能得分于0至1之间进行标准化处理,这里1代表满分。报告两个得分,具体定义如下:

    作为参考 175B GPT - 3 模型 其 MC1 值为 0.21 其 MC2 值为 0.33

    下面是两个例子,用以说明算术2ds和算术4ds之间的区别:

    如前文所说,确定了数据集,采用广为研究或常用的数据集来开展有监督指令微调。当然,存在许多其他用于指令微调的数据集,像LIMA、Dolly、FLAN等。然而,在未来研究里,探究在多个数据集以及数据集组合上进行训练会是个有意思的课题。

    数据集样例数据如下图所示:

    代码框架

    你提供的内容似乎存在较多不清晰和难以理解的表述,可能影响准确改写,请检查或进一步明确相关内容。

    我在这篇文章里用的自定义大型语言模型微调代码基于开源的Lit - GPT仓库。为让文章前言简洁,我不深入探讨使用细节。不过你能在Lit - GPT教程部分找到更详尽的指南。

    简要来说,使用方法如下:

    克隆相关仓库和安装相关依赖

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="Ifs4a"><code>通过git工具进行克隆操作,克隆的源地址为https://github.com/Lightning-AI/lit-gpt
cd lit-gpt
通过pip安装与requirements.txt文件中列出的依赖项一致的包</code></pre></p>
    下载模型ckpt文件

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="tUjT6"><code>python scripts/download.py \
仓库标识为mistralai/Mistral-7B-Instruct-v0.1
还有许多其他受支持的模型</code></pre></p>
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="GHiKl"><code>运行python脚本convert_hf_checkpoint.py
检查点目录为checkpoints/mistralai/Mistral-7B-Instruct-v0.1</code></pre></p>
    数据准备

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="rIQkP"><code>运行python脚本prepare_alpaca.py
--checkpoint_dir checkpoints/mistralai/Mistral-7B-Instruct-v0.1</code></pre></p>
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="Idrbe"><code># or from a custom CSV file
运行Python脚本prepare_csv.py
--csv_dir MyDataset.csv \
--checkpoint_dir checkpoints/mistralai/Mistral-7B-Instruct-v0.1</code></pre></p>
    进行监督微调

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="A8tl1"><code>python finetune/lora.py \
检查点目录为 checkpoints/mistralai/Mistral-7B-Instruct-v0.1/
--precision bf16-true</code></pre></p>
    将Lora权重合并到原始模型上

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="dDgG6"><code>运行Python脚本merge_lora.py
检查点目录为“checkpoints/mistralai/Mistral-7B-Instruct-v0.1”
lora路径为“out/lora/alpaca/Mistral - 7B - Instruct - v0.1/lit_model_lora_finetuned.pth”
输出目录为“out/lora_merged/Mistral - 7B - Instruct - v0.1/”
检查点cp /mistralai/Mistral-7B-Instruct-v0.1/中的所有.json文件


输出/低功耗广域物联网合并/米斯特拉尔7B指令v0.1/</code></pre></p>
    效果评估

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="jEM5T"><code>运行python eval/lm_eval_harness.py文件
检查点目录为“out/lora_merged/Mistral-7B-Instruct-v0.1/”
评估任务为“算术二维,……,真实问答多项选择”
--precision "bf16-true" \
--batch_size 4 \
--num_fewshot 0 \
保存文件路径为“results.json”</code></pre></p>
    模型使用

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="qTTR8"><code>python chat/base.py \
检查点目录为“out/lora_merged/Mistral-7B-Instruct-v0.1/”</code></pre></p>
    选择一个好的基础模型

    首先我要为LoRA实验挑选一个合适的基础模型。这里我关注的是未经过指令微调的模型。包括phi-1.5 1.3B、7B、Llama 2 7B、Llama 2 13B和40B。需要注意的是所有实验都在单个A100 GPU上运行。

    从上表能看出,7B模型在数学基准测试里表现极为出色。同时,鉴于其规模相对较小,phi - 1.5 1.3B模型在MC2上展现出令人赞叹的性能。因某种缘由,Llama 2 13B在算术基准测试中表现不佳,而较小的Llama 2 7B在这方面表现明显优于它

    研究人员和从业者目前推测phi-1.5 1.3B和7B可能已在基准测试数据上训练过。所以我不在实验中使用它们。此外我认为选择剩余模型中最小的一个。能在保持较低硬件要求时提供最大改进空间。因此本文剩余部分聚焦于Llama 2 7B

    评估LoRA的默认设置

    首先 我评估了LoRA的微调 使用的是以下默认设置 这些设置可在/lora.py脚本中更改

    你提供的内容似乎不太完整或存在乱码,不太能明确准确意思进行改写,请补充完整清晰的内容。

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre id="sT2Wa"><code># Hyperparameters
learning_rate = 3e-4
batch_size = 128
micro_batch_size = 1
最大迭代次数为50000 这是训练数据集的大小
weight_decay = 0.01
lora_r = 8
lora_alpha = 16
lora_dropout = 0.05
lora_query = True
lora_key = False
lora_value = True
lora_projection = False
lora_mlp = False
lora_head = False
warmup_steps = 100</code></pre></p>
    请注意,批处理大小是128。我们运用带有1个微批处理的梯度累积来节省内存。这使得训练轨迹与常规使用128批处理大小的训练一样。

    这个配置训练了个LoRA参数 总共有个可训练参数 在我使用单个A100的机器上 大约花费了1.8小时 最大内存使用量为21.33GB

    我重复进行了三次实验。目的是衡量差异。我观察了性能的波动。这波动存在于不同运行之间。

    正如我们在上表中所见到的,不同运行间的性能极为一致且稳定。同样值得留意的是,LoRA默认模型在算术任务上表现欠佳。但这或许是因为,据我所知,数据集中并无(或仅有极少)算术任务。

    另外 我对Meta用RLHF对7B Llama 2版本做指令微调后的模型展开了研究 根据下表 Meta的Llama 2 Chat模型在算术性能方面表现更差 不过 Chat模型在其他基准测试中 除BLiMP外 取得了显著进步 我们能够把它当作我们想通过LoRA微调去接近的参考

    使用QLoRA节省内存

    在我们着手调整LoRA超参数前 我想探究QLoRA 也就是一种流行的量化LoRA技术 该技术由等人提出 在模型性能与内存节省间的权衡情况

    我们能够借助在Lit - GPT里使用–标志来启用QLoRA。这里采用4位正常浮点类型。具体如下所示:

    另外 我尝试了4位浮点精度作为对照 以下是其对训练时间的影响 以及对最大内存使用量的影响

    默认LoRA(使用-16):

    通过–- “bnb.nf4”启用的QLoRA:

    通过– “bnb.fp4”启用的QLoRA:

    我们能够看到 QLoRA 使内存需求减少了将近 6GB。不过,其代价是训练时间延长了 30%。这是因为存在额外的量化步骤以及反量化步骤。

    接下来,让我们看看QLoRA训练如何影响模型性能:

   


    从上表能看出,和常规QLoRA相比,QLoRA对模型性能有影响。模型在算术基准测试里有改进。但在MMLU全球事实基准测试中下降了。

    内存节省相当可观。这通常会超过较长的训练时间。因为它允许用户在较小的GPU上运行模型。所以我将在本文的其余部分使用QLoRA。

    学习率调度器和SGD

    我在之前的全部实验里都用了AdamW优化器,它是LLM训练的常用选择。但大家都知道,Adam优化器可能很占内存。这是由于它为每个模型参数引入并跟踪两个额外参数,即动量m和v。大型语言模型有很多模型参数,像我们的Llama 2模型就有70亿个模型参数。

    本节要探讨把AdamW换成SGD优化器值不值得。不过,对SGD优化器来说,引入学习率调度器特别重要。我选了个余弦退火调度。它在每次批量更新后会降低学习率。

    不幸的是,将AdamW替换为SGD只节省了少量内存。

    这或许是由于大部分内存用于大型矩阵乘法。而非用于存储额外参数。

    但这种小差异或许在预料之中。在当前所选的LoRA配置(r = 8)下,我们有个可训练参数。若Adam为每个模型参数添加2个额外值,且以16位浮点数存储,那么我们有乘以2乘以16位,即134.22兆比特,也就是16.78兆字节。

    当把LoRA的r增加到256时能观察到更大差异 这一点稍后会做 在r等于256的情况下 有个可训练参数 用上述同样计算方法 相当于2.6GB 实际测量结果显示有3.4GB的差异 可能是因为存储和复制优化器状态存在一些额外开销

    底线是 对于少量可训练参数 比如在LoRA和低r(秩)值的情况 与预训练相比 预训练时训练了更多参数 使用SGD替换AdamW 内存收益可能非常小

    尽管SGD在此处未带来明显的内存节省 但我们还是快速查看一下结果模型的性能

    看来,SGD优化器的性能和AdamW差不多。有意思的是,给AdamW添加调度器后,MC2和MMLU全球事实性能有所提升,不过算术性能有所降低。(注:MC2是其他公共排行榜上被广泛认可的基准测试。)当前,我们不会过度看重算术性能,会在本文后续实验中使用带调度器的AdamW。

    要是您想复制这些实验。我发现AdamW最佳学习率是3e - 4。其衰减率为0.01。SGD最佳学习率是0.1。动量为0.9。这两种情况下。我都用了额外100步学习率热身。

    并且现在默认启用

    多次迭代数据集

    到目前为止 我已用50k次迭代训练所有模型 数据集有50k个训练示例 一个明显问题是 我们能否通过多次迭代训练集提高模型性能 所以我用100k次迭代运行之前实验 这是两倍的增加

    有趣的是,迭代次数增加致使整体性能下降。算术基准测试的下降最为显著。我的假设是,数据集未包含任何相关算术任务。当模型更多关注其他任务时,它会主动忘掉基本算术运算。

    无论如何要是说这个结果不让人欣慰那就是说谎如此我就能在本文剩余部分继续开展较短的50k次迭代实验

    LoRA超参数调整第一部分:对所有层启用LoRA

    既然我们已经探究了围绕LoRA微调脚本的基本设定,现在让我们把注意力放到LoRA超参数自身。在默认情形下,LoRA仅针对多头自注意力块里的Key和Query矩阵启用。现在,我们还将其用于Value矩阵、投影层以及线性层

    LoRA超参数调整第二部分:增加R

    LoRA参数里极为重要的一个是“r”。它决定LoRA矩阵的秩。它也决定LoRA矩阵的维度。它会直接对模型的复杂度产生影响。它还会直接对模型的容量产生影响。较高的“r”意味着具备更强的表达能力。不过较高的“r”可能致使过拟合。而较低的“r”能够减少过拟合。只是较低的“r”是以表达能力降低作为代价的。我们保持对所有层启用LoRA。我们把r从8增加到16。我们看看这对性能会产生什么影响。

    我们能够看到,只是增加r本身,结果变差了。那么究竟发生了什么呢?答案在下一节中寻找。

    LoRA超参数调整第三部分:改变Alpha

    在上一节里 我们提升了矩阵秩r 同时让LoRA的alpha参数维持不变 较高的“alpha”会更加强调低秩结构或正则化 较低的“alpha”则会削弱其影响 让模型更多依靠原始参数 调整“alpha”有助于在拟合数据与通过正则化模型防止过拟合之间寻得平衡

    作为经验法则,微调语言模型时一般选一个alpha。其大小是秩的两倍。注意,处理扩散模型时情况不同。我们来试试,看看把alpha增加一倍会怎样。

    我们能够看到,把alpha提升至32,如今生成了目前为止最佳的模型!然而,我们是以更多可训练参数作为代价才取得这一改进的:

    r=8:

    r=16:

    然而可训练参数数量依旧足够小。小到不会明显影响峰值内存需求。

    无论如何 我们现在终于开始取得一些成果 是通过更明显的幅度改进模型性能取得的 那么 让我们继续前进 看看通过增加秩和alpha能够达到多远

    我还做了一些额外实验。这些实验使用的秩异常大,分别是512、1024和2048。但这些实验结果不好。有些运行在训练期间甚至没有收敛到接近零的损失。所以我没把它们添加到表格中。

    到目前为止 我们能留意到 最后一行中 r 等于256且alpha等于512的模型 总体表现最佳 作为额外对照实验 我重复了alpha为1的运行 并注意到 大的alpha值 对良好性能确实是必要的

    我重复了使用alpha值为16的实验。我重复了使用alpha值为32的实验。我观察到。与选择alpha值为秩的两倍相比。性能同样更差。

    LoRA超参数调整第四部分:非常大的R

    对于本文最后一个调整实验 我想进一步优化上一节最佳模型的alpha值 其r为256 位于最后一行 我怀疑该值可能有点过大

    如下表所示 增加秩的时候 选择较大的alpha值 似乎至关重要

    对于QLoRA模型,其中r等于256且a等于512,很明显我们的模型相较于基础模型有了显著改进。唯一存在不足的区域是,微调模型在四位数算术方面的表现不如基础模型。不过,考虑到数据集或许未包含此类训练示例,这是能够理解的。

    上面我们看到 选择alpha为秩的两倍的常见建议产生了最佳结果 比如r等于256且alpha等于512 较小的alpha值导致了更差的结果 但是 将alpha增加到“秩的两倍”建议之外会怎样呢

    依据上表给出的结果来选择。alpha值超过“秩的两倍”这种建议。会让基准测试结果变差。

    结论

    本文对使用LoRA训练自定义LLM时能调整的各类设置展开了探索。我们发觉QLoRA是个不错的内存节省工具,虽说它提升了运行时间成本。另外,虽说学习率调度器或许有益处,但在AdamW和SGD优化器间做选择影响较小。并且,多次迭代数据集甚至可能让结果变差。通过优化LoRA设置(含秩)能够获得最佳性价比。增加秩会致使出现更多可训练参数。这有可能引发更高程度的过拟合现象。还会造成运行成本增加。不过。在增加秩的时候。选择适宜的alpha值是很关键的。

更多帖子推荐

您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|小黑屋|关于我们

Copyright © 2001-2025, Tencent Cloud.    Powered by Discuz! X3.5    京ICP备20013102号-30

违法和不良信息举报电话:86-13718795856 举报邮箱:hwtx2020@163.com

GMT+8, 2025-4-28 19:40 , Processed in 0.088868 second(s), 17 queries .