Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 人工智能 / Artificial Intelligence

AI 基础设施 / AI Infrastructure

集群基础设施 / Cluster Infrastructure

1. GPU 集群基础设施全景——训练框架之下、硬件之上的那一层 / GPU Cluster Infrastructure Between Training Frameworks and Hardware

2. GPU 集群硬件架构——从 NVLink 到 InfiniBand / GPU Cluster Hardware from NVLink to InfiniBand

3. 异构硬件生态——CPU/DPU/NPU 的集群角色 / Roles of CPUs, DPUs, and NPUs in Heterogeneous Clusters

4. GPU 虚拟化与资源隔离——一张卡多人用 / GPU Virtualization and Resource Isolation

5. 作业调度系统——Kubernetes 和 Slurm / Job Scheduling with Kubernetes and Slurm

6. 多作业与多租户管理——让集群被所有人高效使用 / Multi-Job and Multi-Tenant Cluster Management

7. 网络架构与 RDMA——让 GPU 之间的通信更快 / Network Architecture and RDMA for Faster GPU Communication

8. NCCL 集群组网——大规模集合通信调优 / NCCL Cluster Networking and Collective Communication Tuning

9. 分布式存储——让数据跑得比 GPU 快 / Distributed Storage That Keeps GPUs Fed with Data

10. 集群运营与故障处理——让万卡集群稳定运行 / Operations and Failure Recovery for Large GPU Clusters

训练系统 / Training Systems

1. AI Infra 训练侧全景——让千亿参数模型跑起来需要什么 / Training-Side AI Infrastructure for Hundred-Billion-Parameter Models

2. GPU 硬件基础——为什么 GPU 比 CPU 快,显存为什么总是不够 / GPU Hardware, Parallel Throughput, and Memory Capacity

3. 分布式训练——如何把大模型分到多张卡上 / Distributing Large-Model Training Across Multiple GPUs

4. 显存优化——让 70B 模型在有限显存中跑起来 / Memory Optimization for Running 70B Models

5. 混合精度与通信——BF16 为什么是 LLM 训练的主流选择 / Mixed Precision and Communication with BF16

6. 预训练——Scaling Laws、数据工程与训练稳定性 / Pretraining with Scaling Laws, Data Engineering, and Stability

7. 后训练 SFT——从预训练模型到助手模型 / Supervised Fine-Tuning from Pretrained Model to Assistant

8. 后训练 RLHF/DPO——从助手模型到对齐模型 / RLHF and DPO from Assistant Model to Aligned Model

9. 高效微调——LoRA 和 QLoRA 让大模型走进消费级 GPU / Efficient Fine-Tuning with LoRA and QLoRA on Consumer GPUs

10. 训练工程——千卡集群的管理与故障恢复 / Training Engineering for Thousand-GPU Cluster Operations and Recovery

本页目录

高效微调——LoRA 和 QLoRA 让大模型走进消费级 GPU / Efficient Fine-Tuning with LoRA and QLoRA on Consumer GPUs ​

📅 创建时间:2026-06-02 🏷️ 标签:#LoRA #QLoRA #Adapter #高效微调 #低秩分解 #NF4 #PEFT 📚 前置知识:[[06-posttraining-sft]](SFT 监督微调) [[03-memory-optimization]](显存优化) 📚 相关知识:[[07-posttraining-rlhf]](RLHF/DPO)


