深入理解三种PEFT方法:LoRA的低秩更新、QLoRA的4位量化与DoRA的幅度-方向分解

简介: 大模型全量微调显存开销巨大(65B模型需130GB),参数高效微调(PEFT)应运而生。LoRA通过低秩矩阵增量更新,节省99%+参数;QLoRA结合4-bit量化(NF4)与LoRA,单卡48GB即可微调65B模型;DoRA进一步解耦权重的幅度与方向,精度显著超越LoRA。三者协同构建高效、低成本、高性能的微调新范式。

LLaMA、Mistral、Qwen这些大语言模型动辄数十亿参数,在自定义数据上全量微调代价极高:65B 模型光是 float16 就要消耗掉约 130GB 显存,顶配硬件跑个几天几周很正常而多数下游任务根本用不到那么多参数。

于是研究者们开始思考:能不能只调一小部分参数,效果还不差?答案是可以。这类方法统称为参数高效微调(PEFT)。LoRA、QLoRA、DoRA 各自从不同角度切入这个问题。

LoRA——低秩自适应

论文:LoRA: Low-Rank Adaptation of Large Language Models, Hu et al. (ICLR 2022)

核心思想

LoRA 的做法很简单,冻结原始权重矩阵 W在旁边挂两个小的可训练矩阵 A 和 B。前向传播时的计算表达式为:

 output = W·x + (B·A)·x × (alpha/r)

训练过程中只更新 A 和 B,W 保持不动。这里的秩 r 是分解的瓶颈维度常见取值 4、8 或 16。alpha 是缩放因子控制 LoRA 更新的强度。

参数量的减少非常明显以一个 (4096, 4096) 的权重矩阵为例,原始参数量是 1670 万换成 rank=8 的 LoRA 之后,A 的维度 (8, 4096) 有 32,768 个参数,B 的维度 (4096, 8) 同样 32,768 个,加起来总共 65,536——比原来少了 99.6%。

LoRA 论文中一个关键发现是,微调过程中大部分有意义的权重更新本来就集中在低维子空间里,所以把更新约束在低秩矩阵上并不会造成多大损失。

微软官方仓库中 Linear 层的实现:

 # Source: github.com/microsoft/LoRA — loralib/layers.py 

 class Linear(nn.Linear, LoRALayer):  
     def __init__(  
         self,  
         in_features: int,  
         out_features: int,  
         r: int = 0,  
         lora_alpha: int = 1,  
         lora_dropout: float = 0.,  
         merge_weights: bool = True,  
         **kwargs  
     ):  
         nn.Linear.__init__(self, in_features, out_features, **kwargs)  
         LoRALayer.__init__(self, r=r, lora_alpha=lora_alpha,  
                            lora_dropout=lora_dropout,  
                            merge_weights=merge_weights)  
         if r > 0:  
             self.lora_A = nn.Parameter(  
                 self.weight.new_zeros((r, in_features))  
             )  
             self.lora_B = nn.Parameter(  
                 self.weight.new_zeros((out_features, r))  
             )  
             self.scaling = self.lora_alpha / self.r  
             # Freeze the pretrained weights  
             self.weight.requires_grad = False  

     def forward(self, x: torch.Tensor):  
         if self.r > 0 and not self.merged:  
             # Original frozen weights + low-rank update  
             result = F.linear(x, self.weight, bias=self.bias)  
             result += (  
                 self.lora_dropout(x)  
                 @ self.lora_A.transpose(0, 1)  
                 @ self.lora_B.transpose(0, 1)  
             ) * self.scaling  
             return result  
         else:  
             return F.linear(x, self.weight, bias=self.bias)

实际用于替换注意力投影的写法:

 # Source: github.com/microsoft/LoRA — README [1]  
 import loralib as lora  

 # Before: standard attention projection  
 # qkv_proj = nn.Linear(d_model, 3*d_model)  

 # After: apply LoRA to Q and V, freeze K  
 qkv_proj = lora.MergedLinear(  
     d_model, 3*d_model,  
     r=8,  
     enable_lora=[True, False, True]  # Q=LoRA, K=frozen, V=LoRA  
 )  

 # Mark only LoRA parameters as trainable  
 lora.mark_only_lora_as_trainable(model)

基准测试结果(来自 LoRA 论文 )

