Qlora和Adalora的详细对比学习
2026/9/11 18:33:03 网站建设 项目流程
  • 一、Adaloar学习
    • 1.1 引出问题
      • 1.1.1 原始 LoRA 的问题:所有层都用同一个 rank
      • 1.1.2 更合理的做法:非均匀分配 rank
      • 1.1.3 进一步演进:AdaLoRA
    • 1.2 AdaLora的特点
      • 1.2.1 AdaLoRA 的核心:总预算不变,重新分配
      • 1.2.2 为什么要这样做?
      • 1.2.3 真正的关键问题
    • 1.3 具体区别展示
      • 1.3.1 LoRA 和 AdaLoRA 的核心区别
      • 1.3.2 为什么要用 `PΛQ`
      • 1.3.3 AdaLoRA 怎么实现动态 rank?
    • 1.4 训练流程
      • 1.4.1 Instruction Data 怎么训练
      • 1.4.2 Loss 怎么来的
      • 1.4.3 AdaLoRA 真正作用在哪里
    • 1.5 原理分析(一)
      • 1.5.1 LoRA → AdaLoRA 的结构变化
      • 1.5.2 为什么要加 `Λ`
      • 1.5.3 AdaLoRA 怎么实现动态 Rank
    • 1.6 原理分析(二)
      • 1.6.1 上半部分:Loss 从哪里来
      • 1.6.2 下半部分:为什么要引入 SVD
      • 1.6.3 SVD 怎么启发 AdaLoRA
    • 1.7 Adalora详细解析
      • 1.7.1 先算每个 Rank 方向的重要性
      • 1.7.2 所有 Rank 做“全局竞争”
      • 1.7.3 不重要的方向直接关闭
    • 1.8 Adalora的重要性评分计算
      • 1.8.1 先给“单个参数”打分
      • 1.8.2 再把参数分数聚合成 Rank 分数
      • 1.8.3 最后拿去做 Rank 剪枝
  • 二、Qlora学习
    • 2.1 引出问题
      • 2.1.1 为什么 LoRA 之后还需要 QLoRA?
      • 2.2.2 QLoRA 的核心思路
      • 2.2.3 它主要解决什么?
    • 2.2 QLoRA 的直接价值:显存大幅下降
      • 2.2.1 传统微调为什么贵
      • 2.2.2 QLoRA 怎么把显存降下来
      • 2.2.3 效果有多明显
    • 2.3 QLoRA 显存优化:从 16-bit Base Model 到 4-bit
      • 2.3.1 QLoRA 真正压缩的是 Base Model
      • 2.3.2 为什么显存能继续下降?
      • 2.3.3 还有一个关键技术:Paged Optimizer
    • 2.4 Full Fine-tuning 的显存成本:70B 为什么约 840 GB?
      • 2.4.1 每个参数不只要存“权重”
      • 2.4.2 70B 模型为什么变成 840 GB?
      • 2.4.3 这就是 LoRA / QLoRA 出现的原因
    • 2.5 Quantization 基础:Float32 怎么映射成 INT8?
      • 2.5.1 核心思路:先缩放,再取整
      • 2.5.2 两个最关键的公式
      • 2.5.3 量化真正的问题:会产生误差
    • 2.6 Quantization 的 Outlier 问题:为什么要做 Block-wise Quantization
      • 2.6.1 Global Quantization 的问题
      • 2.6.2 Block-wise Quantization 怎么解决
      • 2.6.3 为什么又会引出 Double Quantization?
    • 2.7 Quantile:为什么“等概率分箱”更适合低比特量化?
      • 2.7.1 Quantile 不是“等距离”,而是“等数量”
      • 2.7.2 数据越密集,量化就越精细
      • 2.7.3 这就是 NF4 的重要铺垫
    • 2.8 Normal Distribution + Quantile:NF4 为什么要按概率分配量化区间?
      • 2.8.1 神经网络权重通常集中在 0 附近
      • 2.8.2 Quantile 改成“等概率划分”
      • 2.8.3 这正是 NF4 的核心铺垫
    • 2.9 NF4:4-bit 的 16 个量化值到底怎么设计?
      • 2.9.1 NF4 不是等距离量化
      • 2.9.2 为什么必须保留 Exact Zero?
      • 2.9.3 实际怎么量化?
  • 三、思维导图总结

一、Adaloar学习

1.1 引出问题

1.1.1 原始 LoRA 的问题:所有层都用同一个 rank

例如统一设成 r = 8。 但不同层、不同矩阵的重要性并不一样。 结果就是:不重要的地方浪费参数,关键位置又不够用。