场景:想微调 Llama-3 但只有一张消费级 4090 ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  你有一张 RTX 4090(24GB 显存)。                      │
│  你想微调 Llama-3-8B。                                 │
│                                                             │
│  问题来了:                                              │
│                                                             │
│  Llama-3-8B 完整微调需要的资源:                    │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  模型参数:8B × 2 bytes(BF16)= 16 GB         │  │
│  │  梯度:8B × 2 bytes = 16 GB                      │  │
│  │  优化器状态:8B × 4 bytes(FP32)= 32 GB        │  │
│  │  Activation:约 10-20 GB                          │  │
│  │                                                     │  │
│  │  总计:约 80 GB                                   │  │
│  │  你的卡:24 GB → 装不下!                        │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  但如果用 LoRA:                                         │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  冻结原模型参数:只保存,不更新 → 0 GB             │  │
│  │  训练 LoRA 参数:8B × r × 2 × 2 / 1024 ≈ 1 GB |  │
│  │  (r=8,假设 rank=8 的低秩矩阵)                 │  │
│  │  梯度:LoRA 参数的梯度 → ~1 GB                   │  │
│  │  Activation:原模型 + LoRA → ~10 GB             │  │
│  │                                                     │  │
│  │  总计:约 12 GB                                   │  │
│  │  你的卡:24 GB → 轻松跑起来!                    │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  LoRA 就是让大模型走进消费级 GPU 的关键技术。            │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

第1节:全参数微调的局限性 ​

为什么全参数微调不现实 ​

┌─────────────────────────────────────────────────────────────┐
│                 全参数微调的问题                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题 1:显存不够(最直接的问题)                          │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  训练 70B 模型:需要 660GB+ 显存               │  │
│  │  → 只有大厂能玩得起                               │  │
│  │  → 普通研究者无法参与                            │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  问题 2:计算成本高                                      │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  全参数微调的计算量 ≈ 全量预训练的 1/1000       │  │
│  │  但仍然是亿级参数模型的中等规模训练               │  │
│  │  → 需要数百张 GPU,成本数十万美元               │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  问题 3:灾难性遗忘                                      │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  全参数微调会更新所有参数                         │  │
│  │  → 模型可能丢失预训练学到的通用能力               │  │
│  │  → 变得只擅长微调任务,其他任务退化              │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  问题 4:无法多任务并存                                  │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  全参数微调后,模型参数被覆盖                     │  │
│  │  → 无法同时保留多个领域的能力                     │  │
│  │  → 每次换任务都要重新训练                         │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

PEFT 的基本思路 ​

┌─────────────────────────────────────────────────────────────┐
│                 PEFT(Parameter-Efficient Fine-Tuning)基本思路        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  核心洞察:                                                │
│  → 微调大模型时,不需要更新所有参数                      │
│  → 只需要调整"少量关键参数"就能改变模型行为              │
│                                                             │
│  PEFT 的几种主流方法:                                    │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  方法               │  可训练参数 │  显存节省 │  效果 │  │
│  │  ──────────────────┼────────────┼───────────┼───────│  │
│  │  LoRA              │  0.1-1%   │  极高    │  好   │  │
│  │  QLoRA             │  0.1-1%   │  极高    │  相当  │  │
│  │  Adapter           │  1-5%     │  高     │  好   │  │
│  │  Prefix Tuning     │  0.1-1%   │  高     │  中   │  │
│  │  Prompt Tuning     │  <0.1%    │  极高    │  中下  │  │
│  │  全参数微调         │  100%     │  无     │  最好  │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  本章重点:LoRA 和 QLoRA(工业界最流行)                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第2节:LoRA——低秩适配的原理 ​

LoRA 的数学原理 ​

┌─────────────────────────────────────────────────────────────┐
│                 LoRA:低秩矩阵分解                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  背景:对于预训练好的权重矩阵 W₀ ∈ R^(d×k),               │
│        全参数微调时更新 W = W₀ + ΔW                        │
│                                                             │
│  LoRA 的假设:                                             │
│  → ΔW 是低秩的(low-rank)                                │
│  → 也就是说,ΔW = B·A,其中 B ∈ R^(d×r),A ∈ R^(r×k)   │
│  → r << min(d, k),通常 r ∈ {2, 4, 8, 16, 32, 64}       │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │                                                     │  │
│  │  全参数微调:                                       │  │
│  │  h = W₀ · x                                        │  │
│  │  ΔW 需要更新 d×k 个参数                           │  │
│  │                                                     │  │
│  │  LoRA:                                            │  │
│  │  h = W₀ · x + B·A·x                              │  │
│  │  → 冻结 W₀,只更新 B 和 A                         │  │
│  │  → 只训练 d×r + r×k 个参数(而非 d×k)            │  │
│  │                                                     │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  参数节省计算:                                            │
│  例:d=4096, k=4096, r=8                                 │
│  → 全参数:4096 × 4096 = 16M 参数                       │
│  → LoRA:(4096×8) + (8×4096) = 65K 参数               │
│  → 压缩比:16M / 65K ≈ 250x                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

