PEFT

img

img

img

参数高效微调(PEFT,Parameter-Efficient Fine-Tuning)是一系列旨在高效适应大型预训练模型到特定下游任务的方法。与传统微调更新整个模型所有参数不同,PEFT 方法只调整模型中很小一部分参数,从而大大减少了计算和存储成本,同时通常能达到与全量微调相媲美的性能。


PEFT 的主要类型

PEFT 方法大致可以分为几大类:

1. 适配器方法 (Adapter-based Methods)

这类方法通过在预训练模型的特定位置(例如Transformer层的中间)插入小的、可训练的神经网络模块(适配器),并只训练这些适配器,而冻结原始模型的大部分参数。

  • Adapter Tuning (或 Adapters):这是最早也是最经典的适配器方法之一。它在Transformer的每个子层(自注意力层和前馈网络层)之后插入一个小的瓶颈结构(通常是先降维再升维的线性层)。训练时只更新这些适配器的参数。
  • LoRA (Low-Rank Adaptation):LoRA 是目前最流行和高效的PEFT方法之一。它不直接修改原始模型的权重,而是通过在预训练矩阵旁边引入两个小的低秩矩阵来模拟对原始权重的更新。在训练时,只更新这两个低秩矩阵的参数,原始权重保持冻结。LoRA 的核心思想是,微调所需的权重变化(ΔW)通常是低秩的,因此可以用两个较小的矩阵的乘积来表示。
  • QLoRA (Quantized Low-Rank Adaptation):QLoRA 是 LoRA 的一个扩展,它将预训练模型量化为更低的精度(例如4比特)来进一步减少内存占用,同时在训练时仍然使用LoRA引入的低秩适配器,并在计算梯度时进行反量化。这使得在消费级GPU上也能微调非常大的模型。
  • AdaLoRA:LoRA 的变体,它引入了自适应机制,根据权重的重要性动态调整低秩矩阵的秩,从而进一步优化了参数效率和性能。
  • LoHa (Low-Rank Hessian Adaptation)LoKr (Low-Rank Kronecker product Adaptation):LoRA 的其他变体,旨在通过不同的低秩分解方式来提升性能。

2. 提示工程方法 (Prompt-based Methods)

这类方法通过添加或修改输入提示(prompts)来引导模型,而不是直接修改模型内部的权重。这些提示可以是离散的(硬提示,通常手动设计),也可以是连续可训练的(软提示/连续提示)。

  • Prompt Tuning (软提示/连续提示):在模型的输入嵌入前添加一小段可训练的连续向量(软提示),只训练这些向量,而模型主体参数保持冻结。这些软提示不对应任何实际的词汇,而是通过优化学习到最能激活模型完成任务的模式。
  • Prefix Tuning:在Transformer的每一层都插入一小段可训练的连续前缀(prefix),这些前缀通常会影响注意力机制的键(Key)和值(Value)矩阵。同样,只训练这些前缀的参数,模型主体冻结。
  • P-Tuning:Prompt Tuning 的一个变体,旨在解决 Prompt Tuning 在某些情况下性能不稳定的问题。P-Tuning 通过使用一个小型网络(如LSTM或MLP)来生成软提示,使得软提示的优化更加稳定和有效。
  • P-Tuning v2:P-Tuning 的改进版,它将提示插入到Transformer的更多层中(类似于Prefix Tuning),并发现这对于提升性能和稳定性至关重要。

3. 选择性方法 (Selective Methods)

这类方法选择性地微调模型中的一小部分现有参数,而不是引入新的参数。

  • BitFit:只微调模型中的偏置(bias)项。实验发现,即使只训练偏置项,也能在一些任务上获得不错的效果,因为偏置项在神经网络中对输出的微调起着关键作用。
  • DiffPruning:通过学习一个稀疏的更新掩码来选择性地更新部分权重,从而达到参数效率。

4. 其他方法

  • IA3 (InfiniTune Adaptor for Intrinsic Adaptability and Interpretability):通过学习一组适配器向量来缩放模型的内部激活,而不是像LoRA那样修改权重矩阵。
  • Bit-Level Fine-Tuning:结合量化技术,在低精度下进行微调,以减少内存和计算需求。

PEFT 的优势

  • 显著减少计算资源:只需要更新和存储少量参数,大大降低了GPU内存和计算时间的需求。
  • 减少存储空间:对于每个下游任务,只需存储微调后的PEFT模块(适配器或提示),而不是整个模型的一份副本。这对于部署大量特定任务模型非常有益。
  • 缓解灾难性遗忘:由于大部分预训练模型的参数是冻结的,模型在适应新任务时不容易忘记其在预训练阶段学到的通用知识。
  • 提高模型便携性:微调后的PEFT模块文件很小,便于分享、部署和更新。

