大模型 SFT 中的关键技术总结学习
文章目录
- 微调策略
- LoRA 微调
- 核心思想
- 具体实现过程
- 超参数与技巧
- 实现步骤
- QLoRA 相关技术
- 1. 核心原理
- 2. 技术优势
- 3. 实现流程
- 4. 应用场景
- P-tuning
- 核心思想
- 关键技术点
- 训练流程
- 优点
- 应用场景
- P-tuning v2
- Prefix Tuning
- 一、关键概念
- 前缀(Prefix)
- 虚拟标记(Virtual Token)
- 二、核心原理
- 三、技术实现要点
- 训练过程
- 四、与传统微调对比优势
- 五. 实践建议
- Adapter Tuning
微调策略
- 全参数微调(Full Parameter Fine-Tuning): 更新模型的所有参数,适用于高质量、大规模任务数据。
- 部分参数微调(Parameter-Efficient Fine-Tuning, PEFT):
- LoRA(Low-Rank Adaptation): 通过低秩矩阵调整权重,减少计算开销。
- QLoRA:结合量化和低秩适配,进一步提升效率。
- 提示微调(P - Tuning) :通过在输入中添加可训练提示向量,引导模型学习特定任务模式,不改变模型主体参数,轻量级微调方式,能有效利用预训练模型知识,适应多种任务。
- P-Tuning v2:仅微调与提示(prompt)相关的参数。
- 冻结微调(Freeze Fine-Tuning) :冻结部分层(如底层),仅微调顶层或新增任务头。
LoRA 微调
LoRA(Low - Rank Adaptation,低秩适应)是一种用于高效微调大型神经网络的技术,尤其适用于直接微调整个网络参数成本高昂或不切实际的情况。以下是其原理的详细解释:
从矩阵角度理解秩
在矩阵理论中,矩阵的秩是指矩阵中线性独立的行或列的最大数目。对于一个权重矩阵,如果秩较低,意味着矩阵中的信息冗余度较低,其自由度也较低,可以用更紧凑的形式来表示。在大型神经网络中,模型的权重矩阵通常规模巨大且是满秩的,这意味着存储和计算成本都很高。
核心思想
LoRA 的核心思想是在冻结预训练模型权重的基础上,对模型的权重矩阵引入低秩结构,通过添加可学习的低秩矩阵来实现对模型行为的调整。在下游任务微调时,不改变预训练模型的原始权重,而是通过训练低秩矩阵,让模型学习特定任务的知识 。
具体实现过程
假设预训练模型中的某个权重矩阵为 W 0 ∈ R d × d W_0 \in \mathbb{R}^{d \times d} W0∈Rd×d (d 为矩阵维度 )。在 LoRA 中,不是直接对 W 0 W_0 W0 进行更新,而是将全参微调的增量参数矩阵 Δ W \Delta W ΔW 表示为两个参数量更小的矩阵 A 和 B 的乘积,即:
W 0 + Δ W = W 0 + B A W_0 + \Delta W = W_0 + BA W0+ΔW=W0+BA
其中, B ∈ R d × r B \in \mathbb{R}^{d \times r} B∈Rd×r 和 A ∈ R r × d A \in \mathbb{R}^{r \times d} A∈Rr×d 为 LoRA 低秩适应的权重矩阵,秩 r 远小于 d 。这样,原本需要更新的参数量为 d × d d \times d d×d 的 Δ W \Delta W ΔW ,现在变成了更新参数量为 2 × r × d 2 \times r \times d 2×r×d 的 A 和 B 。因为 2 r ≪ d 2r \ll d 2r≪d ,所以可训练参数数量大幅减少 。
举例来说,如果一个模型的权重矩阵维度 d = 1000 d = 1000 d=1000 ,传统全量微调要更新 1000 × 1000 = 1000000 1000 \times 1000 = 1000000 1000×1000=1000000 个参数;若 r = 10 r = 10 r=10 ,使用 LoRA 只需更新 2 × 10 × 1000 = 20000 2 \times 10 \times 1000 = 20000 2×10×1000=20000 个参数,计算量和存储需求显著降低。
-
训练过程
-
初始化:矩阵 B 通常通过高斯函数初始化,即 b i ∼ N ( 0 , σ b 2 ) b_i \sim N(0, \sigma_b^2) bi∼N(0,σb2) ;矩阵 A 一般初始化为全零矩阵,即 a i = 0 a_i = 0 ai=0 。这样在训练开始前, B A = 0 BA = 0 BA=0,微调从预训练权重 W 0 W_0 W0 开始。
-
前向传播:给定输入 x ∈ R d x \in \mathbb{R}^d x∈Rd ,添加 LoRA 后的输出 h ∈ R d h \in \mathbb{R}^d h∈Rd 为:
h = ( W 0 + Δ W ) x = W 0 x + B A x h = (W_0 + \Delta W)x = W_0x + BAx h=(W0+ΔW)x=W0x+BAx
这里, Δ h = B A x \Delta h = BAx Δh=BAx ,它代表了由于低秩矩阵带来的输出变化。 -
反向传播:在训练过程中,原始参数 W 0 W_0 W0 被冻结,即不计算其对应梯度 ∂ L ∂ W 0 \frac{\partial L}{\partial W_0} ∂W0∂L ,只计算低秩矩阵 A 和 B 的梯度,并根据梯度下降等优化算法更新 A 和 B 的参数。
-
推理阶段:推理时,可直接将训练好的低秩矩阵 BA 与预训练权重 (W_0) 合并,即最终推理时使用的权重为 W 0 + B A W_0 + BA W0+BA ,因此相比原始模型在推理时不存在额外开销。
-
超参数与技巧
-
秩 r 的选择:秩 r 是 LoRA 中一个关键超参数。较小的 r 可以节省大量参数和显存,实现更快的训练速度,但可能会减少低秩矩阵中捕获的特定于任务的信息,甚至导致过拟合;较大的 r 能捕获更多任务信息,但会增加计算和存储成本。需通过实验找到精度和性能的平衡。
一般情况下,从 r=8 开始实验,复杂任务可增至 32。 -
学习率:设为全微调的 10-100 倍(如 2e−4)。
-
目标模块:优先微调注意力层的 Query/Value 矩阵
-
权重系数 α \alpha α :实际实现时, Δ W = B A \Delta W = BA ΔW=BA 会乘以系数 α r \frac{\alpha}{r} rα 后再与原始预训练权重 W 0 W_0 W0 合并,即 h = ( W 0 + α r Δ W ) x h = (W_0 + \frac{\alpha}{r}\Delta W)x h=(W0+rαΔW)x 。系数 α \alpha α 是一个超参,它决定了低秩适应的权重矩阵 BA 在最终模型参数中所占的比例 。
实现步骤
- 安装依赖:
pip3 install transformers peft
。 - 配置参数:选择目标模块(如 q_proj, v_proj)、秩 r(通常 4-64)和缩放系数 α。
from peft import LoraConfig
config = LoraConfig(r=8, lora_alpha=32, target_modules=["q_proj", "v_proj"])
3. 训练与部署:使用 Trainer 微调后,可保存适配器(仅几 MB)或合并到原模型。
QLoRA 相关技术
QLoRA(Quantized Low-Rank Adaptation)是一种结合量化技术与低秩适配的高效大模型微调方法,能够在极低显存占用下保持接近全参数微调的性能。以下是其核心技术要点
1. 核心原理
-
4-bit NormalFloat(NF4)量化
针对预训练权重通常服从正态分布的特点,QLoRA提出NF4量化方法:- 通过分位点量化(Quantile Quantization)将权重映射到4-bit空间,理论上对正态分布数据是最优的量化方式。
- 公式:将权重归一化到[−1,1]后,按理论正态分布分位点划分16个区间,每个区间映射为一个4-bit整数值,显著减少存储需求。
-
双重量化(Double Quantization)
对量化常数(Scale)进行二次量化,进一步节省存储空间。例如,第一次量化常数用FP16存储,第二次将其量化为8-bit,平均每个参数节省0.37 bits。 -
分页优化器(Paged Optimizers)
利用NVIDIA统一内存技术,在GPU显存不足时将优化器状态临时卸载到CPU内存,避免内存溢出。
关于双重量化:
第一次量化(主权重量化)
- 分块处理:将权重矩阵 W W W划分为64个参数/块
- 4-bit NF4量化:每块内参数映射到4-bit空间
- 存储缩放因子:每块需存储FP32格式的 C max C_{\text{max}} Cmax(块内绝对值最大值)
- 示例:65B模型需约8TB存储 C max C_{\text{max}} Cmax
第二次量化(缩放因子量化)
- 二次分块:将 C max C_{\text{max}} Cmax集合按256个/块分组
- 8-bit FP8量化:对 C max C_{\text{max}} Cmax进行二次压缩
- 存储优化: C max C_{\text{max}} Cmax存储空间减少50%(FP32→FP8)
2. 数学表达
量化方式 | 存储成本计算公式 | 每参数成本 | 空间节省 |
---|---|---|---|
单次量化 | 32 64 = 0.5 bits \frac{32}{64}=0.5\text{ bits} 6432=0.5 bits | 0.5 bits | - |
双重量化 | 8 64 + 32 64 × 256 ≈ 0.127 bits \frac{8}{64}+\frac{32}{64×256}≈0.127\text{ bits} 648+64×25632≈0.127 bits | 0.127 bits | 75% |
3. 技术优势
- ✅ 显存效率:65B模型 C max C_{\text{max}} Cmax存储从8TB→4TB
- ✅ 精度保留:经反量化后精度损失<2%
- ✅ 硬件适配:支持消费级GPU运行大模型微调
2. 技术优势
-
显存效率:
- 65B参数模型微调仅需48GB显存(4-bit量化+LoRA),而全参数微调需780GB。
- 7B模型可在消费级显卡(如RTX 3090)上运行,显存占用低至5-6GB。
-
性能保留:
通过NF4量化和LoRA适配器补偿,微调后性能与16-bit全参数微调相当(差距<2%)。
3. 实现流程
- 模型加载:以4-bit NF4格式加载预训练权重,冻结原始参数。
插入LoRA适配器:在注意力层(如q_proj、v_proj)添加低秩矩阵(秩r=8∼64),仅训练这部分参数。 - 混合精度训练:计算时反量化为BF16进行矩阵运算,适配器权重保持FP16。
示例代码(Hugging Face集成):
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4")
model = AutoModel.from_pretrained("model_name", quantization_config=bnb_config)
4. 应用场景
- 资源受限环境:如学术研究或边缘设备上的大模型微调。
- 多任务适配:不同任务可独立训练QLoRA适配器,动态加载
P-tuning
核心思想
传统的模型微调方法通常需要调整预训练模型的大量参数,这不仅计算成本高,还可能导致过拟合问题。P-tuning 的核心思想是在输入中插入可训练的提示向量,让模型根据这些提示向量学习如何完成特定任务。这样,只需调整少量的提示向量参数,就可以使模型适应不同的下游任务,大大减少了计算资源和训练时间。
关键技术点
- 提示向量设计
连续提示向量:P-tuning 使用连续的向量来表示提示,而不是传统的离散文本提示。这些连续向量可以直接在模型的嵌入空间中进行训练,使得模型能够更好地理解和利用提示信息。
可训练性:提示向量是可训练的参数,在微调过程中,通过反向传播算法更新这些向量的值,以优化模型在特定任务上的性能。 - 提示插入位置
输入层插入:通常将提示向量插入到输入序列的开头或其他合适的位置。例如,在文本分类任务中,可以将提示向量放在输入文本的前面,作为模型处理文本的额外引导信息。
自适应调整:根据不同的任务和模型架构,提示向量的插入位置可以进行自适应调整,以达到最佳的效果。
输入改造:
对于输入句子 “who are you” ,P-Tuning 会在其前面拼接一组可训练的连续向量(例如 [P1][P2]…[Pn] ),形成新的输入:
X ′ = [ P 1 , P 2 , . . . , P n ; " w h o " , " a r e " , " y o u " ] X' = [P_1, P_2, ..., P_n; "who", "are", "you"] X′=[P1,P2,...,Pn;"who","are","you"]
其中 P i P_i Pi是通过反向传播优化的向量,与词嵌入维度相同(如 768 维)。训练目标:
仅更新这些 Prompt Embeddings 和任务相关层(如分类头),冻结预训练模型的其他参数
- 任务特定提示学习
提示学习目标:在微调过程中,定义一个与特定任务相关的损失函数,通过最小化该损失函数来更新提示向量。例如,在文本分类任务中,可以使用交叉熵损失函数来训练模型。
联合训练:提示向量的学习可以与模型的其他部分(如解码器)联合进行,使得模型能够更好地适应任务需求。
训练流程
- 初始化提示向量:随机初始化提示向量,这些向量将作为模型输入的一部分。
构建输入序列:将提示向量与原始输入文本拼接成一个完整的输入序列,输入到预训练模型中。 - 前向传播:模型对输入序列进行处理,输出预测结果。
- 计算损失:根据任务的目标,计算预测结果与真实标签之间的损失。
- 反向传播:通过反向传播算法,计算损失函数对提示向量的梯度,并更新提示向量的值。
- 重复训练:重复步骤 2 - 5,直到模型在验证集上的性能达到满意的程度。
优点
轻量级微调:只需调整少量的提示向量参数,无需大规模调整模型的原始参数,大大减少了计算资源和训练时间。
跨任务泛化性:由于只调整提示向量,模型的核心参数保持不变,因此 P-tuning 具有较好的跨任务泛化能力,可以在不同的下游任务之间快速迁移。
避免过拟合:相比于传统的全参数微调方法,P-tuning 减少了可训练参数的数量,降低了过拟合的风险。
应用场景
资源受限环境:在计算资源有限的设备上进行模型微调,如移动设备、边缘设备等。
快速任务适应:当需要快速将模型应用到新的任务时,P-tuning 可以通过调整提示向量,快速使模型适应新任务。
多任务学习:在多任务学习场景中,P-tuning 可以通过为每个任务设计不同的提示向量,实现模型在多个任务上的高效学习。
P-tuning v2
P - tuning v2 在 Transformer 每一层插入 Prompt 是对 P - tuning 技术的改进,旨在更有效地利用预训练语言模型的能力。以下是详细解释:
- 背景
在自然语言处理中,Transformer 架构的预训练语言模型在各种任务上取得了显著成果。然而,将这些模型应用于特定任务时,通常需要进行微调以适应任务的特点。P - tuning v2 就是一种在微调过程中,通过在 Transformer 的每一层插入可学习的 Prompt 来提高模型性能的方法。 - 具体操作
- Prompt 表示:P - tuning v2 中的 Prompt 是一系列可学习的向量。这些向量与输入文本的嵌入向量具有相同的维度,并且在训练过程中会不断调整,以引导模型更好地完成任务。
- 插入位置:与原始的 P - tuning 不同,P - tuning v2 不仅仅在输入层插入 Prompt,而是在 Transformer 的每一层都插入 Prompt。具体来说,在每一层的输入之前,将相应的 Prompt 向量与该层的输入向量进行拼接。这样,Prompt 就能够在模型的每一层都对信息处理产生影响,使得模型能够更全面地利用 Prompt 所携带的任务相关信息。
层级插入:
在 Transformer 的每一层(包括 Self-Attention 和 FFN 层)的输入前添加可学习的 Prompt Embeddings(橙色块),与原始输入(蓝色块)拼接后参与计算。
数学表示:对于第i层,输入变为 X i ′ = [ P i ; X i ] X_i' = [P_i; X_i] Xi′=[Pi;Xi],其中 P i P_i Pi是该层的 Prompt 向量 。
参数高效性:仅需调整 0.1%-3% 的参数量(每层 Prompt),远低于全量微调 。
- 作用机制
- 引导信息流动:在 Transformer 中,每一层都对输入进行逐步的特征提取和语义理解。通过在每一层插入 Prompt,可以在不同的抽象层次上引导模型的信息处理过程。Prompt 可以作为一种额外的上下文信息,帮助模型更好地聚焦于任务相关的信息,从而更准确地进行特征提取和语义推理。
- 增强模型适应性:每一层的 Prompt 都可以根据任务的特点和数据的分布进行自适应调整。在底层,Prompt 可以帮助模型更好地处理输入文本的原始特征,如词汇和句法信息;在高层,Prompt 可以引导模型关注更抽象的语义和任务特定的信息,从而使模型能够更好地适应各种不同的任务需求。
- 优点
- 更精细的控制:在每一层插入 Prompt 使得对模型的控制更加精细。相比于只在输入层插入 Prompt,这种方法能够更全面地影响模型的信息处理过程,从而更好地利用模型的多层结构和丰富的表示能力。
- 提高性能:通过在每一层都引入任务相关的提示信息,模型能够更准确地学习到任务的模式和规律,从而在各种自然语言处理任务上取得更好的性能,例如在文本分类、问答系统、文本生成等任务中,P - tuning v2 通常能够优于传统的微调方法以及只在输入层插入 Prompt 的 P - tuning 方法。
- 更好的泛化能力:每一层的 Prompt 都可以根据不同的任务和数据进行自适应调整,这使得模型具有更好的泛化能力。它能够在面对新的任务或数据时,更灵活地利用 Prompt 信息来适应变化,减少对大规模标注数据的依赖,提高模型在不同场景下的适用性。
- 与P-Tuning v1的对比
特性 | P-Tuning v1 | P-Tuning v2 |
---|---|---|
提示位置 | 仅输入层 | 每一层 |
参数占比 | 0.01% | 0.1%-3% |
任务通用性 | 仅适用于简单NLU任务 | 支持序列标注等复杂任务 |
优化方式 | 使用LSTM/MLP重参数化 | 直接优化Prompt,移除编码器 |
关于 P-tuning 的重参数化
- 重参数化概念
重参数化在这里是指通过引入额外的神经网络结构(LSTM 或 MLP ),以一种新的参数化方式来表示原本的 Prompt Embedding(提示嵌入) 。其目的是对 Prompt Embedding 进行变换、调整和优化,让这些提示信息能更好地被预训练模型利用,以适应特定任务。 - LSTM/MLP 具体作用
- LSTM(长短期记忆网络)
- 处理序列相关性:LSTM 擅长处理具有序列相关性的数据。在 P - tuning 里,Prompt 可以看作是一个向量序列。LSTM 能捕捉这些提示向量之间的长短期依赖关系 。比如在文本生成任务中,不同的提示词之间可能存在语义上的前后关联,LSTM 可以学习并利用这种关联,使生成的文本更符合逻辑。
缓解局部最优问题:直接对 Prompt Embedding 进行随机初始化训练,容易陷入局部最优解。LSTM 通过其独特的门控机制(输入门、遗忘门、输出门 ),可以更好地控制信息的流动和记忆,对 Prompt Embedding 进行更有效的编码,引导优化过程,使模型更容易收敛到更好的解 。 - 共享参数与任务适应:在 P - tuning 中,LSTM 的参数可以在不同任务间共享,但针对不同任务会输出独特的 virtual token embeddings(虚拟词嵌入 )。这样既减少了参数数量,又能让模型根据不同任务的需求,对提示信息进行特定的调整 。
- 处理序列相关性:LSTM 擅长处理具有序列相关性的数据。在 P - tuning 里,Prompt 可以看作是一个向量序列。LSTM 能捕捉这些提示向量之间的长短期依赖关系 。比如在文本生成任务中,不同的提示词之间可能存在语义上的前后关联,LSTM 可以学习并利用这种关联,使生成的文本更符合逻辑。
- MLP(多层感知机)
- 增强非线性变换能力:MLP 由多个全连接层组成,能够对输入进行复杂的非线性变换。将其用于 Prompt Embedding 处理时,可以增加模型对提示信息特征提取和变换的能力 。例如,通过多层的非线性映射,可以将原始的提示向量转换到更有利于模型进行任务学习的特征空间。
- 鼓励离散性:在 P - tuning 中,使用带有 ReLU 激活函数的两层 MLP,有助于鼓励 Prompt Embedding 的离散性 。这在一定程度上可以让模型学习到更具区分度的提示特征,提升提示信息对模型预测的影响力。
- LSTM(长短期记忆网络)
- 整体流程
- 首先有一组可学习的 Prompt Embedding 作为输入。
- 将这些 Prompt Embedding 输入到 LSTM 和 MLP 中,LSTM 捕捉序列关联,MLP 进行非线性变换和特征提取,对 Prompt Embedding 进行重新编码和调整。
- 经过 LSTM/MLP 重参数化处理后的提示向量,再输入到预训练模型(如 Transformer )中参与后续的计算,引导模型完成特定任务。
不过在 P - tuning v2 中,发现重参数化(包括 LSTM/MLP 这种方式 )带来的改进较小,尤其是对于较小的模型,还可能影响模型表现,所以移除了这种重参数化编码器 。
(1) LSTM 重参数化
- 结构:双向 LSTM + MLP
# Hugging Face P-Tuning 示例
prompt_encoder = nn.Sequential(nn.LSTM(embedding_dim, hidden_size, bidirectional=True),nn.Linear(hidden_size * 2, embedding_dim)
)
- 优势:
捕捉 Prompt 序列的时序依赖关系,适合自然语言风格的提示优化。
(2) MLP 重参数化
- 结构:多层感知机(含 ReLU 激活)
prompt_encoder = nn.Sequential(nn.Linear(embedding_dim, hidden_size),nn.ReLU(),nn.Linear(hidden_size, embedding_dim)
)
- 优势:
计算效率更高,适合简单任务。
Prefix Tuning
Prefix Tuning(前缀微调)是一种参数高效微调(Parameter - Efficient Fine - tuning, PEFT)方法,旨在以较低的计算成本使预训练语言模型适配特定任务。以下是其详细介绍:
一、关键概念
前缀(Prefix)
位于输入序列前的可训练向量序列,是 Prefix Tuning 的核心。这些向量不是自然语言形式,而是抽象的、连续的可学习表示,用于传递任务特定信息,引导模型生成符合任务需求的输出。
虚拟标记(Virtual Token)
前缀向量在模型中被视为 “虚拟输入标记”,参与注意力计算,影响模型对输入信息的处理和生成。
二、核心原理
Prefix Tuning 通过在模型输入前添加可训练的连续向量序列(Prefix)来引导模型行为。具体如下:
冻结预训练模型参数
预训练模型已在大规模数据上学习到通用语言知识,Prefix Tuning 在微调时冻结其参数,避免破坏这些知识,仅优化前缀向量。
添加可训练前缀向量
在模型输入序列前添加可训练的前缀向量,不同任务可学习到不同的前缀表示。以文本生成任务为例,合适的前缀向量能引导模型生成符合特定风格、主题或格式要求的文本。
参与模型计算
这些前缀向量作为 “虚拟标记” 参与模型的注意力计算等过程,让模型在处理输入时考虑前缀携带的任务相关信息,调整输出。
三、技术实现要点
修改后的注意力计算:
Attention ( Q , [ P K ; K ] , [ P V ; V ] ) \quad \text{Attention}(Q, [P_K; K], [P_V; V]) Attention(Q,[PK;K],[PV;V])
前缀向量设计
- 添加位置
- 对于解码器模型(如 GPT),仅在解码器输入前添加前缀。
- 对于编码器 - 解码器模型(如 BART),在编码器和解码器输入前均添加前缀。
模型类型 | 输入改造公式 | 说明 |
---|---|---|
自回归模型(GPT) | ( z = [PREFIX; x; y] ) | 前缀影响编码和生成 |
编码器-解码器 | ( z = [PREFIX; x; PREFIX’; y] ) | 分别添加Encoder/Decoder前缀 |
- 长度确定
- 前缀长度(虚拟标记数量)是超参数,一般取值在 20 - 100,需根据任务复杂度和计算资源确定。
- MLP 分解
- 为使训练更稳定,常将前缀参数分解为更小的嵌入层和 MLP 层(多层感知机)。这能减少参数量,提升训练稳定性,例如将原始前缀参数 P P P_P PP 进行分解。
训练过程
- 加载预训练模型
- 用 Hugging Face 的 transformers 库等工具加载模型,并冻结所有参数。
- 插入前缀适配器
- 定义前缀长度等参数,插入前缀模块。例如使用 PEFT 库时,配置
PrefixTuningConfig
,设置任务类型、前缀长度、是否使用 MLP 分解等参数,再通过get_peft_model
插入适配器。
- 定义前缀长度等参数,插入前缀模块。例如使用 PEFT 库时,配置
- 配置训练参数
- 设置学习率(常低于全量微调,如 1 e − 4 1e - 4 1e−4 到 5 e − 5 5e - 5 5e−5)、批次大小(可依显存适当增大)等超参数。
- 训练与评估
- 训练中仅优化前缀参数,监控生成质量指标(如文本生成任务用 BLEU、ROUGE)。
- 推理部署
- 推理时固定前缀参数,输入文本加上前缀向量后传入模型,生成任务特定输出。
from peft import PrefixTuningConfigconfig = PrefixTuningConfig(task_type="SEQ_2_SEQ_LM",num_virtual_tokens=20, # 前缀长度prefix_projection=True, # 启用MLP重参数化encoder_hidden_size=768 # MLP隐藏层维度
)
四、与传统微调对比优势
特性 | Prefix-Tuning | P-Tuning v2 | Prompt Tuning |
---|---|---|---|
参数位置 | 所有层 | 所有层 | 仅输入层 |
适用架构 | 生成任务 | NLU/NLG通用 | 大模型NLU |
参数量 | 0.1%-1% | 0.1%-3% | <0.1% |
重参数化 | MLP | 无 | 无 |
-
参数高效
传统微调需调整模型全部参数,计算成本高;Prefix Tuning 仅优化前缀向量相关参数,通常只需优化约 1 % 1\% 1% 的参数(远小于全量微调),大幅降低计算和存储需求。
-
减少过拟合风险
由于大部分预训练模型参数不变,Prefix Tuning 在小数据集上微调时,过拟合风险更低。
-
任务适配灵活
可针对不同任务学习不同前缀,快速适配多种下游任务,无需重复训练整个模型。
-
可用于闭源模型
因不改变模型主体参数,对于一些未开源、无法直接访问内部参数的模型,也能应用 Prefix Tuning 进行任务适配。
五. 实践建议
- 前缀长度通常选择10-20个token
- 初始化使用任务相关文本编码更稳定
- 复杂任务建议结合多任务学习策略
Adapter Tuning
Adapter Tuning(适配器微调)是一种参数高效的迁移学习方法,通过在预训练模型(如 BERT、GPT 等)中插入小型可训练模块(Adapter 层),仅调整这些模块的参数,而冻结主模型参数,从而显著降低计算和存储成本。以下是其核心要点:
-
核心原理
- 结构设计:每个 Adapter 层包含下采样(Down-Projection)、非线性激活(如 ReLU/GELU)和上采样(Up-Projection)模块,形成瓶颈结构(Bottleneck Layer)。例如,输入维度 d=768 可压缩到 m=64,参数量仅为 2md+2d(远小于全连接层的 d²)。
- 残差连接:Adapter 输出与原始输入相加,确保训练初期模型性能稳定。
-
优势
- 参数高效:仅需 0.5%-8% 的额外参数(如 BERT-Large 仅增加约 1.5M 参数)。
- 多任务适配:通过插入不同 Adapter 模块实现多任务并行,无需保存独立模型。
- 训练速度快:训练时间仅为全量微调的 1/10 至 1/100。
-
技术变种
- AdapterFusion:分两阶段训练,先独立训练各任务 Adapter,再学习组合多个 Adapter 的知识,提升目标任务性能。
- AdapterDrop:动态移除部分 Adapter 层以减少推理开销,效率可提升 39%。
- LoRA:通过低秩矩阵分解进一步减少参数量(如 1%),适合极大模型(如 GPT-3)。
AdapterFusion 是一种针对多任务学习的参数高效微调方法,通过两阶段训练整合多个任务的知识,同时避免灾难性遗忘。以下是其核心要点:
3.1. 两阶段训练机制
- 知识提取阶段:独立训练各任务的 Adapter 模块(如 NLI、STS 等),冻结预训练模型参数。可采用两种策略:
- ST-A(单任务适配器):各任务独立训练,互不干扰。
- MT-A(多任务适配器):联合优化所有任务,但可能因任务差异导致性能不均衡。
- 知识组合阶段:固定预训练参数和 Adapter 参数,引入 AdapterFusion 层(类似 Attention 机制),动态加权组合不同 Adapter 的输出。公式如下:
Output = SoftMax ( Q K T d ) V \text{Output} = \text{SoftMax}\left(\frac{QK^T}{\sqrt{d}}\right)V Output=SoftMax(dQKT)V
其中 Q Q Q 为 Transformer 层输出, K / V K/V K/V 来自各任务 Adapter。
3.2. 结构设计
- AdapterFusion 层:每层 Transformer 插入一个共享的 Attention 模块,参数包括 (Q/K/V) 矩阵,通过上下文动态分配权重。
- 残差连接:保留 Adapter 的恒等映射初始化,确保训练稳定性。
-
应用场景
- 文本分类/机器翻译:在 BERT 或 NMT 模型中插入语言/任务特定 Adapter,保留通用知识的同时适配新任务。
- 跨领域迁移:如医疗、法律等领域的定制化模型。
-
实现示例(基于 Hugging Face)
from transformers import AutoModelForSequenceClassification, AutoTokenizer model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased") model.add_adapter("task_name", config={"reduction_factor": 12}) # m=64 model.train_adapter("task_name") # 仅训练 Adapter 参数
-
对比其他方法
方法 | 参数量 | 计算效率 | 适用场景 |
---|---|---|---|
全量微调 | 100% | 低 | 资源充足的单一任务 |
Adapter Tuning | 0.5%-8% | 高 | 多任务/资源受限场景 |
LoRA | ~1% | 极高 | 极大模型(如 GPT-3) |
- 挑战
推理延迟:Adapter 层增加前向传播分支,可能略微降低推理速度。
结构设计:需平衡瓶颈维度 m 与性能,过小可能影响效果。
相关文章:
大模型 SFT 中的关键技术总结学习
文章目录 微调策略LoRA 微调核心思想具体实现过程超参数与技巧实现步骤 QLoRA 相关技术1. 核心原理2. 技术优势3. 实现流程4. 应用场景 P-tuning核心思想关键技术点训练流程优点应用场景 P-tuning v2Prefix Tuning一、关键概念前缀(Prefix)虚拟标…...
AI如何重塑DDoS防护行业?六大变革与未来展望
一、AI驱动的攻击与防御:攻防博弈的全面升级 AI技术的引入使DDoS攻防进入“智能对抗”时代,攻击者与防御方均借助AI提升效率,形成新的技术平衡。 1. 攻击端:AI赋能攻击的智能进化 动态流量生成:攻击者利用生成对抗网…...
电池的寿命
思路: 首先,我们观察发现:由于每枚电池的使用时间不同,而我们又要减少浪费才能使所有电池加起来用得最久,不难发现:当n2时,输出较小值。 第一步:将电池分为两组,使两组…...
Android完整开发环境搭建/Studio安装/NDK/本地Gradle下载配置/创建AVD/运行一个Android项目/常用插件
目录 安装Android Studio 修改sdk位置 配置 HTTP 代理 安装 NDK 设置快捷键 Gradle 说明 setting.gradle init.gradle build.gradle 下载 相关设置 创建项目 阿里云加速 清理缓存并同步 创建AVD 实用插件 ADB Idea Android Drawable Importer GsonFormat …...
【KWDB 创作者计划】_KWDB引领数据库技术革新的璀璨之星
【KWDB 创作者计划】_KWDB引领数据库技术革新的璀璨之星 🌟嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 在当今数字化浪潮汹涌澎湃的时代&…...
设计模式--桥接模式详解
桥接模式(bridge pattern) 桥接模式时将抽象部分与它的实现部分分离,使他们可以独立的变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或者接口(interface)模式&…...
Python+Selenium+Pytest+Allure PO模式UI自动化框架
一、框架结构 allure-report:测试报告base:定位元素封装data:数据log:日志文件page:页面封装文件夹report:缓存报告testcases:测试用例层utils:工具类run.py:执行文件 二…...
【C语言操作符详解(一)】--进制转换,原反补码,移位操作符,位操作符,逗号表达式,下标访问及函数调用操作符
目录 一.操作符的分类 二.二进制和进制转换 2.1--2进制转10进制 编辑 2.1.1--10进制转2进制数字 2.2--2进制转8进制和16进制 2.2.1--2进制转8进制 2.2.2--2进制转16进制 三.原码,反码,补码 四.移位操作符 4.1--左移操作符 4.2--右移操作符…...
回顾|Apache Cloudberry™ (Incubating) Meetup·2025 杭州站
2025 年 4 月 19 日,由酷克数据与中启乘数联合举办的 Apache Cloudberry™ (Incubating) Meetup 杭州站在浙江省杭州市滨江区滨江会展中心成功举办。本次活动邀请了 Cloudberry PPMC 团队成员、活跃内核贡献者以及中兴 EBASE-A、阿里云 ADB-PG、网易、中启乘数等多…...
使用 Autofac 实现依赖注入
前言:接上一篇文章,有了微软官方的依赖注入组件Microsoft.Extensions.DependencyInjection, 那么今天介绍一个新的开源的依赖注入组件Autofac 一、二者的差异Autofac和微软官方的依赖注入组件(Microsoft.Extensions.DependencyIn…...
HTTP:十二.HTTPS
HTTPS 概述 超文本传输安全协议(英语:HyperText Transfer Protocol Secure,缩写:HTTPS;常称为HTTP over TLS、HTTP over SSL或HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,利用TLS加密数据包。 HTTPS的主要目的是提供对网站服务器…...
《代码整洁之道》第12章 迭进 - 笔记
好的设计是如何形成的? 章节核心: 好的软件设计不是完全靠前期庞大的设计方案来完成的,而更多地是在持续的编码、测试和重构过程中,“涌现”或“演进”出来的。 设计不是一次性的前期活动 大白话: 作者认为&#x…...
数字巴别塔:全栈多模态开发框架如何用自然语言重构软件生产关系?
一、自然语言编程的范式革命 1. 从代码行数到语义密度 开发效率对比(某金融 SaaS 案例): 开发方式代码量(行)开发时间(天)维护成本($/年)传统 React5,2004512,000低代码…...
【C语言极简自学笔记】C 语言数组详解:一维数组与二维数组
在 C 语言中,数组是一种非常重要的数据结构,它可以将多个相同类型的元素组织在一起,以便于我们进行批量处理和操作。本文将详细介绍 C 语言中的一维数组和二维数组,包括它们的定义、初始化、元素访问以及内存存储等方面的内容。 …...
从零构建云原生秒杀系统——后端架构与实战
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:秒杀系统的挑战与机遇 在电商、票务、抢购等业务场景中,“秒杀”系统扮演着至关重要的角色。 秒杀活动通常会在极短时间内爆发出数十倍至数百倍的平时流量,这对后端系统的承载能力、响应…...
Linux Socket编程:从API到实战
Linux Socket编程完全指南:从API到实战 概述 Socket(套接字)是网络编程的基础,它允许不同主机或同一主机上的不同进程之间进行通信。在Linux系统中,Socket编程主要通过一系列系统调用来实现,这些API提供了…...
德州仪器(TI)—TDA4VM芯片详解(1)—产品特性
写在前面 本系列文章主要讲解德州仪器(TI)TDA4VM芯片的相关知识,希望能帮助更多的同学认识和了解德州仪器(TI)TDA4VM芯片。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 错过其他章节的同学…...
增强版wps-plugin-deepseek开源插件是DeepSeek 支持的 WPS 插件,在您的办公工作流程中提供智能文档自动化和 AI 驱动的生产力增强
一、软件介绍 文末提供程序和源码下载学习 增强版wps-plugin-deepseek开源插件专为WPS Office插件开发打造的Vue模板,搭配Vite构建工具,提供丰富的WPS API实操示例。虽然官方提供了TypeScript扩展包,但支持程度有限,因此本项目选…...
在 Cursor 中 配置 GitHub MCP Server
文章目录 1、简单回顾 sequentialthinking 的安装2、提出问题:如何在 cursor 配置 github mcp 呢3、结果如下How to Configure GitHub MCP in CursorPrerequisitesStep 1: Update Cursor (if needed)Step 2: Generate a GitHub Personal Access TokenStep 3: Open Cursor MCP S…...
uniapp-商城-40-shop 购物车 选好了 进行订单确认4 配送方式3 地址编辑
前面说了配送 和地址页面 当地址页面为空或需要添加地址时,需要添加地址。 我的地址页面有个按钮 就是添加地址 点击 添加地址 按钮 后,就会跳转到地址添加的页面 1、添加地址页面 2、添加地址文件夹以及文件的创建 3、添加地址的代码 <template…...
初步自定义layui的table(laravel 12)
layui的table是非常好的表格,有美观的样式,对接起来也很便捷。使用后端翻页传过来的数据,本地测试是好的,部署到服务器时,翻页不起作用。故而暂时采用一次性读取全部数据,发送给table,界面如下所…...
手写SpringMVC(基本框架)
服务器启动阶段处理 分析服务器启动阶段都都需要初始化什么? 1.初始化Spring容器 组件扫描包下的类纳入IOC容器管理创建视图解析器对象创建所有的拦截器对象扫描这和包下的所有类org.myspringmvc.web.servlet.mvc.method.annotation,全部实例化&#…...
JS-OCR-demo加载本地文件
背景: 在了解 Tesseract 的识别效果的时候,有个demo项目很好用。有个小毛病,就是没事都要从摄像头抓取图片,然后进行识别。如果可以从本地读取图,就更方便了。 实现: 下载项目代码:https://gi…...
MySQL 表的约束(一)
文章目录 表的约束空属性默认值列描述zerofill主键总结 表的约束 1. 为什么要有表的约束? 因为要保证数据的完整性和可约束性,合法性 空属性 两个值:null(默认的)和not null(不为空)数据库默认字段基本都是字段为空…...
论文导读 - 基于大规模测量与多任务深度学习的电子鼻系统实现目标识别、浓度预测与状态判断
基于大规模测量与多任务深度学习的电子鼻系统实现目标识别、浓度预测与状态判断 原论文地址:https://www.sciencedirect.com/science/article/abs/pii/S0925400521014830 引用此论文(GB/T 7714-2015): WANG T, ZHANG H, WU Y, …...
力扣hot100_子串_python版本
一、560. 和为 K 的子数组 思路:这就是一道典型的前缀和的题代码: class Solution:def subarraySum(self, nums: List[int], k: int) -> int:presum [0] * (len(nums) 1)for i, x in enumerate(nums):presum[i 1] presum[i] x # 前缀和序列需要n1个ans 0…...
cached-property - 类属性缓存装饰器
本文翻译整理自:https://github.com/pydanny/cached-property 文章目录 一、关于 cached-property相关链接资源关键功能特性 二、安装三、使用指南1、基础用法2、手动清除缓存3、线程安全版本4、异步支持5、缓存超时(TTL) 四、致谢 一、关于…...
「Mac畅玩AIGC与多模态03」部署篇02 - 在 Mac 上部署 Dify
一、概述 本篇介绍如何在 macOS 环境下本地部署 Dify 平台,作为多模型协同与工作流集成的可视化应用服务。Dify 提供了模型调用、对话管理、知识库问答、插件服务等功能,可与 Ollama、OpenAI、DeepSeek 等推理后端集成,适用于本地智能体应用的快速搭建与扩展。 二、部署流…...
扩散模型和马尔科夫链
1. 扩散模型的基本原理 扩散模型的灵感来源于热力学扩散(如一滴墨水在水中逐渐扩散的过程),其核心分为两个阶段: 前向过程(Forward Process):逐步向数据添加噪声,直到数据完全变为随…...
Dify框架面试内容整理-Dify如何处理知识库的集成?
Dify 在知识库集成方面采用了“检索增强生成(RAG)”的技术架构,核心实现思路如下: 一、知识库集成的整体流程 Dify处理知识库集成通常包括以下关键步骤: 文档上传↓...
第35课 常用快捷操作——用“鼠标左键”拖动图元
概述 拖动某个图元,是设计过程中常需要用到的操作,我们可以在原理图中拖动某个元器件符号,也可以在PCB图中拖动某个焊盘。 和常用的软件类似,用按住鼠标左键的方式来完成拖动操作。 用鼠标左键拖动图元 在想要拖动的图元上&…...
复盘笔记1
以下是一份专业股市投资操盘手的复盘清单,涵盖市场分析、交易策略、风险管理等核心环节,帮助系统化梳理每日交易并优化次日决策: --- ### **一、市场整体复盘** 1. **指数与成交量分析** - 主要指数表现(上证、深证、创业板、科…...
海思dump图原理
在海思中是用指令进行对应的dump。 例如./vi_chn_dump 0 0 1 1 第一个指令代表是dump哪里的数据。 第一个0代表是vi_pipe。 第二个0代表vi_chn。 第一个1代表需要dump帧的数量。 第二个dump代表dump帧的位置,如果是0表示dump的是在所有ISP模块后面的数据࿰…...
C++:STL——list
一简介 底层是一个带头双向循环列表 二、成员函数 (1)构造函数 三、迭代器 四、修饰函数 (1)insert 插入和删除不再使用下标,而是使用迭代器指针作为要插入位置的形参,这是因为:vector是连续的…...
在Azure Databricks中实现缓慢变化维度(SCD)的三种类型
在Azure Databricks中使用PySpark实现缓慢变化维度(SCD)的三种核心类型,需结合Spark SQL和DataFrame API的特性,并利用Delta Lake的事务支持。以下是具体设计与实现步骤,以及测试用例: 通过以下步骤&#…...
Segment Anything in Images and Videos
目录 摘要 Abstract SAM2 模型框架 图像编码器 记忆机制 提示编码器和掩码解码器 实验 代码 总结 摘要 SAM2是基于Meta公司推出的Segment Anything Model升级而来的先进分割模型。它在SAM的基础上,通过引入记忆注意力模块和优化图像编码器等改进…...
C++之异常
目录 一、异常的概念及使用 1.1、异常的概念 1.2、异常的抛出和捕获 1.3、栈展开 1.4、查找匹配的处理代码 1.5、异常重新抛出 1.6、异常安全问题 1.7、异常规范 1.8、C异常的优缺点 二、标准库的异常 一、异常的概念及使用 1.1、异常的概念 异常处理机制允许程序中…...
服务器不能复制粘贴文件的处理方式
1.打开远程的服务器,在服务器的任务栏随便一块空白处右击鼠标,选择“启动任务管理器”。 2.在打开的任务管理器中,我们找到“rdpclip.exe”这个进程,如果没有找到那么如图所示 任务管理器–文件–运行新任务,然后在弹出的对话框内输入rdpclip.exe 如下图࿱…...
Golang | 搜索表达式
// (( A | B | C ) & D ) | E & (( F | G ) & H )import "strings"// 实例化一个搜索表达式 func NewTermQuery(field, keyword string) *TermQuery {return &TermQuery{Keyword: &Keyword{Field: field, Word: keyword},} }func (tq *TermQuery…...
【速写】conda安装(linux)
序言 昨天叶凯浩空降(全马241),降维打击,10分24秒断层夺冠。 夏潇阳10分53秒绝杀小崔10分54秒第2,小崔第3,均配都在3’30"以内,即便我是去年巅峰期也很难跑出这种水平。我就知道他去年大…...
linux两个特殊的宏 _RET_IP_ 和_THIS_IP_ 实现
本文探讨了Linux环境下两个特殊的宏,_RET_IP_和_THIS_IP_,它们分别用于获取当前函数的返回地址和当前指令指针的地址。 1、宏定义 我们先看它们的宏定义 include./linux/kernel.h#define _RET_IP_ (unsigned long)__builtin_return_address(0)#define _THIS_IP_ ({ __labe…...
开源|上海AILab:自动驾驶仿真平台LimSim Series,兼容端到端/知识驱动/模块化技术路线
导读 随着自动驾驶技术快速发展,有效的仿真环境成为验证与增强这些系统的关键。来自上海人工智能实验室的研究团队推出了LimSim Series——一个革命性的自动驾驶仿真平台,它巧妙解决了行业面临的三大挑战:仿真精度与持续时间的平衡、功能性与…...
全栈黑暗物质:可观测性之外的非确定性调试
一、量子计算的测不准Bug 1. 经典 vs. 量子系统的错误模式 量子程序崩溃的观测影响: 调试方法崩溃复现率观测干扰度日志打印12%35%断点调试5%78%无侵入跟踪27%9%量子态层析成像63%2% 二、量子调试工具箱 1. 非破坏性观测协议 # 量子程序的无干扰快照 from qiski…...
光耦、继电器
一、光耦 1.什么是光耦? ①图一:Ic受控于Ib,间接受控于Ia ②如果Va和Vb是隔离的两个电压系统该咋控制?可以利用光耦来控制,让两边建立关系 2.光电耦合器的基本原理 ①是以光为媒介来传输电信号的器件,通常把发光器…...
使用Three.js搭建自己的3Dweb模型(从0到1无废话版本)
教学视频参考:B站——Three.js教学 教学链接:Three.js中文网 老陈打码 | 麒跃科技 一.什么是Three.js? Three.js 是一个基于 JavaScript 的 3D 图形库,用于在网页浏览器中创建和渲染交互式 3D 内容。它基于 WebGL࿰…...
Redis远程链接应用案例
1.配置文件设置 打开配置文件redis.windows.conf,配置以下内容: 1.bind 0.0.0.0(设置所有IP可访问) 2.requirepass 1234.com(密码设置) 3.protected-mode no(远程可访问) 2.防火…...
STM32 定时器TIM
定时器基础知识 定时器就是用来定时的机器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM6、TIM7),如下图所示: STM32F1…...
基于大模型的急性化脓性阑尾炎全程诊疗预测与方案研究
目录 一、引言 1.1 研究背景与意义 1.2 国内外研究现状 1.3 研究目标与方法 二、大模型技术原理与应用基础 2.1 大模型概述 2.2 相关技术原理 2.3 数据收集与预处理 三、术前风险预测与准备 3.1 病情评估指标分析 3.2 大模型预测方法与结果 3.3 术前准备方案 四、…...
第一个 servlet请求
文章目录 前端后端前后端 产生 联系 前端 后端 package com.yanyu;import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.I…...
XLSX.utils.sheet_to_json设置了blankrows:true,但无法获取到开头的空白行
在用sheetJs的XLSX库做导入,遇到一个bug。如果开头行是空白行的话,调用sheet_to_json转数组获得的数据也是没有包含空白行的。这样会导致在设置对应的起始行时,解析数据不生效。 目前是直接跳过了开头的两行空白行 正确应该获得一下数据 问…...