LoRA 实际应用在 Transformer 的哪些层 ​

┌─────────────────────────────────────────────────────────────┐
│                 LoRA 应用位置:注意力机制的权重                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Transformer Layer 中的可训练参数:                           │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │                                                     │  │
│  │  ┌───────────────────────────────────────────────┐│  │
│  │  │  Self-Attention:                             ││  │
│  │  │                                             ││  │
│  │  │  Q_proj: W_q → LoRA(W_q)    ← 常用      ││  │
│  │  │  K_proj: W_k → LoRA(W_k)    ← 常用      ││  │
│  │  │  V_proj: W_v → LoRA(W_v)    ← 常用      ││  │
│  │  │  O_proj: W_o → LoRA(W_o)    ← 可选      ││  │
│  │  │                                             ││  │
│  │  │  QKV 投影效果最明显(Ayer et al. 2023)    ││  │
│  │  └───────────────────────────────────────────────┘│  │
│  │                                                     │  │
│  │  ┌───────────────────────────────────────────────┐│  │
│  │  │  MLP Layer:                                  ││  │
│  │  │                                             ││  │
│  │  │  gate_proj: W_gate → LoRA(W_gate)  ← 可选  ││  │
│  │  │  up_proj:   W_up   → LoRA(W_up)    ← 可选  ││  │
│  │  │  down_proj: W_down → LoRA(W_down)  ← 可选  ││  │
│  │  │                                             ││  │
│  │  │  MLP 通常不需要 LoRA,效果提升有限           ││  │
│  │  └───────────────────────────────────────────────┘│  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  推荐配置:                                                │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  任务类型           │  推荐应用层      │  推荐 rank │  │
│  │  ────────────────────┼─────────────────┼─────────────│  │
│  │  通用对话           │  QKV + O        │  8-16     │  │
│  │  领域适应(医疗/法律)│  QKV          │  16-32    │  │
│  │  代码微调           │  QKV + O        │  32-64    │  │
│  │  指令遵循           │  QKV            │  8-16     │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

LoRA 的 PyTorch 实现 ​

python
import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Optional

class LoRALinear(nn.Module):
    """
    LoRA 适配的 Linear 层
    """
    def __init__(
        self,
        original_layer: nn.Linear,
        rank: int = 8,
        lora_alpha: float = 16,
        dropout: float = 0.0,
    ):
        super().__init__()
        d_out, d_in = original_layer.weight.shape
        self.rank = rank
        self.lora_alpha = lora_alpha
        self.scaling = lora_alpha / rank  # 缩放因子

        # 冻结原始权重
        self.weight = original_layer.weight
        self.weight.requires_grad = False

        # 如果原始层有 bias,也冻结
        if original_layer.bias is not None:
            self.bias = original_layer.bias
            self.bias.requires_grad = False
        else:
            self.bias = None

        # LoRA 的 A 和 B 矩阵
        # A: (r, d_in),用零初始化(训练初期和为零)
        self.lora_A = nn.Parameter(torch.zeros(rank, d_in))
        # B: (d_out, r),用随机初始化
        self.lora_B = nn.Parameter(torch.randn(d_out, rank) * 0.01)

        # 可选的 Dropout
        self.lora_dropout = nn.Dropout(p=dropout)

        # 初始化 A 为零(确保 ΔW 初期为零)
        nn.init.kaiming_uniform_(self.lora_A, a=5**0.5)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # 原始层的输出
        original_output = F.linear(x, self.weight, self.bias)

        # LoRA 的增量
        # h = Wx + (scaling) * (BA)x
        lora_output = self.lora_dropout(x) @ self.lora_A.T @ self.lora_B.T
        lora_output = lora_output * self.scaling

        return original_output + lora_output