具体介绍

BitFit

调整模型的bias参数,比如transformer中的mlp层和注意力层

 # 基于bitfit只训练带有bias的参数
    for name, param in model.named_parameters():
        if "bias" not in name:
            param.requires_grad = False

Prefix Tuning

img

img

通过全连接层(具有两层的迷你MLP和介于两者之间的非线性激活函数)来进行桥接

不改变预训练好的语言模型(LM)本身的参数,而是给这个模型添加一个新的部分(一个新的前缀模型,在代码中体现为给要调整的层增加维度或者层数),即前缀(prefix)。这个前缀是可以进行训练的,并且是针对特定任务定制的。例如,对于一个文本分类任务和一个文本生成任务,就可以设计两个不同的前缀分别用于这两个任务,这样就能在同一预训练语言模型的基础上,实现对不同任务的适应。

该方法是在输入token之前构造一段任务相关的virtual tokens作为Prefix,相当于对于transformer的每一层 (不只是输入层,且每一层transformer的输入不是从上一层输出,而是随机初始化的embedding作为输入),都在真实的句子表征前面插入若干个连续的可训练的"virtual token" embedding,这些伪token不必是词表中真实的词,而只是若干个可调的自由参数

Prefix Tuning和Prompt Tuning最大的区别就是Prefix Tuning会向每层的Transformer Block添加可训练的张量

Prompt Tuning

Prefix Tuning 的简化版本,它给每个任务定义了自己的Prompt(虚拟值virtual token,不是真实语言),然后拼接到数据上作为输入,但只在输入层加入prompt tokens,并且不需要加入 MLP 进行调整来解决难训练的问题。

在K,V上添加新的embedding

total_virtual_tokens = config.num_virtual_tokens * config.num_transformer_submodules
# 初始化 embedding 层
self.embedding = torch.nn.Embedding(total_virtual_tokens, config.token_dim)

过反向传播更新参数来学习prompts,而不是人工设计prompts;同时冻结模型原始权重,只训练prompts参数,训练完以后,用同一个模型可以做多任务推理。

Adapter Tuning

类似Lora,但是它是在这些层后增加一个小型的神经网络。

在 Adapter Tuning 中,会在模型的每个层或某些特定层之间插入小的神经网络模块,称为“adapters”。这些 adapters 是可以训练的,而原始模型的参数则保持不变。

P-Tuning

v1

img

类似Prompt Tuning,不同在于在使用一是专门用一个Prompt Encoder把提示词变为连续的嵌入向量virtual token,二是virtual token插在输入层的任意位置,而且在输入层中不一定是前缀,可能是输入层的前面、或者中间或者后面

image-20250625105742920

结合第一个图片中的 (b) P-tuning 的图示,这个表达式代表了 P-tuning 方法中输入给预训练语言模型的最终嵌入序列

下面是各字母和符号的意义:

  • h0,…,hi,hi+1,…,hj,hj+1,…,hk:

    • 这些 h 字母代表的是 伪提示(Pseudo Prompts)的嵌入向量
    • 在 P-tuning 中,这些伪提示不是实际的文本词汇,而是可学习的、连续的向量。它们在训练过程中被优化,以引导预训练语言模型更好地完成下游任务。
    • 它们通常被称为 软提示(Soft Prompts)连续提示(Continuous Prompts)
    • 图 (b) 中,上面的 "[P0]...[Pi]" 和 "[Pi+1]...[Pm]" 箭头指向的就是这些伪提示,它们经过一个 "Prompt Encoder" 编码器(或直接作为可训练参数)后,成为嵌入向量 h0,…,hk。
  • e(x):

    • 这代表了 输入文本 x 的词嵌入向量
    • x 通常是用户问题或任务相关的原始文本输入中的一个部分(例如,图 (b) 中的 "capital")。
    • e(⋅) 表示一个嵌入函数,它将文本(词或子词)映射到一个高维的向量空间。这些嵌入向量通常是由预训练语言模型的原始词嵌入层生成的
  • e(y):

    • 这代表了 输入文本 y 的词嵌入向量
    • y 是用户问题或任务相关的原始文本输入中的另一个部分(例如,图 (b) 中的 "Britain")。
    • 同样,e(⋅) 也是通过预训练语言模型的原始词嵌入层生成的。
  • 方括号 {…}:

    • 表示一个序列或集合。在这里,它表示将伪提示的嵌入向量和原始输入文本的嵌入向量按特定顺序拼接或插入,形成一个完整的序列
  • 省略号 …:

    • 表示序列中省略了中间的元素。

总结来说,这个表达式描述了 P-tuning 方法的核心思想:

将任务相关的伪提示(可学习的连续向量 hi)*与原始输入文本(经过预训练模型词嵌入层得到的 e(x) 和 e(y))的嵌入向量*混合在一起,形成一个统一的输入序列。这个序列随后被送入冻结的预训练语言模型(如 GPT、BERT),以引导模型完成特定任务,而无需对整个大型模型进行微调。这种方法通过优化少量伪提示的参数,就能有效地适应下游任务。

ps:该Prompt Encoder是用 LSTMs or MLPs做的

v2

更像是Prefix Tuning的改进,而不是Prompt Tuning

按照v1的方法,作者发现有以下局限

  • 规模通用性:在Fixed LM Prompt Tuning并采用全量数据的前提下,Prompt Tuning (The Power of Scale for Parameter-Efficient Prompt Tuning) 被证明能够匹敌Fine-tuning的效果,而只需要很少的参数微调:但是要求是10B以上的参数量的预训练模型,以及特殊的初始化技巧等
    对于普通模型,能不能在Fixed LM Prompt Tuning+全量数据情况下匹敌Fine-tuning?
  • 任务通用性:尽管P-tuning在SuperGLUE上表现很好,对于一些比较难的token-level的任务表现就差强人意了,比如阅读理解和NER,当然现在也有一些工作在用prompt做序列标注(template-NER,lightNER,template-free NER)
    还有一个问题是,不是所有标签都有明确的语义,verbalizer这边映射的label words都是有具体含义的,对于一些没有label语义的分类任务应该怎么办,比如用户评论的聚类等

img

Deep Prompt Tuning on NLU 采用Prefix-tuning的做法,在输入前面的每层加入可微调的参数

去掉重参数化的编码器
以前的方法利用重参数化功能来提高训练速度和鲁棒性(例如,用于prefix-tunning的 MLP 和用于 P-tuning的 LSTM)。在 P-tuning v2 中,作者发现重参数化的改进很小,尤其是对于较小的模型,同时还会影响模型的表现

可选的多任务学习
Deep Prompt Tuning的优化难题可以通过增加额外的任务数据或者无标注数据来缓解,同时可微调的prefix continuous prompt也可以用来做跨任务的共享知识。比如说,在NER中,可以同时训练多个数据集,不同数据集使用不同的顶层classifer,但是prefix continuous prompt是共享的回归传统的CLS和token label classifier
主要是为了解决一些没有语义的标签的问题

Lora

img

使用低秩矩阵结合在原始的权重矩阵,训练的时候只训练这些低秩矩阵

img

训练的时候固定原始PLM的参数,只训练降维矩阵A与升维矩阵B

选择要调整的权重矩阵:在大型模型(如GPT)中,我们首先确定要微调的权重矩阵。通常,这些矩阵位于模型的多头自注意力(Multi-head Self-Attention)和前馈神经网络(Feed-Forward Neural Network)部分。

引入两个低秩矩阵:接着,我们引入两个低秩矩阵,记为A和B,这两个矩阵的维度比原始权重矩阵小得多,例如,如果原始矩阵的尺寸是dd,那么,A和B的尺寸可能是dr和r*d,其中r是一个远小于d的数。

计算低秩更新:通过计算这两个低秩矩阵的乘积,生成一个新的矩阵AB,这个新矩阵的秩(即r)远小于原始权重矩阵的秩。这个乘积实际上是一个低秩近似,可以视为对原始权重矩阵的一种调整。

结合原始权重:最后,这个新生成的低秩矩阵AB被加到原始的权重矩阵上。这样,原始的权重矩阵得到了微调,但大部分权重保持不变。这个过程可以用数学公式表示为:新权重 = 原始权重 + AB。

QLoRA

img

img

LoRa为LLM的每一层添加了少量的可训练参数(适配器),并冻结了所有原始参数。这样对于微调,只需要更新适配器权重,这可以显著减少内存占用,而QLoRa更进一步,引入了4位量化、双量化和利用nVidia统一内存进行分页

该方法贡献为下面四点:

  • 4位NormalFloat量化:这是一种改进量化的方法。它确保每个量化仓中有相同数量的值。这避免了计算问题和异常值的错误
  • 双量化:QLoRa的作者将其定义如下“对量化常量再次量化以节省额外内存的过程。”
  • 统一内存分页:它依赖于NVIDIA统一内存管理,自动处理CPU和GPU之间的页到页传输,它可以保证GPU处理无错,特别是在GPU可能耗尽内存的情况下

reference

https://zhuanlan.zhihu.com/p/660721012

https://zhuanlan.zhihu.com/p/635848732

https://zhuanlan.zhihu.com/p/635686756

https://arxiv.org/abs/2110.07602

https://blog.csdn.net/weixin_43863869/article/details/134759033

如果对你有帮助就太好了)))