1.1.2 更合理的做法:非均匀分配 rank

例如:

ΔW_k^1 → r = 20 ΔW_q^1 → r = 12 ΔW^2 → r = 2

也就是:重要模块多分一点,不重要模块少分一点。

1.1.3 进一步演进:AdaLoRA

在总参数预算基本不变的情况下,动态调整不同模块的秩。 训练过程中把更多容量分给重要方向,压缩不重要方向。

一句话总结: 普通 LoRA 是“大家平均分 rank”,AdaLoRA 更像“谁重要谁多拿预算”,让有限参数用在最关键的位置。

1.2 AdaLora的特点

1.2.1 AdaLoRA 的核心:总预算不变,重新分配

  • 标准 LoRA:每个矩阵都用同一个r,例如r = 8
  • AdaLoRA:允许不同矩阵使用不同的 rank。
  • 但总预算保持不变,例如:
    r₁ + r₂ + ... + r₁₀₀ = 800

1.2.2 为什么要这样做?

  • 不同层、不同矩阵对任务的重要性不同。
  • 如果平均分配 rank,可能出现:
    • 不重要的模块浪费参数
    • 重要模块容量不够
  • 所以更合理的是:重要模块多分,不重要模块少分。

1.2.3 真正的关键问题

AdaLoRA 最核心的问题其实变成了:

How to measure importance? —— 怎么判断谁更重要?

训练过程中先评估各模块/奇异方向的重要性,再动态剪掉不重要的部分,把预算留给更关键的方向。

一句话总结:
AdaLoRA 本质上是在固定参数预算下做“动态资源调度”:不是增加参数,而是先判断重要性,再把 rank 分到最值得的地方。

1.3 具体区别展示

1.3.1 LoRA 和 AdaLoRA 的核心区别

  • LoRAΔW = BA,rankr通常提前固定。
  • AdaLoRAΔW = PΛQ,把低秩更新拆成“方向 + 重要程度 + 方向”。
  • 其中Λ的对角元素可以理解为各个低秩方向的重要性“开关”。

1.3.2 为什么要用PΛQ

  • P、Q负责学习低秩更新的方向,并通过正交约束让这些方向尽量独立。
  • Λ = diag(λ₁, λ₂, …, λᵣ)控制每个 rank-1 方向的贡献。
  • 如果某个λᵢ被裁剪为 0,对应方向就基本不再参与更新。

1.3.3 AdaLoRA 怎么实现动态 rank?

  • P、Q正常做梯度更新。
  • Λ除了更新外,还会结合重要性评分 + 总预算进行裁剪。
  • 于是不同矩阵最终可以拥有不同的有效 rank,把更多预算留给重要模块。

一句话总结:
LoRA 是“固定 rank 学 BA”,AdaLoRA 是“用 PΛQ 把低秩方向拆开,再动态决定哪些方向留下”。

1.4 训练流程

1.4.1 Instruction Data 怎么训练

  • 一条样本由Instruction + Response拼接成 token 序列。
  • Decoder 采用自回归方式预测下一个答案 token:
    I + O_<t → Ō_t
  • 训练时使用Teacher Forcing,即输入真实的历史答案 token。

1.4.2 Loss 怎么来的

  • 模型对每个O_t输出整个词表的概率分布。
  • 再与真实 token 计算Cross-Entropy Loss
    Ō_t ↔ O_t → CE Loss
  • 指令微调中通常主要对Response 部分计算 Loss

1.4.3 AdaLoRA 真正作用在哪里

  • AdaLoRA不改变 CE Loss 和 Decoder 的生成方式
  • CE Loss 反向传播得到P、Λ、Q的梯度。
  • 再通过重要性评估 + 预算约束 + Λ 裁剪,动态调整各模块的有效 rank。

一句话总结:
这一页主要讲“梯度从哪里来”:Instruction → Decoder → CE Loss → Gradient;AdaLoRA 的创新发生在拿到梯度之后的动态 Rank 分配

1.5 原理分析(一)

1.5.1 LoRA → AdaLoRA 的结构变化

  • LoRAΔW = BA,rankr一般提前固定。
  • AdaLoRAΔW = PΛQ,把低秩更新拆成“方向 + 重要程度 + 方向”。

1.5.2 为什么要加Λ

  • Λ = diag(λ₁, …, λᵣ)控制每个 rank-1 方向的贡献。
  • P、Q通过正交约束尽量保持不同方向独立。
  • 某个λᵢ = 0,就相当于关闭对应的低秩方向。