# 使用 HuggingFace PEFT 库(更简洁)
from peft import LoraConfig, get_peft_model, TaskType

lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,    # 任务类型
    r=8,                              # rank,越大越灵活但参数量越大
    lora_alpha=16,                    # 缩放因子,通常 = 2 * rank
    lora_dropout=0.05,                # dropout,防止过拟合
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],  # 应用到哪些层
    bias="none",                      # bias 是否可训练(none/lora_only/all)
)

model = get_peft_model(base_model, lora_config)
model.print_trainable_parameters()
# 输出:trainable params: 8,388,608 || all params: 6,738,415,616 || trainable%: 0.124%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

第3节:QLoRA——量化 + LoRA 的极致优化 ​

QLoRA 的核心思想 ​

┌─────────────────────────────────────────────────────────────┐
│                 QLoRA:量化 + LoRA 的结合                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  LoRA 的问题:                                             │
│  → LoRA 解决了训练显存问题(梯度从 16GB → 1GB)           │
│  → 但模型权重仍然需要 16GB(8B × 2 bytes BF16)          │
│  → 24GB 显存卡还是勉强                                     │
│                                                             │
│  QLoRA 的解决方案:                                        │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  1. 量化原始模型权重到 INT4 / NF4                  │  │
│  │     → 模型权重从 16GB → 4GB                        │  │
│  │                                                     │  │
│  │  2. 冻结量化权重,推理时反量化到 BF16              │  │
│  │                                                     │  │
│  │  3. LoRA 只训练低秩矩阵,精度保持 BF16             │  │
│  │     → LoRA 部分:约 1GB                            │  │
│  │                                                     │  │
│  │  总显存:4GB + 1GB + Activation ≈ 8GB            │  │
│  │  → 24GB 显存可以轻松跑 65B 模型!                 │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  QLoRA 论文(Tim Dettmers et al., 2023):                 │
│  → 在 65B 模型上,用 QLoRA 微调,效果和全精度 BF16 相当   │
│  → 开创了消费级 GPU 训练大模型的先河                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

NF4 量化——比普通 INT4 更好的量化格式 ​

┌─────────────────────────────────────────────────────────────┐
│                 NF4(4-bit NormalFloat):针对神经网络优化的量化           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题:普通 INT4 量化对神经网络效果不好                      │
│  → 神经网络权重分布不均匀(均值不为零)                     │
│  → 均匀量化的量化误差大                                    │
│                                                             │
│  NF4 的设计:                                              │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  NF4 是一种非均匀量化:                             │  │
│  │                                                     │  │
│  │  量化中心点分布:                                   │  │
│  │  → 4-bit = 16 个离散值                           │  │
│  │  → 这些值不是均匀分布的                            │  │
│  │  → 而是按照正态分布的 quantile(分位数)分布        │  │
│  │                                                     │  │
│  │  原因:神经网络权重近似正态分布                    │  │
│  │  → 更多的量化级别落在均值附近(权重密度高)         │  │
│  │  → 减少量化误差                                    │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  NF4 vs INT4 对比:                                        │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  在 LLaMA 7B 上的效果(Perplexity,越低越好):    │  │
│  │                                                     │  │
│  │  BF16(基线):16.22                              │  │
│  │  INT4:16.77(差 0.55)                          │  │
│  │  NF4:16.34(差 0.12)——明显优于 INT4           │  │
│  │                                                     │  │
│  │  结论:NF4 是目前最好的 4-bit 量化格式             │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

QLoRA 的实现 ​

python
# 使用 bitsandbytes 库实现 QLoRA
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