论文在 GPT-2(自然语言生成)和 RoBERTa/DeBERTa(GLUE 基准)上做了评测。下面是 GPT-2 在 E2E NLG Challenge 上的成绩,LoRA 与全量微调及其他 PEFT 方法的对比:

 | Method            | Trainable Params | BLEU | NIST | MET  | ROUGE-L | CIDEr |  
 |-------------------|-----------------|------|------|------|----------|-------|  
 | Full Fine-Tuning  | 117M            | 68.2 | 8.62 | 46.2 | 71.0     | 2.47  |  
 | Adapter (Houlsby) | 1.0M            | 66.3 | 8.41 | 45.0 | 69.8     | 2.40  |  
 | Prefix Tuning     | 0.35M           | 68.1 | 8.59 | 46.3 | 70.8     | 2.47  |  
 | LoRA (r=4)        | 0.77M           | 70.4 | 8.85 | 46.8 | 71.8     | 2.53  |

LoRA 不只是持平全量微调而是在训练不到 1% 参数的情况下反超了。论文把原因归结于正则化效应:低秩约束本身起到了防止过拟合的作用。

关键超参数

秩 r 定义瓶颈维度,4 到 16 的范围能覆盖绝大多数场景,r 越大容量越高、参数也越多。Alpha(lora_alpha)是缩放因子,LoRA 更新的有效学习率等于 alpha/r一般设 alpha=2r 是不错的起点。Target Modules 决定 LoRA 挂载到哪些层,注意力中的

q_proj

v_proj

是最常见的选择。

QLoRA——量化 LoRA

论文:QLoRA: Efficient Finetuning of Quantized LLMs, Dettmers et al. (NeurIPS 2023)

LoRA 没彻底解决的问题

LoRA 虽然减少了可训练参数,但基础模型还是得完整加载。65B 模型 float16 要 130GB 显存通常得上多块 A100,大部分研究者手里没这个条件。

QLoRA 先把基础模型量化成 4 位再在上面以 16 位跑 LoRA 适配器。

三大技术创新(来自 QLoRA 论文 )

QLoRA 论文同时引入了三项相互配合的技术。

第一项是 NF4(4-bit NormalFloat)一种专门针对正态分布权重设计的 4 位数据类型。神经网络权重天然服从正态分布NF4 从信息论角度是最优的编码方式,存储效率上比 INT4 和 FP4 都要高出一截。

第二项是双重量化,量化常数(把 4 位值转换回浮点时用的常数)本身也占内存,QLoRA 干脆把量化常数也给量化了,65B 模型上约省 3GB 内存。

第三项针对梯度检查点带来的内存峰值,QLoRA 利用 NVIDIA 统一内存机制,当某条序列在 GPU 上触发 OOM 风险时,自动把优化器状态卸载到 CPU RAM等需要时再换回来。

代码(来自 artidoro/qlora)

 # Source: github.com/artidoro/qlora — qlora.py [2]  
 from transformers import AutoModelForCausalLM, BitsAndBytesConfig  
 from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training  
 import torch  

 # Step 1: Define 4-bit quantization config (NF4)  
 bnb_config = BitsAndBytesConfig(  
     load_in_4bit=True,  
     bnb_4bit_quant_type="nf4",          # NormalFloat4  
     bnb_4bit_compute_dtype=torch.bfloat16,  # Compute in bf16  
     bnb_4bit_use_double_quant=True,     # Double quantization  
 )  

 # Step 2: Load base model in 4-bit  
 model = AutoModelForCausalLM.from_pretrained(  
     "meta-llama/Llama-2-7b-hf",  
     quantization_config=bnb_config,  
     device_map="auto",  
 )  

 # Step 3: Prepare for k-bit training (handles frozen layer casting)  
 model = prepare_model_for_kbit_training(model)  

 # Step 4: Apply LoRA adapters in 16-bit on top  
 lora_config = LoraConfig(  
     r=64,  
     lora_alpha=16,  
     target_modules=["q_proj", "v_proj"],  
     lora_dropout=0.05,  
     bias="none",  
     task_type="CAUSAL_LM",  
 )  
 model = get_peft_model(model, lora_config)

整个过程中基础模型权重始终保持 NF4(4 位、冻结状态)只有 LoRA 适配器权重以 bf16 精度参与训练。

基准测试结果(来自 QLoRA 论文 )

QLoRA 训练出了 Guanaco 系列模型。在 GPT-4 评估的 Vicuna 基准测试中,Guanaco 65B 用单块 48GB GPU 训练了 24 小时,就达到了 ChatGPT 性能的 99.3%。

更关键的一点是4 位量化相比 16 位 LoRA 几乎没有性能损失:

 | Method               | Model | Memory Usage | Vicuna Score vs ChatGPT |  
 |----------------------|-------|--------------|--------------------------|  
 | Full Fine-Tuning (fp16) | 65B   | >780 GB      | —                        |  
 | LoRA (fp16)          | 65B   | ~130 GB     | —                        |  
 | QLoRA (NF4)          | 65B   | ~48 GB      | 99.3%                    |  
 | QLoRA (NF4)          | 33B   | ~24 GB      | 97.8%                    |  
 | QLoRA (NF4)          | 7B    | ~5 GB       | ~87%                     |

