超越LoRA:微调技术对标分析
对比LoRA与其他微调方法的性能和应用场景,帮助ML工程师选型。
对比LoRA与其他微调方法的性能和应用场景,帮助ML工程师选型。
如果你想用自己的数据微调一个开放模型,那么你很可能会对所谓的参数高效微调(parameter-efficient fine-tuning,简称 PEFT)感兴趣。这个术语泛指一类能够显著降低模型微调内存需求的技术。尽管这类技术有几十种,但几乎所有人都会选择其中一种——“LoRA”。本文将探讨:LoRA 是否真的是最佳选择,有哪些工具可以帮助你做出明智的决定,以及把视野扩展到 LoRA 之外能为你带来什么好处。
市面上有无数开放模型,但它们往往还不足以很好地满足你的具体用例。使用 prompt 或许能有所帮助,但通常还不够。与其从头训练一个新模型,不如考虑微调一个现有模型。
然而,微调非常吃内存:通常需要足够大的内存,才能同时容纳好几份完整模型。量化可以减少模型的内存占用,但量化后的模型无法直接进行微调。于是,一系列旨在降低微调内存需求的技术应运而生,这类技术被称为“参数高效微调”,即 PEFT。
借助 PEFT,你只需使用原来一小部分的内存就能微调模型,甚至还能微调量化模型。它还具备其他优势,例如 checkpoint 体积很小、更不容易发生灾难性遗忘,以及可以基于同一个基础模型提供多个微调版本的服务。
在 Hugging Face,我们开发了 PEFT library。它通过统一的 API 实现了多种 PEFT 技术,并与整个生态系统良好集成,例如 Transformers 和 Diffusers。它还支持多种量化方法,进一步降低了参数高效微调的使用门槛。无论你是想用自己的数据进行微调,还是正在研究一种新的 PEFT 方法,PEFT 都是一个很好的起点。
有一种很早就出现、且被证明相当有效的参数高效微调技术,叫作“Low Rank Adaptation”,简称“LoRA”。它的工作方式是:在基础模型之上添加少量参数,冻结基础模型的权重,只训练这些新增参数。
在所有 PEFT 技术中,LoRA 是迄今最受欢迎的一种。下面是几组估算数据:
在 Hugging Face Hub 上随机抽取的 20,834 个 model card 中,这些 model card 都只提到了一种 PEFT 技术,其中有 20,509 个提到了 LoRA,占 98.4%。
我们也调查了某个外部网站上用于图像生成的 PEFT 技术流行度。在抽取的 10,000 个 checkpoint 中,有 7,111 个是 LoRA。其他识别出的 PEFT 技术分别是 LoCon(363 个)和 DoRA(11 个,严格来说也可以算作 LoRA 的变体)。这意味着,在所有 PEFT checkpoint 中,LoRA 占到了 95.0%。
在 GitHub 上搜索代码片段 from peft import <PEFT CONFIG>(示例 GH query),71.3% 的结果与 LoRA 有关。紧随其后的是 LoHa(3.7%)和 AdaLoRA(3.5%)。
尽管这些估算并不完美,但结论依然很明确:LoRA 几乎肯定是目前最常见的 PEFT 技术,而且领先幅度非常大。
这可能仅仅意味着 LoRA 对所有人来说效果都最好,而其使用统计数据也反映了这一事实。但还有另一种可能:LoRA 是较早出现并流行起来的 PEFT 技术之一,因此它的使用可能形成了自我强化。LoRA 的曝光度最高,教程和示例数量最多,在下游 package 中获得的支持也最好。于是,LoRA 的流行进一步推动了它自身的流行。
这一切最终引出了一个问题:我们是否因为冷落了更好的技术,而白白损失了本可以获得的性能?毕竟,无数研究者都在论文中声称自己的技术优于 LoRA。这难道还不足以证明,我们应该放弃 LoRA,转向更新的技术吗?
有几十篇论文研究了 LoRA 以外的微调技术。仅在 PEFT library 中,截至本文写作时就已经有 40 多种不同的 PEFT 技术;如果把各种 PEFT 技术的变体也计算在内,数量还会更多。对于其中几乎每一种技术,你都能找到研究者声称,根据他们的 benchmark,自己的技术优于 LoRA。
这些说法的问题在于,研究者面临着必须拿出超越现有 benchmark 结果的压力。即使研究者并无恶意,这种压力也可能使结果产生偏差。例如,与调整研究者自己提出的技术相比,他们可能花更少的时间调整其他备选技术。有一项研究就发现,只需调整 learning rate,LoRA 便可以达到那些号称更加优秀的 PEFT 技术的水平。
另一个复杂之处在于,每篇论文选择用于对比的 PEFT 技术都不一样,运行的 benchmark 组合也各不相同。即使同一种技术在同一个 benchmark 上进行比较,相关代码通常也没有公开,或者很难由你亲自运行,因此结果难以复现。
总的来说,如果只查看论文中的结果,很难判断哪种 PEFT 技术最适合你。因此,你可能会倾向于直接选择默认方案 LoRA。
在 Hugging Face,我们一直在思考如何帮助用户做出更加明智的决定,选出适合自己的 PEFT 技术。通过 PEFT library,我们已经提供了一个实现多种 PEFT 技术、并通过同一套 API 暴露这些技术的 package。下一步,就是提供能够进一步揭示上述问题的 benchmark。
我们已经有一套 benchmark,并用它在数学数据集上测试 LLM 的微调效果,这套 benchmark 已经运行了一段时间。它会选取一个没有经过指令微调的基础 LLM,通过 chain-of-thought 推理数据对其进行微调,让模型生成数学问题的答案。因此,这套 benchmark 不仅会检查模型能否学会进行数学推理,还会检查模型能否把生成的输出调整为预期格式。
为了把研究结果扩展到另一种模态,我们还增加了一套图像生成 benchmark。它测试模型能否通过微调学会一个新概念——一只猫咪毛绒玩具,并在不遗忘现有概念的前提下,将它生成到新的上下文中。
所有 PEFT 技术都在完全相同的条件下接受评估:相同的基础模型、相同的数据集、相同的训练与评估代码,以及相同的硬件。由于不同用户的需求各不相同,我们追踪的不只是测试性能。除了 VRAM 使用量,我们还会追踪遗忘或漂移、运行时间以及 checkpoint 大小等指标。这些实验被设计为可以在消费级硬件上运行,而添加一个新实验只需要增加一份新的 PEFT config,然后运行一个脚本。
由于我们在完全公平的条件下比较所有 PEFT 技术,而且并不偏向其中任何一方,因此我们相信,这些 benchmark 能够客观呈现不同 PEFT 技术的实际表现。我们认为,如果你有自己的数据集,也可以采用类似的方法,利用 PEFT library 评估多种 PEFT 技术。
完成 benchmark 实验后,我们发现:尽管 LoRA 表现不错,但其他 PEFT 方法可以在一个或多个维度上超越它,因此同样值得考虑。请查看下图,其中对比了 LoRA 和另外五种 PEFT 技术的表现。
解读上述结果的一种方式,是从权衡的角度思考。例如:模型在测试集上的表现有多好,与训练它需要多少内存,这两者之间有何关系?如果不存在另一种技术,能够同时在这两个指标上击败某种 PEFT 技术,那么该技术就位于 Pareto Frontier 上。换句话说,如果你希望获得更高的测试准确率,就需要投入更多内存;如果你希望提高内存效率,就必须牺牲准确率。
让我们仔细看看 LLM Math 数据集 benchmark 的结果。在测试准确率与内存使用量之间进行比较时,我们发现 LoRA 确实位于 Pareto Frontier 上。它取得了 53.2% 的测试准确率,峰值 VRAM 需求为 22.6 GB。不过,Pareto Frontier 上还有其他 PEFT 技术。例如,BEFT 的测试准确率为 32.9%,最大内存需求却只有 20.2 GB。另一个极端则是 Lily,它取得了 54.9% 的测试准确率,但需要 25.6 GB 内存。根据你更看重哪一项指标,最终可能会得出结论:LoRA 并没有提供最适合你的权衡方案。
还有一点值得注意:尽管 LoRA 在这个任务上表现良好,但这里讨论的并不是原版 LoRA。一边是采用 rank stabilized initialization 的 LoRA,这种技术会以不同于默认初始化的方式缩放 LoRA 的贡献,并提供非常出色的测试准确率(53.2%)。另一边是 LoRA-FA,它使用专为 LoRA 设计的 optimizer,冻结一部分 LoRA 权重,因此内存效率更高(20.2 GB)。普通 LoRA 在占用 22.5 GB 内存的情况下,准确率仅为 48.1%,因此应该优先选择其他方案,避免使用普通 LoRA。
接下来看看图像生成 benchmark。在 Hugging Face Space 中,从“Select Task”下拉菜单选择“image-gen”即可查看结果。该任务的目标是学习一个新概念,也就是一只猫咪毛绒玩具,并将其泛化到新的 prompt 中。
对这项任务来说,主要指标是“dino similarity”,它衡量生成图像与留出测试数据集中的图片有多相似,数值越高越好。和往常一样,我们也需要关注内存使用量。在绘制这两个指标的 Pareto Frontier 时,我们发现 LoRA 位于这条前沿线之下。来看具体数字:LoRA 的相似度得分为 0.697,而 OFT 达到了 0.708;在内存方面,LoRA 需要 9.97 GB,OFT 则只需要 9.01 GB。因此,在这两个指标上,OFT 都严格优于 LoRA。
当然,你也应该检查其他接近 Pareto Frontier 的 PEFT 方法,因为受随机性影响,指标可能会出现小幅波动。此外,你还应该考察其他指标:运行时性能对你来说是否重要?你是否在意 checkpoint 的大小?从下拉菜单中选择相关指标后,整个结果图景可能会发生很大变化。对于图像生成 benchmark,还应该仔细查看生成的样例图像,直观感受微调后模型的能力。
对 PEFT benchmark 的一种批评是,hyper-parameter 的选择可能会偏向某一种技术。这一点确实存在:面对如此多的技术,要进行穷尽且公平的 hyper-parameter sweep 并不容易。不过,任何人都可以非常轻松地向 PEFT 贡献自己的实验。如果你认为通过选择不同的 hyper-parameter,可以进一步改善某种 PEFT 技术,请创建一个 PR!我们已经添加了相关操作说明。同样,如果你想贡献一套全新的 benchmark,也可以联系我们讨论你的想法。
这些 benchmark 的另一个问题在于,它们可能无法完整体现某一种 PEFT 技术的能力。我们让用户可以从许多不同维度比较各种技术,并根据这些权衡找出最优秀的方案,但这种方式不可能覆盖所有方面。例如,有一种名为 Cartridges 的 PEFT 技术,专门用于压缩长 prompt,而现有 benchmark 并不会衡量这种能力。还有一些其他因素也会影响选择,例如:
根据 PEFT 技术的不同,可能只有特定的 layer 类型可以被修改。
并非所有 PEFT 技术都支持量化基础模型,不过我们正在积极扩大 PEFT 对此的支持范围。
一些 PEFT 技术允许将 adapter 合并到模型中,以减少运行时开销,但另一些技术不支持这样做。
benchmark 无法彻底替你承担研究和判断的责任,但可以提供合理的参考方向。
使用 LoRA 以外的 PEFT 技术存在一个限制:它们无法像 LoRA 那样,在下游 package 中获得广泛支持。例如,如果你想使用 vLLM 提供模型服务,就只能加载 LoRA checkpoint。好在 PEFT 现在已经支持把其他 adapter 转换成 LoRA。这样一来,你就可以把非 LoRA checkpoint 转换为 LoRA,然后在 vLLM 或其他下游 package 中使用。
为了测试这一功能,我们将一个采用 GraLoRA 技术的图像 adapter 转换成了 LoRA checkpoint。转换前后的测试得分几乎完全相同(相似度 0.702 → 0.694,0.260 → 0.269)。下面是针对 prompt “sks cat at the beach”生成的测试图像:
目前,我们还没有为所有 PEFT 技术实现转换功能,但如果存在相关需求,我们会扩大支持范围。
在开发 PEFT package 的过程中,我们注意到,尽管其他 PEFT 技术可能更加优秀,LoRA 依然拥有巨大的发展势能。因此,我们着手为 PEFT 添加 benchmark,希望更加客观地呈现不同 PEFT 技术在各项指标上的表现。
根据我们得到的结果,可以有把握地得出结论:LoRA 绝不是一个糟糕的选择,但可能存在更好的选择。尤其是在图像生成 benchmark 中,LoRA 被其他技术超越。我们还讨论了,在选择合适的 PEFT 技术时,除了指标之外,还必须考虑其他因素。即便如此,我们仍在继续推进 PEFT,争取让 LoRA 与其他技术在功能支持上达到同等水平。
我们的探索还远未结束。我们希望继续扩展并改进现有 benchmark,未来也计划加入更多 benchmark。我们已经确保社区可以轻松参与贡献。因此,如果你对此感兴趣,请在 PEFT repository 中创建 issue,告诉我们你希望如何参与贡献。
如果你只能从本文中记住一件事,那就是:在为自己的用例选择 PEFT 技术时,不应该自动把 LoRA 当作默认选项。得益于 PEFT 提供的统一 API,从一种 PEFT 技术切换到另一种技术,只需更换代码中的一个 config。即使你仍然决定使用 LoRA,也请了解一下 PEFT 支持的各种 LoRA 变体:DoRA、rs-LoRA、LoRA-FA 等。尝试一下这些其他技术,结果可能会给你带来惊喜。
示例:使用 PEFT 从 LoRA 切换到 OFT:
from transformers import AutoModelForCausalLM
-from peft import LoraConfig, get_peft_model
+from peft import OFTConfig, get_peft_model
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-3B", dtype="bfloat16")
-config = LoraConfig(target_modules=["q_proj", "v_proj"])
+config = OFTConfig(target_modules=["q_proj", "v_proj"])
model = get_peft_model(base_model, config)
本文提及的数据集 2
本文提及的 Spaces 1
本文提及的论文 3
全世界的 LoRA 训练脚本,联合起来!
TGI Multi-LoRA:一次部署,服务 30 个模型
感谢你的分析,非常有帮助。
DEFT 怎么样?它将预训练权重矩阵的更新分解为两个分量,并通过两个可训练矩阵对其进行适配:(1)投影到由一个低秩矩阵张成的低秩子空间的补空间上;(2)一次低秩更新。其中,一个可训练的低秩矩阵负责定义该子空间,另一个可训练的低秩矩阵则支持在该子空间内进行灵活的参数适配。
GitHub https://github.com/MAXNORM8650/DEFT
论文:https://arxiv.org/abs/2509.22793
你们愿意为此向 PEFT 提交一个 PR 吗?
OFT 有 version 2,并且跳过了 version 1。你们测试的是哪个版本?
测试的是更新后的 OFT version 2:https://github.com/huggingface/peft/pull/2575。
· 注册或登录后发表评论
本文提及的数据集 2
本文提及的 Spaces 1
本文提及的论文 3