# QLoRA 配置
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,              # 4-bit 量化加载
    bnb_4bit_quant_type="nf4",     # 使用 NF4 量化
    bnb_4bit_compute_dtype=torch.bfloat16,  # 计算时用 BF16
    bnb_4bit_use_double_quant=True,  # 双重量化(进一步节省显存)
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3-8B",
    quantization_config=quantization_config,
    device_map="auto",
)

# 准备 QLoRA 训练
model = prepare_model_for_kbit_training(model)

# LoRA 配置
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM,
)

model = get_peft_model(model, lora_config)

# 显存估算(Llama-3-8B):
# 模型权重(NF4):~4 GB
# LoRA 参数(BF16):~0.5 GB
# Activation:~6 GB
# KV Cache:~2 GB
# 总计:~12-14 GB(可以在 24GB 显存的 4090 上跑)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

第4节:LoRA 的进阶话题 ​

LoRA 秩的选择 ​

┌─────────────────────────────────────────────────────────────┐
│                 LoRA rank 如何选择                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  rank 越大,LoRA 可表达的变换越多,但参数量也越大:         │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  rank | 参数节省比  |  拟合能力  |  推荐场景        │  │
│  │  ──────┼──────────────┼────────────┼─────────────────│  │
│  │    2   |   2000x     |  极低    |  简单任务       │  │
│  │    4   |   1000x     |  低      |  轻量微调       │  │
│  │    8   |    500x     |  中      |  通用微调       │  │
│  │   16   |    250x     |  中高    |  领域适应       │  │
│  │   32   |    125x     |  高      |  代码/数学       │  │
│  │   64   |     62x     |  极高    |  复杂任务       │  │
│  │   128  |     31x     |  极高    |  极限效果       │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  经验法则:                                                │
│  → r = 8:对大多数对话/指令微调足够                       │
│  → r = 16:对需要特定知识注入的场景                        │
│  → r = 32+:对代码生成、数学推理等复杂任务                 │
│                                                             │
│  注意:rank 不是越大越好                                   │
│  → 更大的 rank 可能导致过拟合                             │
│  → 需要更多数据支撑                                        │
│  → 训练时间更长                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

LoRA 的合并——训练完如何合并权重 ​

