【大模型微调】PET,Prompt Tuning,P Tuning,Lora,Qlora 微调的简介

概览

到2025年,虽然PET(Pattern-Exploiting Training)和Prompt Tuning在学术界仍有探讨,但在工业和生产环境中它们已基本被LoRA/QLoRA等参数高效微调(PEFT)方法取代 。LoRA因其实现简单、推理零开销,并能在大规模模型上以极少量参数达到与全量微调相当的效果,已成为最受欢迎的PEFT技术 。QLoRA在此基础上再结合4-bit量化,使得即便是65B级模型也能在单块48 GB GPU上完成微调,内存占用降低近3倍,性能几乎无损 。


1 PET 与 Prompt Tuning ,P-Tuning 的现状

1.1 PET(Pattern-Exploiting Training)

PET于2021年在EACL提出,通过“Pattern + Verbalizer Pair”(PVP)将分类和推理任务转换为完形填空问题来利用预训练模型 。

然而,由于其需要手工设计模板、映射词表,且在真正生产环境中难以自动化部署,PET已很少在实际项目中使用,大多数团队已转向更为通用且自动化程度更高的PEFT方法 。所以懒得写PET了。直接看后面ptuning和lora,


1.2 Prompt Tuning

Prompt Tuning(又称Soft Prompt Tuning)在2021年提出,直接对输入端添加 L 个可训练嵌入向量,仅更新这部分参数来适配下游任务 。

尽管Prompt Tuning在少样本和学术基准上表现良好,但因其训练不稳定、对超大模型需要较长的收敛时间,故在商业产品中采用的越来越少,主要用于研究和小规模试验场景 。


说明:Prompt Tuning 直接将一段可训练的向量拼接到输入端,冻结主模型权重,仅优化这段“软提示”及下游头部参数。

# ——— 1. 准备模型 ——————————————————————————————
model = load_pretrained_model("bert-base-uncased")      # 加载预训练模型  [oai_citation:0‡ACL Anthology](https://aclanthology.org/2021.emnlp-main.243/?utm_source=chatgpt.com)
freeze_parameters(model)                                # 冻结所有模型参数

# 初始化可训练的“软提示”向量 (L × H)
L = 20                                                  # Prompt 长度
H = model.config.hidden_size
prompt = RandomTensor(shape=(L, H), requires_grad=True) 

# 新增一个线性分类头
classifier = Linear(H, num_labels)                      # num_labels 为类别数

optimizer = AdamW([prompt, *classifier.parameters()], lr=1e-3)

# ——— 2. 训练循环 ——————————————————————————————
for epoch in range(num_epochs):
    for input_ids, labels in dataloader:
        # 2.1 获取原始 token embeddings → [B, N, H]
        emb = model.embeddings(input_ids)              
        
        # 2.2 在序列前拼接软提示 → [B, L+N, H]
        pref = prompt.unsqueeze(0).expand(emb.size(0), -1, -1)
        inputs_embeds = concat(pref, emb, dim=1)        

        # 2.3 仅给 embeddings,绕过原始 token‐to‐id 过程
        outputs = model.encoder(inputs_embeds)         

        # 2.4 取第 L 个位置的输出作为 “CLS” 表示 → [B, H]
        cls_repr = outputs[:, L, :]                     

        # 2.5 分类 & 计算损失
        logits = classifier(cls_repr)
        loss   = CrossEntropy(logits, labels)

        # 2.6 反向只更新 prompt 和分类头
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

1.3 P Tuning 

说明:P-Tuning 除了学习可训练提示向量外,还通过一个小型网络(如 LSTM 或 MLP)对提示向量进一步编码,稳定并提升少样本学习效果。

# ——— 1. 准备模型 ——————————————————————————————
model = load_pretrained_model("bert-base-uncased")      # 加载预训练模型  [oai_citation:3‡arXiv](https://arxiv.org/abs/2103.10385?utm_source=chatgpt.com)
freeze_parameters(model)                                # 冻结所有模型参数

# 定义 L 个“伪 token”ID,对应潜在的提示 embedding
L          = 20
pseudo_ids = range(L)

# 从模型 embedding table 提取初始向量 → [L, H]
H          = model.config.hidden_size
init_emb   = model.embeddings(pseudo_ids)              

# 定义一个 Prompt Encoder(LSTM/MLP)将 init_emb 映射到最终 prompt_emb
prompt_encoder = LSTM(input_size=H, hidden_size=H)      

# 新增分类头
classifier = Linear(H, num_labels)

optimizer = AdamW([*prompt_encoder.parameters(), *classifier.parameters()], lr=1e-3)