1.5.3 AdaLoRA 怎么实现动态 Rank

  • P、Q正常梯度更新。
  • Λ还会结合重要性评分 + Budget做裁剪。
  • 最终不同权重矩阵可以获得不同的有效 rank,把更多参数留给重要模块。

一句话总结:
LoRA 是“固定 rank 学 BA”,AdaLoRA 是“用 PΛQ 把 rank 方向拆开,再按重要性决定哪些方向留下”。

1.6 原理分析(二)

1.6.1 上半部分:Loss 从哪里来

  • Instruction + Response送入 Decoder。
  • 模型做自回归预测,并与真实O_t计算Cross-Entropy Loss
  • 这个 Loss 反向传播后,才会得到 AdaLoRA 需要的梯度。

1.6.2 下半部分:为什么要引入 SVD

  • SVD 把矩阵写成:A = UΣVᵀ
  • 每个σ_i u_i v_iᵀ都可以看成一个rank-1 方向
  • σ_i越大,通常说明这个方向越重要,因此可以通过保留大奇异值、舍弃小奇异值来做低秩近似。

1.6.3 SVD 怎么启发 AdaLoRA

  • SVD:A = UΣVᵀ
  • AdaLoRA:ΔW = PΛQ
  • 可以对应理解为:U ↔ PΣ ↔ ΛVᵀ ↔ Q。AdaLoRA 再结合重要性评分,把不重要方向的λ_i置零,从而动态调整有效 Rank。

一句话总结:
这页真正是在解释:SVD 先告诉我们“不同 rank 方向的重要性不同”,AdaLoRA 再把这个思想变成PΛQ,让每个低秩方向都能被单独评估、保留或裁掉。

1.7 Adalora详细解析

1.7.1 先算每个 Rank 方向的重要性

  • k个矩阵写成:ΔW_k = P_kΛ_kQ_k
  • Λ_k中每个λ_{k,i}对应一个 Rank-1 方向。
  • AdaLoRA 会为每个方向计算重要性分数S_{k,i}

1.7.2 所有 Rank 做“全局竞争”

  • 不是每个矩阵各自保留固定数量。
  • 而是把整个模型所有S_{k,i}放在一起排序
  • 当前预算为b^(t)时,只保留Global Top-b^(t)

1.7.3 不重要的方向直接关闭

  • 进入 Top-b^(t):对应λ_{k,i}保留。
  • 没进入:λ_{k,i} → 0,该 Rank 方向失效。
  • 因此不同矩阵最终会得到不同的有效 Rank。

一句话总结:
AdaLoRA 的动态 Rank 分配就是:先算重要性 → 全局排序 → 按预算保留 Top-b → 其余 λ 置零,让所有层共同竞争有限的 Rank Budget。

1.8 Adalora的重要性评分计算

1.8.1 先给“单个参数”打分

  • AdaLoRA 先计算参数敏感度:I(w)=|w·∇_wL|
  • 再用 EMA 得到平滑敏感度Ī(w),同时计算波动程度Ū(w)
  • 最终得到单参数重要性:s(w)=Ī(w)·Ū(w)

1.8.2 再把参数分数聚合成 Rank 分数

  • 一个 Rank 方向由三部分组成:P的第 i 列 +λ_{k,i}+Q的第 i 行
  • 所以 AdaLoRA 不只看|λ|,而是把这三部分的重要性一起综合。
  • 得到:S_{k,i}=s(λ)+Avg[s(P列)]+Avg[s(Q行)]

1.8.3 最后拿去做 Rank 剪枝

  • S_{k,i}越大,说明这个 Rank 方向越重要。
  • 后续把所有S_{k,i}做全局排序。
  • 进入Top-b^(t)的方向保留,其余对应λ_{k,i}→0

一句话总结:
AdaLoRA 的 Importance Score 就是:先给参数打分,再把参数的重要性聚合成整个 Rank 方向的分数,最后用于全局 Budget 排序与剪枝。

二、Qlora学习

2.1 引出问题

2.1.1 为什么 LoRA 之后还需要 QLoRA?

  • LoRA已经大幅减少了“需要训练的参数”。
  • 但冻结的Base Model 仍然要加载进显存
  • 模型越大,光保存基础权重就已经非常昂贵。

2.2.2 QLoRA 的核心思路

  • LoRA:高精度 Base Model + 可训练 LoRA
  • QLoRA:4-bit 量化 Base Model + 可训练 LoRA
  • 也就是:Base Model 不训练,就进一步把它压缩存储。

2.2.3 它主要解决什么?

  • Quantization:降低基础模型的显存占用。
  • LoRA:减少真正需要更新的参数量。
  • 两者结合后,让大模型微调更容易在有限 GPU 显存下完成。