┌─────────────────────────────────────────────────────────────┐
│                 LoRA 权重合并:训练完成后的问题                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题:LoRA 训练完成后,模型有 W₀ + ΔW(ΔW = BA)         │
│        推理时需要两个部分,计算慢,部署复杂                   │
│                                                             │
│  解决:合并权重                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  合并后的权重:                                      │  │
│  │  W_merged = W₀ + (α/r) * BA                        │  │
│  │                                                     │  │
│  │  其中 α 是 LoRA 的 alpha 参数                       │  │
│  │  合并后:W_merged = W₀ + ΔW                        │  │
│  │  → 推理时只需要 W_merged,不需要额外的 BA 计算      │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  合并时机:                                                │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  1. 训练完成后合并(推荐):                        │  │
│  │     → 保存合并后的权重,推理更快                    │  │
│  │     → 但无法继续训练                                │  │
│  │                                                     │  │
│  │  2. 部署时动态合并:                                │  │
│  │     → 保留 LoRA adapter,推理时临时合并             │  │
│  │     → 支持动态切换不同的 LoRA adapter               │  │
│  │     → 比如:针对不同客户加载不同的领域 LoRA          │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  HuggingFace PEFT 合并:                                   │
```python
from peft import PeftModel

# 加载基础模型
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B")

# 加载 LoRA adapter
model = PeftModel.from_pretrained(base_model, "path/to/lora/adapter")

# 合并权重
merged_model = model.merge_and_unload()
# merged_model 现在包含 W₀ + ΔW,可以直接推理

# 保存合并后的模型
merged_model.save_pretrained("path/to/merged/model")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

│ │ └─────────────────────────────────────────────────────────────┘


### Adapter——LoRA 的替代方案
1
2

┌─────────────────────────────────────────────────────────────┐ │ Adapter:另一种 PEFT 方法 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Adapter 的结构: │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ x → LayerNorm → ┬─→ [Down] → [Up] → + → output │ │ │ │ │ │ │ │ │ └────────────────────────────────┘ │ │ │ │ ↑ │ │ │ │ 残差连接 │ │ │ │ │ │ │ │ Down: d → r(缩小维度) │ │ │ │ Up: r → d(恢复维度) │ │ │ │ r 通常是 d/4 到 d/16 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ LoRA vs Adapter 对比: │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ 维度 │ LoRA │ Adapter │ │ │ │ ├────────────────┼────────────────┼────────────────┤ │ │ │ │ 结构 │ 低秩矩阵 BA │ Down-Up MLP │ │ │ │ │ 位置 │ 并行于原层 │ 串行(残差) │ │ │ │ │ 推理延迟 │ 可合并(无额外)│ 无法消除 │ │ │ │ │ 表达能力 │ 中等 │ 较高 │ │ │ │ │ 工业界流行度 │ 最高 │ 次高 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ 选择建议: │ │ → 推理延迟敏感 → LoRA(可合并) │ │ → 需要更高表达能力 → Adapter │ │ → 多任务切换 → LoRA(动态加载 adapter) │ │ │ └─────────────────────────────────────────────────────────────┘


---

## 升华:LoRA 的工程哲学
1
2
3
4

┌─────────────────────────────────────────────────────────────┐ │ LoRA 的核心工程哲学 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 低秩假设是 LoRA 成功的关键 │ │ → 不是所有参数的更新都同等重要 │ │ → 预训练模型参数的"微调方向"是低秩的 │ │ → r=8 的 LoRA 就能捕获大部分任务相关的方向 │ │ │ │ 2. 冻结 + 增量是最优雅的设计 │ │ → 预训练知识被完整保留 │ │ → 只学习任务特定的方向 │ │ → 灾难性遗忘?不存在的 │ │ │ │ 3. QLoRA 打开了民主化的大门 │ │ → 以前需要 A100 才能微调 65B 模型 │ │ → 现在 RTX 4090 就可以 │ │ → 学术界和独立开发者终于能参与进来 │ │ │ │ 4. LoRA 是部署的艺术,不只是训练的艺术 │ │ → 可以动态切换不同的 LoRA adapter │ │ → 一个基础模型 + N 个领域 LoRA = N 个专家模型 │ │ → 大幅降低部署成本 │ │ │ │ 一句话总结: │ │ LoRA 用"少量参数撬动大模型"的设计哲学, │ │ 让大模型从大厂的专属品,变成了每个人都能微调的工具。 │ │ │ └─────────────────────────────────────────────────────────────┘


---

## "AI 可查 vs 必须理解"清单
1
2
3
4

AI 可查: ✅ bitsandbytes 库的具体使用细节 ✅ 不同量化格式(INT8/NF4/FP4)的详细对比 ✅ Adapter 和 Prefix Tuning 的具体实现代码

必须理解: 🔴 LoRA 的核心思想:冻结原始权重,只训练低秩矩阵 B 和 A 🔴 为什么 ΔW 是低秩的(预训练模型微调方向是低秩的假设) 🔴 LoRA 的参数节省计算:d×k → 2×r×(d+k) 🔴 QLoRA 的三层优化:NF4 量化 + 双重量化 + BF16 LoRA 🔴 为什么 NF4 比普通 INT4 更适合神经网络(基于正态分布的 quantile) 🔴 LoRA rank 的选择依据:r=8 通用,r=32+ 代码/数学 🔴 LoRA 合并权重的时机和原因


---

**学习状态**:🟡 开始学习
1
2
3
4

最后更新于:

Pager
上一篇8. 后训练 RLHF/DPO——从助手模型到对齐模型 / RLHF and DPO from Assistant Model to Aligned Model
下一篇10. 训练工程——千卡集群的管理与故障恢复 / Training Engineering for Thousand-GPU Cluster Operations and Recovery

持续记录,持续成长

Copyright © Tidenflow