7B Guanaco 模型只占 5GB 显存在 Vicuna 基准上却以超过 20 个百分点的差距碾压了 Alpaca 65B。这才是 QLoRA 真正革命性的地方:拿一块普通 GPU 就能微调大规模语言模型门槛一下子降到了底。

DoRA——权重分解低秩自适应

论文:DoRA: Weight-Decomposed Low-Rank Adaptation, Liu et al. (ICML 2024, Oral)

LoRA 表现不错但和全量微调之间始终有一道精度差距,当秩取值较低时这个差距尤为明显——LoRA 没法完整复现全参数更新时的梯度学习行为。

问题出在哪?DoRA 论文提出了一种权重分解分析来回答这个问题。

核心洞察

任何权重矩阵 W 都可以拆成两个分量:

 W = m × (V / ||V||_c)

其中 m 是幅度分量,这个标量向量反映每个输出神经元权重的"大小";V / ||V||_c 是方向分量,即权重的单位方向向量。

DoRA 论文发现,全量微调时幅度和方向是以灵活、耦合的方式同步更新的。但 LoRA 的更新方式把两者绑在一起,主要只改变了方向上的朝向反而限制了模型的学习能力。

DoRA 的做法是把两者拆开:冻结分解结构后,只让 LoRA 作用于方向分量,同时把幅度 m 当作独立的可学习标量自由更新。

 W' = (m + Δm) × ((V + ΔV_LoRA) / ||V + ΔV_LoRA||_c)

这样一来 LoRA 的学习模式就更接近全量微调了。并且由于幅度和方向在部署前可以合并回单个权重矩阵,推理阶段零额外开销。

代码(来自 NVlabs/DoRA )

DoRA 的前向传播逻辑,简化后展示核心分解机制:

# Source: github.com/NVlabs/DoRA — adapted from DoRA paper implementation [3]  
import torch  
import torch.nn as nn  
import torch.nn.functional as F  

class DoRALayer(nn.Module):  
    def __init__(self, d_in, d_out, rank, lora_alpha):  
        super().__init__()  

        # Frozen pretrained weight  
        self.weight = nn.Parameter(  
            torch.randn(d_out, d_in), requires_grad=False  
        )  

        # Learnable magnitude (one scalar per output neuron)  
        self.m = nn.Parameter(  
            self.weight.norm(p=2, dim=1, keepdim=True)  
        )  

        # LoRA matrices for directional updates (trainable)  
        std = 1 / torch.sqrt(torch.tensor(rank).float())  
        self.lora_A = nn.Parameter(torch.randn(d_in, rank) * std)  
        self.lora_B = nn.Parameter(torch.zeros(rank, d_out))  

        self.rank = rank  
        self.scaling = lora_alpha / rank  

    def forward(self, x):  
        # Compute the directional update from LoRA  
        lora_update = (self.lora_A @ self.lora_B).T * self.scaling  

        # Adapted weight = base weight + LoRA update  
        adapted = self.weight + lora_update  

        # Column-wise normalization → unit direction vectors  
        column_norms = adapted.norm(p=2, dim=1, keepdim=True)  
        V_normalized = adapted / column_norms  

        # Scale by learned magnitude  
        effective_weight = self.m * V_normalized  

        return F.linear(x, effective_weight)

通过 HuggingFace PEFT 启用 DoRA(peft>=0.9.0 已支持 ):

# Source: HuggingFace PEFT documentation — DoRA is supported from peft>=0.9.0 [3]  
from peft import LoraConfig, get_peft_model  

lora_config = LoraConfig(  
    r=16,  
    lora_alpha=32,  
    target_modules=["q_proj", "v_proj"],  
    lora_dropout=0.05,  
    bias="none",  
    task_type="CAUSAL_LM",  
    use_dora=True,   # ← This single flag enables DoRA  
)  

model = get_peft_model(model, lora_config)

就一个标志位这是和 LoRA 配置的唯一区别。

基准测试结果(来自 DoRA 论文 [3])

DoRA 论文在 8 个常识推理数据集(BoolQ、PIQA、HellaSwag、WinoGrande、ARC-e、ARC-c、OBQA 及综合平均)上做了评测,在 LLaMA-7B 和 LLaMA2-7B 两个模型上与 LoRA 对比,秩相同、可训练参数量相同,确保公平:

| Method        | BoolQ | PIQA | HellaSwag | WinoGrande | ARC-e | ARC-c | OBQA | Avg   |  
|--------------|-------|------|-----------|------------|-------|-------|------|-------|  
| Full FT      | 69.4  | 82.3 | 89.7      | 82.4       | 79.8  | 60.7  | 81.6 | 77.99 |  
| LoRA (r=32)  | 68.9  | 80.9 | 90.0      | 82.1       | 78.2  | 59.8  | 80.0 | 77.13 |  
| DoRA (r=32)  | 70.0  | 83.6 | 91.0      | 83.0       | 81.4  | 65.8  | 83.4 | 79.75 |

8 个数据集上 DoRA 全面胜出。差距在复杂推理任务上尤其明显比如 ARC-c 从 LoRA 的 59.8 跳到 65.8,幅度相当大。论文还跑了 LLaVA-1.5-7B 的视觉指令调优和 VL-BART 的图像/视频-文本理解实验,DoRA 同样全面压过 LoRA。

对比

内存需求

| Method                  | LLaMA 7B | LLaMA 13B | LLaMA 33B | LLaMA 65B |  
|-------------------------|----------|-----------|-----------|-----------|  
| Full Fine-Tuning (fp16) | ~28 GB   | ~52 GB    | ~130 GB   | ~260 GB   |  
| LoRA (fp16)             | ~14 GB   | ~26 GB    | ~65 GB    | ~130 GB   |  
| QLoRA (NF4)             | ~5 GB    | ~8 GB     | ~20 GB    | ~48 GB    |  
| DoRA (fp16)             | ~14 GB   | ~26 GB    | ~65 GB    | ~130 GB   |

DoRA 因为多了一个幅度向量(每个目标层的每个输出神经元一个标量),会有少量额外开销但实际可以忽略。

与全量微调的性能对比

| Method            | Commonsense Reasoning | Instruction Tuning     | Memory     |  
|-------------------|-----------------------|------------------------|------------|  
| Full Fine-Tuning  | Baseline              | Baseline               | Very High  |  
| LoRA              | -0.86 avg             | Comparable             | Medium     |  
| QLoRA             | ~Same as LoRA         | 99.3% of ChatGPT       | Low        |  
| DoRA              | +2.62 avg over LoRA   | Better than LoRA       | Medium     |

训练速度(相对值)

 | Method | Speed                                   |  
 |--------|------------------------------------------|  
 | LoRA   | Fast                                     |  
 | DoRA   | Fast (near identical to LoRA)            |  
 | QLoRA  | Moderate (quantize/dequantize overhead)  |

各场景下的最佳选择

该用 LoRA 的场景

显存 16GB 以上,模型不超过 13B 左右想要一个稳定可靠、经过实战验证的方案。所有后续方法都建立在 LoRA 之上,HuggingFace 的 PEFT 生态围绕它搭建,工具链最成熟。没做过 PEFT 的人从这里入手最省心。

该用 QLoRA 的场景

显存小但又想跑 30B 以上的大模型。QLoRA 让单块 48GB GPU 微调 LLaMA-65B 成为现实,24GB 显存就能跑 LLaMA-33B。用免费 Colab T4(15GB 显存)想动 20B+ 模型的话,QLoRA 基本是唯一可行方案。

该用 DoRA 的场景

在跟 LoRA 一样的参数预算下追求最高精度,DoRA 是 LoRA 的即插即用替代品配置里加个

use_dora=True

就行推理零成本,并且在复杂推理任务上提升尤为突出。

该用 QLoRA + DoRA(QDoRA)的场景

既要省显存又要高精度这种组合已获官方支持,实验数据证明效果优于单纯的 QLoRA。部分早期实验甚至表明 QDoRA 能持平乃至超过全量微调。

总结

2025 年的微调生态分三层:LoRA 是底座,简单、快、生态好,多数场景够用;QLoRA 打开了消费级显卡微调大模型的大门精度还没怎么掉;DoRA 则是免费升级——跟 LoRA 成本一样但结果更好,

use_dora=True

一行代码就能搞定。

三种方法各有分工,互为补充,你唯一需要考虑的是哪种 PEFT 方案最贴合自己的硬件条件和精度要求。

https://avoid.overfit.cn/post/154732e0b0474f2ea8e2a4dac0d16819

by Harish K