# ——— 2. 训练循环 ——————————————————————————————
for epoch in range(num_epochs):
    for input_ids, labels in dataloader:
        B, N = input_ids.size()

        # 2.1 用 Prompt Encoder 编码初始伪 token 嵌入 → [1, L, H]
        prompt_emb, _ = prompt_encoder(init_emb.unsqueeze(0))
        prompt_emb    = prompt_emb.expand(B, -1, -1)    # → [B, L, H]

        # 2.2 获取原始 token embeddings → [B, N, H]
        emb = model.embeddings(input_ids)

        # 2.3 拼接 prompt_emb 与 emb → [B, L+N, H]
        inputs_embeds = concat(prompt_emb, emb, dim=1)

        # 2.4 前向并行计算全序列输出
        outputs = model.encoder(inputs_embeds)

        # 2.5 取第 L 个位置的向量作为分类表示 → [B, H]
        cls_repr = outputs[:, L, :]

        # 2.6 分类 & 计算损失
        logits = classifier(cls_repr)
        loss   = CrossEntropy(logits, labels)

        # 2.7 反向仅更新 Prompt Encoder 与分类头
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

2 LoRA/QLoRA 的主导地位

2.1 LoRA(Low-Rank Adaptation)

LoRA于2021年问世,通过冻结Transformer的主干权重,在每层线性映射旁支注入两段低秩矩阵 A 与 B,仅训练 A,B,可训练参数量减少约10,000倍,且推理阶段无额外延迟 。

实际项目中,LoRA因其“插拔式”适配、易于在各种框架中集成(如Hugging Face PEFT、ColossalAI等),几乎成为所有PEFT管道的默认选择 。

# 1. 初始化
model = GPTForCausalLM.from_pretrained("gpt2")      # 加载预训练 GPT-2
freeze_parameters(model)                            # 冻结所有原有参数

# 2. 注入 LoRA 适配器
r = 8                                               # 低秩矩阵秩 rank
alpha = 16                                          # 缩放因子
for layer in model.transformer.h:                   # 遍历 Transformer 每一层
    # 拦截自注意力和前馈层的 Linear
    for name in ["c_attn", "c_proj", "mlp.c_fc", "mlp.c_proj"]:
        W = getattr(layer, name)                    # 原线性层
        # 保存原权重,用于推理时合并
        W.requires_grad = False                      
        # 新增 A、B 两段可训练矩阵
        A = nn.Parameter(torch.randn(W.in_features, r) * 0.01)
        B = nn.Parameter(torch.zeros(r, W.out_features))
        layer.register_parameter(f"{name}_lora_A", A)
        layer.register_parameter(f"{name}_lora_B", B)

# 3. 前向时叠加低秩更新
def lora_forward(x, W, A, B):
    return x @ W.weight + (alpha / r) * (x @ A @ B)

# 4. 替换每个需要微调的 Linear 层前向
for layer in model.transformer.h:
    for name in ["c_attn", "c_proj", "mlp.c_fc", "mlp.c_proj"]:
        orig_linear = getattr(layer, name)
        A = getattr(layer, f"{name}_lora_A")
        B = getattr(layer, f"{name}_lora_B")
        # 用闭包 Capture 原 Linear、A、B
        def new_forward(x, _orig=orig_linear, _A=A, _B=B):
            return lora_forward(x, _orig, _A, _B)
        orig_linear.forward = new_forward

# 5. 训练循环:仅更新 A、B 矩阵
optimizer = AdamW(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-4)
model.train()
for batch in dataloader:
    outputs = model(**batch)     # 包括 input_ids, attention_mask, labels
    loss = outputs.loss
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()
LoRA 冻结预训练模型权重,在每个线性层旁路注入低秩矩阵,只训练这部分额外参数。LoRA 可在保持原模型推理效率的同时,将可训练参数减少 10,000 倍,且不增加推理延迟

2.2 QLoRA(Quantized LoRA)

QLoRA在LoRA之上先将预训练模型量化至4-bit(NF4),再冻结量化权重并仅训练LoRA分支,显存占用降低近3倍,却保持与16-bit LoRA几乎相同的性能,被用于在单块48 GB GPU上微调65B参数模型(如Guanaco)至近ChatGPT水平 。

# 1. 初始化与 4-bit 量化
model = GPTForCausalLM.from_pretrained("gpt2")
freeze_parameters(model)  
# bitsandbytes 提供的 4-bit 量化函数
for name, param in model.named_parameters():
    param.data = quantize_4bit(param.data, dtype="nf4")  # NF4 量化

# 2. 注入 LoRA(与上述 LoRA 步骤一致)
r = 8; alpha = 16
for layer in model.transformer.h:
    for name in ["c_attn", "c_proj", "mlp.c_fc", "mlp.c_proj"]:
        W = getattr(layer, name)
        W.requires_grad = False
        A = nn.Parameter(torch.randn(W.in_features, r) * 0.01)
        B = nn.Parameter(torch.zeros(r, W.out_features))
        layer.register_parameter(f"{name}_lora_A", A)
        layer.register_parameter(f"{name}_lora_B", B)

# 3. 替换前向(同 LoRA)
# …(如上)

# 4. 训练循环:仅更新 A、B
optimizer = AdamW(filter(lambda p: p.requires_grad, model.parameters()), lr=5e-5)
model.train()
for batch in dataloader:
    outputs = model(**batch)   
    loss = outputs.loss         
    loss.backward()            
    optimizer.step()           
    optimizer.zero_grad()

QLoRA 首先将模型权重量化到 4-bit,然后在量化模型上应用 LoRA 适配器,仅训练低秩矩阵,极大节省显存并保持性能