一句话总结:
LoRA 解决“训练参数太多”,QLoRA 进一步解决“冻结的大模型本身还是太占显存”,核心就是4-bit Quantization + LoRA

2.2 QLoRA 的直接价值:显存大幅下降

2.2.1 传统微调为什么贵

  • 全参数微调不仅要存模型权重,还要保存梯度、优化器状态和激活值
  • 模型越大,显存需求增长非常快。
  • 课件示例中,LLaMA2-70B 的传统微调显存达到840 GB

2.2.2 QLoRA 怎么把显存降下来

  • Base Model:4-bit 量化 + 冻结
  • LoRA Adapter:保持可训练
  • 这样既减少基础模型的存储,又避免为全部参数保存完整训练状态。

2.2.3 效果有多明显

  • T5-11B:132 GB → 6 GB
  • Mistral-7B:84 GB → 5 GB
  • LLaMA2-70B:840 GB → 46 GB

一句话总结:
LoRA 是“少训练参数”,QLoRA 更进一步是“冻结的大模型也少占显存”,最终实现4-bit Quantization + LoRA → 更低显存的大模型微调

2.3 QLoRA 显存优化:从 16-bit Base Model 到 4-bit

2.3.1 QLoRA 真正压缩的是 Base Model

  • 普通 LoRA 仍然保存16-bit Frozen Base Model
  • QLoRA 把它进一步量化成4-bit,而 LoRA Adapter 继续保持可训练。
  • 所以核心变化就是:16-bit → 4-bit,Base Model 的存储开销大幅下降。

2.3.2 为什么显存能继续下降?

  • LoRA 已经减少了梯度和优化器状态的开销。
  • QLoRA 再把最大的显存来源——冻结的基础模型权重压缩。
  • 课件示例中,70B 模型从 LoRA 的约154 GB降到 QLoRA 的约46 GB

2.3.3 还有一个关键技术:Paged Optimizer

  • QLoRA 还通过CPU ↔ GPU 分页调度缓解训练时的显存峰值。
  • 它主要解决Memory Spike / OOM,而不是负责 16-bit → 4-bit 的主体压缩。
  • 因此可以记成:4-bit Quantization + LoRA + Paged Optimizer

一句话总结:
QLoRA 就是在 LoRA 的基础上,把冻结的 Base Model 从16-bit 压到 4-bit,再配合分页优化器进一步降低显存门槛。

2.4 Full Fine-tuning 的显存成本:70B 为什么约 840 GB?

2.4.1 每个参数不只要存“权重”

按课件的简化估算,全参数微调需要同时保存:

  • Weight:16 bit
  • Gradient:16 bit
  • Adam Optimizer States:64 bit

所以每个参数大约需要:

16 + 16 + 64 = 96 bit = 12 Byte

2.4.2 70B 模型为什么变成 840 GB?

直接计算:

70B × 12 Byte ≈ 840 GB

其中大约可以拆成:

  • 权重:140 GB
  • 梯度:140 GB
  • 优化器状态:560 GB

这还没算 Activation、临时缓存等额外开销。

2.4.3 这就是 LoRA / QLoRA 出现的原因

  • Full FT:整个模型都训练,显存最高。
  • LoRA:冻结 Base Model,只训练少量 Adapter。
  • QLoRA:进一步把冻结的 Base Model 量化到 4-bit。

一句话总结:
Full Fine-tuning 真正贵的地方,不只是模型权重大,而是每个可训练参数还要额外配套梯度和优化器状态,所以 70B 模型的训练状态可以迅速膨胀到数百 GB。

2.5 Quantization 基础:Float32 怎么映射成 INT8?

2.5.1 核心思路:先缩放,再取整

  • 原始 Float32 是连续小数,INT8 只能表示有限整数。
  • 所以先找最大绝对值a_max = max|a|,把数据缩放到[-1,1]
  • 再映射到[-127,127],最后Round成整数。

2.5.2 两个最关键的公式

  • Scale:s = max|a| / 127
  • Quantization:q = round(a / s)
  • 需要恢复时,再做:â = s · q

例如:
(-2.7,-3.8,5.7,6.1,6.8) → (-50,-71,106,114,127)

2.5.3 量化真正的问题:会产生误差

  • Round 会丢掉一部分小数信息,所以只能近似恢复原值。
  • AbsMax 量化还容易受到Outlier影响,一个极端值可能让大量普通权重挤在 0 附近。
  • 这正好引出后面的NF4:当只有 4-bit、16 个表示位置时,怎样安排这些位置才能让误差更小?