目录
相关文章
|
3天前
|
存储 自动驾驶 物联网
大模型应用:高精度量化感知训练(QAT)与低成本后训练量化(PTQ)方案优选.55
本文深入解析大模型量化两大核心技术:后训练量化(PTQ)与量化感知训练(QAT)。涵盖原理、流程、代码实现及选型策略,对比其在精度损失、算力成本、部署效率等方面的差异,助开发者根据数据、算力与精度需求,科学选择最优量化方案。
97 15
|
19天前
|
传感器 数据采集 运维
VAE 原理拆解:从概率编码到潜在空间正则化
本文深入浅出拆解VAE构建全流程,聚焦实现、训练、调试与部署,而非纯数学推导。逐行解读PyTorch最小实现,详解编码器、重参数化、解码器三大组件及损失设计,并系统介绍训练后五大推理模式:异常检测、生成合成数据、条件生成、潜在空间分析与数据填补。
114 7
VAE 原理拆解:从概率编码到潜在空间正则化
|
1月前
|
编解码 atlas ice
MEaSUREs 格陵兰冰盖测绘项目(GrIMP)基于 GeoEye 和 WorldView 影像的数字高程模型 V002
MEaSUREs格陵兰冰绘图计划(GrIMP)V002 DEM,基于GeoEye与WorldView系列卫星亚米级立体影像生成,空间分辨率高,经ICESat-2 ATL06数据精校准,适用于冰盖高程变化研究。(239字)
130 15
|
11天前
|
监控 安全 区块链
基于Windows Terminal的ClickFix攻击链演化与防御机制研究
本文剖析2024年兴起的“ClickFix”新型网络钓鱼攻击:攻击者从诱导用户使用Win+R转向更隐蔽的Win+X→I启动Windows Terminal执行恶意命令,绕过传统检测与安全培训。文章深入解析其多阶段载荷投递、LOLBin滥用、EtherHiding及QueueUserAPC内存注入等关键技术,并提出“零信任命令执行”理念与技术管控、认知重构并重的防御策略。(239字)
91 16
|
9天前
|
供应链 安全 数据安全/隐私保护
供应链投毒与窃密木马的协同攻击机制及防御策略
本文剖析供应链投毒与Stealer木马协同攻击新范式,揭示其通过污染GitHub、滥用CI/CD、依赖混淆等手段实现隐蔽窃密的全链路机制,并提出融合SBOM验证、行为启发式分析与零信任架构的主动防御框架。(239字)
94 12
|
9天前
|
数据采集 JSON API
从踩坑到高效落地:关键词搜索京东商品列表API的实操心得
本指南聚焦京东商品列表API实操,详解jd.item_search接口调用要点:涵盖必填参数(app_key、timestamp、sign等)、关键词/分页/价格筛选配置及核心响应字段(SKU、标题、售价、销量等),助开发者快速对接,高效获取合规商品数据。(239字)
129 22
|
4天前
|
XML 人工智能 JavaScript
后假期时代AI钓鱼与恶意SVG载荷的持续演进及防御策略
本文分析2025–2026年“假日后效应”下AI钓鱼与恶意SVG攻击的常态化趋势:攻击者利用大语言模型生成高迷惑性邮件,借SVG文件嵌入JavaScript绕过网关检测。研究揭示传统签名/沙箱防御失效,强调需转向端侧行为监控、XML深度解析与用户认知重塑的弹性防御体系。(239字)
85 14
|
15天前
|
人工智能 前端开发 Serverless
vLLM + SGLang + Ollama 自动适配!阿里云 Qwen3 部署智能选引擎
阿里云Qwen3正式开源8款混合推理模型(含2款MoE、6款Dense),支持119种语言,适配vLLM/SGLang/Ollama。依托函数计算FC与FunctionAI平台,提供模型服务与应用模板两种Serverless部署方式,最低GPU配置即可快速体验。
586 20
|
9天前
|
供应链 安全 Shell
ExifTool元数据解析漏洞机制与macOS供应链防御研究
本文深度剖析ExifTool高危漏洞CVE-2026-3102:攻击者通过构造恶意图像元数据,在macOS下利用`-n`参数触发远程代码执行。漏洞源于解析逻辑缺陷,非传统内存破坏,隐蔽性强。文章揭示“文件即武器”新范式,提出补丁更新、输入验证、沙箱隔离与最小权限等纵深防御方案,并附PoC与实操脚本。(239字)
71 18
|
2天前
|
存储 机器学习/深度学习 自然语言处理
56.大模型应用:大模型瘦身:量化、蒸馏、剪枝的基础原理与应用场景深度解析.56
本文深入对比大模型轻量化三大核心技术:量化(降精度,快部署)、蒸馏(知识迁移,高精度)、剪枝(删冗余,结构精简)。详解原理、分类、适用场景、代码实现及选型建议,助开发者根据硬件条件、精度要求与落地周期科学决策。
159 16