QLoRA 能在单卡 48 GB GPU 上微调百亿级模型,且性能与 16-bit LoRA 相当

 LoRA 与 QLoRA 在自回归 GPT 模型上的核心实现思路,二者的唯一区别在于 步骤 1:是否对模型权重做 4-bit 量化


小结

  • PET与Prompt Tuning:学术价值依旧,但因可用性、自动化程度及训练效率原因,已在工业界被LoRA/QLoRA等PEFT所取代;

  • LoRA/QLoRA:凭借参数效率、推理零成本及与量化结合的超低资源需求,成为2025年主流的高效微调方案。

若您正在为生产环境选择PEFT技术,建议优先考虑LoRA及其量化变体QLoRA,并辅以Hugging Face PEFT、ColossalAI等工具链来快速集成与部署。

<think>嗯,用户让我介绍一下LoRa大模型微调。首先,我需要回忆一下LoRa的基本概念和相关知识。LoRa全称是Low-Rank Adaptation,是一种用于微调大语言模型的技术。记得它主要是通过低秩矩阵分解来减少训练参数的数量,这样可以在保持效果的同时降低计算资源的需求。 接下来,我得考虑用户的背景。他们可能是机器学习从业者或者研究者,尤其是那些在自然语言处理领域工作的人。用户可能已经了解过传统的微调方法,比如全参数微调,但遇到资源消耗大的问题,所以想寻找更高效的替代方案。也有可能用户是刚开始接触大模型微调,想了解不同的技术选项。 用户的需求可能包括了解LoRa的原理、优势、应用场景以及如何实现。需要分步骤解释,确保结构清晰。可能需要比较LoRa和传统微调的区别,突出其优点,比如参数效率、资源节省等。另外,用户可能想知道实际应用中的例子,比如在哪些任务中使用LoRa效果比较好,或者有没有现成的库可以使用。 还要注意用户可能存在的疑问,比如LoRa是否会影响模型性能,或者它的局限性在哪里。比如,虽然LoRa减少了参数,但在某些复杂任务上可能不如全参数微调有效,这时候需要权衡。此外,可能需要提到相关的技术,如Adapter TuningPrompt Tuning,帮助用户理解不同方法的差异。 在组织回答时,应该先概述LoRa是什么,然后详细说明其工作原理,接着讨论优缺点,再给出应用场景,最后提供实现建议或工具。确保每个部分都有足够的细节,但不过于技术化,保持易懂。同时,需要检查LaTeX格式是否正确,比如所有数学表达式用$...$包裹,独立公式用$$...$$,并且正确使用中文。 还要注意用户可能的深层需求,比如他们是否在寻找实际操作的指南,或者是否更关心理论背景。这时候需要平衡理论与实践的信息量。例如,在实现部分提到Hugging Face的PEFT库,这可以帮助用户快速上手,而理论部分解释低秩分解如何减少参数。 最后,确保回答真实可靠,引用正确的论文或权威来源,比如提到LoRa的提出者或相关研究,增加可信度。同时,语言要简洁明了,避免术语堆砌,让不同层次的读者都能理解。</think>好的,我将分步骤为您介绍LoRa大模型微调技术: 1. **基本概念** LoRa(Low-Rank Adaptation)是一种针对大语言模型的高效微调方法,由微软研究院在2021年提出。其核心思想是通过**低秩矩阵分解**,仅训练少量参数即可适配下游任务,典型应用场景如:$W_{adapted} = W_{original} + \Delta W$,其中$\Delta W$被分解为两个低秩矩阵$B \cdot A$。 2. **工作原理** - 在原模型权重矩阵$W \in \mathbb{R}^{d \times k}$旁添加适配层 - 将参数增量矩阵分解为: $$\Delta W = B \cdot A \quad (B \in \mathbb{R}^{d \times r}, A \in \mathbb{R}^{r \times k})$$ 其中$r \ll \min(d,k)$为秩(rank),通常取4-64 - 仅需训练$B$和$A$,冻结原始模型参数 3. **关键优势** | 方法 | 训练参数量 | GPU显存 | 存储开销 | |---|---|----|----| | 全参数微调 | 100% | 高 | 每个任务保存完整模型 | | LoRa | 0.1%-1% | 降低60%+ | 仅保存适配器参数 | 4. **典型应用场景** - 领域适配(医疗/法律文本生成) - 多任务学习(同时适配多个任务) - 资源受限环境(单卡微调百亿参数模型) 5. **实现步骤** ```python # 使用Hugging Face PEFT库示例 from peft import LoraConfig, get_peft_model lora_config = LoraConfig( r=8, # 秩 lora_alpha=32, # 缩放系数 target_modules=["q_proj", "v_proj"], # 作用于Attention层 lora_dropout=0.1 ) model = get_peft_model(base_model, lora_config) ``` 6. **局限性** - 需要经验选择目标模块和秩大小 - 在极复杂任务上可能弱于全参数微调 - 适配器参数需要与基础模型配合使用 建议实际使用时结合QLoRa(量化+LoRa)进一步优化资源消耗,当前主流方案已支持在单张24G显卡上微调65B参数模型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值