一句话总结:
量化就是把连续浮点数通过Scale → 映射 → Round变成低比特整数,用更少存储换取可接受的近似误差。

2.6 Quantization 的 Outlier 问题:为什么要做 Block-wise Quantization

2.6.1 Global Quantization 的问题

  • 全局量化时,整个 Tensor 共用一个absmax和 Scale。
  • 如果出现很大的Outlier,例如50,其他正常值会被压到 0 附近。
  • 在 4-bit 这类低比特量化中,很多正常权重甚至可能被映射成相同的离散值,导致明显信息损失。

2.6.2 Block-wise Quantization 怎么解决

  • 把大权重 Tensor 切成多个小 Block。
  • 每个 Block 单独计算自己的absmax和量化常数C_i
  • 这样 Outlier只影响它所在的 Block,不会把整个模型的量化范围都拉大。

2.6.3 为什么又会引出 Double Quantization?

  • Block 越多,就需要保存越多的C_1、C_2、C_3...
  • 这些 Scale / Quantization Constants 本身也会占显存。
  • 所以 QLoRA 再进一步:把这些C_i也量化,这就是 Double Quantization。

一句话总结:
Outlier 会把全局量化范围拉大 → Block-wise 用局部 Scale 把影响限制在小范围 → 但会产生大量 Scale → Double Quantization 再继续压缩这些 Scale。

2.7 Quantile:为什么“等概率分箱”更适合低比特量化?

2.7.1 Quantile 不是“等距离”,而是“等数量”

  • 先把数据从小到大排序。
  • 再按照概率划分区间,例如 800 个数据分成 8 组,每组约100 个
  • 所以每组的数据数量接近相同,但数值区间宽度可以不同。

2.7.2 数据越密集,量化就越精细

  • 数据集中区域:区间会更窄,量化点更密。
  • 数据稀疏区域:区间会更宽,量化点更稀。
  • 相比等距离分箱,可以把有限的 bit更多用在真正数据多的地方

2.7.3 这就是 NF4 的重要铺垫

  • 4-bit 只有16 个离散表示位置
  • NF4 利用近似正态分布的 Quantile 思想来设计这些量化位置。
  • 核心目的就是:让常见权重区域获得更高表示精度,减少量化误差。

一句话总结:
Uniform Quantization 是“按距离平均分”,Quantile 是“按概率平均分”;对于分布不均匀的模型权重,后者通常能更有效利用有限的量化位置。

2.8 Normal Distribution + Quantile:NF4 为什么要按概率分配量化区间?

2.8.1 神经网络权重通常集中在 0 附近

  • 可以近似理解为Normal Distribution
  • 中间权重多,两侧大权重少。
  • 所以如果仍然“等距离切区间”,有限的量化位置会被浪费。

2.8.2 Quantile 改成“等概率划分”

  • 利用 CDF:F(x)=P(X≤x)
  • 再通过q_p=F⁻¹(p)找到不同分位点。
  • 结果就是:中心数据密集 → 区间更窄;两侧数据稀疏 → 区间更宽。

2.8.3 这正是 NF4 的核心铺垫

  • 4-bit 只有16 个表示位置
  • NF4 根据权重的概率分布设计非均匀量化位置,而不是简单平均铺开。
  • 目的就是把更多量化精度留给最常出现的权重区域

一句话总结:
Normal Distribution 决定“数据主要在哪”,Quantile 决定“量化点该怎么放”,两者结合就是 NF4 非均匀 4-bit 量化的重要直觉。

2.9 NF4:4-bit 的 16 个量化值到底怎么设计?

2.9.1 NF4 不是等距离量化

  • 4-bit 只有16 个离散表示值
  • NF4 根据模型权重近似Normal Distribution的特点,用Quantile来安排这些量化位置。
  • 因此:0 附近更密,两侧更疏,比普通 INT4 更适合权重分布。

2.9.2 为什么必须保留 Exact Zero?

  • 神经网络中0很重要,最好能够被精确表示
  • 所以 NF4 会专门给0留一个编码位置。
  • 最终 16 个值呈轻微不对称,可直观理解为:7 个负值 + 0 + 8 个正值

2.9.3 实际怎么量化?

  • 每个 Block 先通过absmax归一化到[-1,1]
  • 再把每个权重映射到最近的 NF4 codebook 值
  • 最终真正保存的是对应的4-bit index,反量化时再乘回 Block 的 Scale。

一句话总结:
NF4 的核心不是“只有 4 bit”,而是这 16 个值按照正态分布的概率结构来设计,并保留精确的 0,从而用有限的 4-bit 表示尽可能减少量化误差。

三、思维导图总结

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询