人工智能咨询培训老师叶梓 转载标明出处
大模型如BERT和GPT-3的参数数量庞大,动辄数十亿甚至数千亿级别,给进一步的微调和应用带来了巨大的挑战。针对这一问题,Vladislav Lialin、Vijeta Deshpande、Anna Rumshisky等研究者中提出了一系列参数高效微调(PEFT)的方法。旨在解决如何在不牺牲性能的前提下,减少对大模型进行微调时所需的计算资源和内存消耗。
论文链接:https://arxiv.org/pdf/2303.15647
方法分类
图2 为PEFT方法的分类,大致分为三类:加法(Additive methods)、选择法(Selective methods)和重参数化法(Reparametrization-based methods)。这些方法通过不同的策略来减少微调过程中需要更新的参数数量。
加法的核心思想是在现有的预训练模型中增加额外的参数或层,并且只训练这些新增加的参数。这是目前最大且被广泛探索的PEFT方法类别。图2在加法方法中,我们可以看到两个大的包含组:类似适配器的方法和软提示。
-
适配器(Adapters):适配器是一种加法参数高效微调方法,涉及在Transformer子层后引入小型全连接网络。这一想法已被广泛采用,并提出了多种适配器的变体,包括修改适配器的放置位置、剪枝和使用重参数化来减少可训练参数的数量。
-
软提示(Soft Prompts):语言模型提示旨在通过修改输入文本来控制语言模型的行为,这通常包括任务描述和一些上下文示例。然而,这些方法难以优化,并且由于模型的最大输入长度限制,训练示例的数量也受到限制。为了解决这些缺点,引入了“软”提示的概念,其中模型的部分输入嵌入通过梯度下降进行微调,将寻找离散空间中的提示问题转化为连续优化问题。
选择性PEFT的一个早期例子是只微调网络的少数顶层。现代方法通常基于层的类型或内部结构,例如只微调整模型的偏置或特定行。
重参数化方法利用低秩表示来最小化可训练参数的数量。这种方法在深度学习的经验性和理论分析中已被广泛探索。重参数化方法中较知名是LoRa,它使用简单的低秩矩阵分解来参数化权重更新。
另外一些方法结合了多种PEFT类别的思想我们称为混合方法 。例如,MAM适配器结合了适配器和提示调整。UniPELT将LoRa添加到混合中。Compacter和KronAB res通过重参数化适配器来减少它们的参数数量。
想要掌握如何将大模型的力量发挥到极致吗?叶老师带您深入了解 Llama Factory —— 一款革命性的大模型微调工具。9月22日晚,实战专家1小时讲解让您轻松上手,学习如何使用 Llama Factory 微调模型。
加助理微信提供直播链接:amliy007,29.9元即可参加线上直播分享,叶老师亲自指导,互动沟通,全面掌握Llama Factory,关注享粉丝福利,限时免费CSDN听直播后的录播讲解。
LLaMA Factory 支持多种预训练模型和微调算法。它提供灵活的运算精度和优化算法选择,以及丰富的实验监控工具。开源特性和社区支持使其易于使用,适合各类用户快速提升模型性能。
表1 为各种方法在存储、内存、反向传播和推理开销方面的特点。例如,适配器(Adapters)在存储和内存效率方面表现良好,但在反向传播时不会减少计算成本,并且在推理时引入了额外的全连接层(FFN)。而BitFit和DiffPruning等选择性方法在存储效率上表现不错,但可能在内存和计算效率方面不占优势。
存储效率关注的是模型在存储时所需的空间。DiffPruning方法虽然在存储上是高效的,因为它训练了一个与模型参数数量相同的二进制掩码,但在微调期间仍会产生相当的RAM和时间成本。
内存效率涉及模型在训练和推理期间占用的RAM量。加法方法通过减少梯度和优化器状态的大小来实现显著的内存效率提升。
计算效率着眼于模型在反向传播过程中的计算成本。例如,LoRa方法通过使用低秩矩阵分解来减少权重更新的参数数量,从而在计算上是高效的。
准确性是衡量模型在特定任务上的性能。尽管参数效率很重要,但最终目标是保持或提高模型的性能。
推理开销是指模型在实际应用中进行预测时所需的计算资源。一些方法可能在训练时参数效率高,但在推理时可能会引入额外的计算开销。
表2 汇总了不同模型大小的PEFT方法,并提供了一个简短的PyTorch伪代码实现,以展示算法的核心部分。
虽然这些方法在某些方面有所改进,但它们并不完全独立,一个维度上的改进并不必然导致另一个维度上的改进。因此,选择合适的PEFT方法需要根据具体的应用场景和资源限制来综合考虑。以下为各个方法详细介绍:
加法
适配器(Adapters)
适配器通常具有比输入更小的隐藏维度,并且已经证明可以通过调整不到模型总参数4%的数量来实现与完全微调相媲美的性能。表2 展示了适配器和其他PEFT方法在不同模型大小上的应用情况,以及它们的可训练参数数量。
表2 显示适配器在小于10亿、小于20亿和超过20亿参数的模型上都经过了评估,并且它们的可训练参数百分比在0.1%到6%之间变化。这表明适配器方法在不同大小的模型上都具有适用性。
一个适配器的实现示例如下:
def transformer_block_with_adapter(x):
residual = x
x = SelfAttention(x)
x = FFN(x) # adapter
x = LN(x + residual)
residual = x
x = FFN(x) # transformer FFN
x = FFN(x) # adapter
x = LN(x + residual)
return x
仅在自注意力层之后(即标准化之后)插入适配器,就可以达到每个Transformer块使用两个适配器的性能。
AdaMix是一种改进的适配器方法,它采用多位专家(MoE)的方式,每个适配器层是一组层(专家),并且每次前向传递只激活一小部分专家。与常规MoE不同,AdaMix随机选择单个专家,这减少了计算成本,并且据研究者称,不会降低性能。训练后,适配器权重会在专家之间平均,这使得推理更加内存高效。
AdaMix的一个实现示例如下:
def transformer_block_with_adamix(x):
residual = x
x = SelfAttention(x)
x = LN(x + residual)
residual = x
x = FFN(x)
# adamix starts here
x = random_choice(experts_up)(x)
x = nonlinearity(x)
x = random_choice(experts_down)(x)
x = LN(x + residual)
return x
def consistency_regularization(x):
logits1 = transformer_adamix(x) # second pass uses different experts
logits2 = transformer_adamix(x)
r = symmetrized_KL(logits1, logits2)
return r
软提示(Soft Prompts)
软提示方法在零样本和少样本场景中表现出色。“软”提示的概念提出是为了克服优化离散自然语言提示或使用上下文学习的不切实际性,将寻找最佳“硬”提示的离散优化问题转化为连续优化问题。
提示调整通过在模型输入嵌入前添加一个可训练的张量P来实现,这个张量被称为“软提示”,并且直接通过梯度下降进行优化。
与提示调整不同,前缀调整在所有层的隐藏状态前添加可训练参数。这种方法通过前馈网络对软提示进行参数化,优化后只需要保留前缀,可以丢弃FFN。
IPT方法通过自编码器来压缩和解压缩软提示,减少未见任务的参数数量。尽管IPT框架减少了未见任务的参数数量,但这需要训练自编码器,这可能会增加计算成本。
加法方法的其他方法
除了适配器和软提示,还有一些加法PEFT方法提出了增强预训练网络的新方法。
Ladder-Side Tuning (LST) LST在预训练网络的一侧训练一个小的Transformer网络,该侧网络结合了预训练骨干网络的隐藏状态和自己的隐藏状态。这种方法在训练期间只通过侧网络计算反向传播,从而节省了内存和计算资源。
(IA)³ (IA)³是一种新的参数高效微调方法,通过学习新参数来重新调整每个Transformer块的键、值和隐藏FFN激活。这种方法在T0-3B模型上只更新了约0.02%的模型参数,并且在参数数量相似的情况下,比其他方法表现得更好。
选择法
BitFit
BitFit 方法由 Ben-Zaken 等人于 2021 年提出,该方法只微调网络的偏置(biases)。对于每个线性或卷积层,保持权重矩阵 W 不变,只优化偏置向量 b。这种方法只更新了模型参数的约 0.05%,在数据量较少的情况下,能够在小于 10 亿参数的 BERT 模型上达到与完全微调相似或更好的性能。然而,在更大规模的网络中,如 T0-3B 或 GPT-3,BitFit 显著落后于完全微调和其他 PEFT 方法。
DiffPruning
DiffPruning 方法由 Guo 等人于 2020 年提出,旨在通过学习神经网络权重的稀疏更新来实现参数效率。该方法引入了一个可学习的二进制掩码,通过模型微调过程中的正则化目标来学习,这是对更新向量 δ 的 L0 范数的可微近似。DiffPruning 在小于 10 亿参数的场景中,修改了模型参数的 0.5%,达到了与完全微调相当的性能。这使得它成为边缘(移动)场景中多任务部署的有用方法,尤其是在存储受限的情况下。然而,这种方法在训练期间需要优化所有参数以及可学习的二进制掩码,因此比传统微调需要更多的内存。
Freeze and Reconfigure (FAR)
FAR 方法由 Vucetic 等人于 2022 年提出,选择要剪枝的参数矩阵列,并将线性层重新配置为可训练和冻结的部分。该方法分为两个阶段:首先,识别参数矩阵中最重要的行进行更新,类似于结构化剪枝。然后,通过将每个参数 W 分割为可训练部分 Wt 和冻结部分 Wf,对网络进行重新配置。这种方法在训练期间虽然增加了计算开销,但它提供了在现代硬件上使用标准框架(如 PyTorch)进行参数选择的灵活性。训练后,可以重新配置参数,消除任何推理开销。
FishMask
FishMask 方法由 Sung 等人于 2021 年提出,这是一种稀疏微调方法,根据模型参数的 Fisher 信息选择 top-p 参数进行优化。Fisher 信息通过对角近似估计,需要在数据的多个批次上计算所有参数的梯度。然而,一旦选择了最高 Fisher 信息的参数,就只需要优化这些参数。尽管 FishMask 在与适配器相当,但不如 LoRa 和 (IA)³ 方法。它已经在小于 10 亿参数的 BERT 和 T0-3B 模型上进行了评估。然而,由于缺乏对稀疏操作的支持,FishMask 在当代深度学习硬件上计算密集且效率低下。
重参数化法
Intrinsic SAID
Intrinsic SAID 方法由 Aghajanyan 等人于 2020 年提出,研究了微调的内在维度,并证明了这一过程可以在低秩子空间中进行。他们使用 Fastfood 变换来重新参数化模型权重的更新。Fastfood 是一种计算高效的维度扩展变换,可以在 O(D log d) 时间和 O(D) 内存内完成。研究结果表明,较大的模型与较小的模型相比,在实现相同微调性能时需要在更低秩的子空间中进行更改。
LoRa
LoRa 方法由 Hu 等人于 2021 年提出,从 Intrinsic SAID 中获得灵感,提出了一种更简单的低秩微调方法。在 LoRa 中,权重矩阵的参数更新被分解为两个低秩矩阵的乘积。所有预训练模型参数都保持冻结状态,只有 WA 和 WB 矩阵是可训练的。训练后,可以通过向原始矩阵 W 添加矩阵 WAWB 来将它们集成到原始 W 中。
KronA
KronA 方法由 Edalati 等人于 2022 年提出,用 Kronecker 乘积替换了 LoRa 中的矩阵分解 δW = WAWB。这提供了更好的秩与参数数量的权衡,因为 Kronecker 乘积保持了被乘矩阵的秩。KronA 方法在 GLUE 上的表现与适配器、LoRa 和 Compacter 相当或更好,同时在推理时间上显著快于适配器或 Compacter。
混合法
SparseAdapter
SparseAdapter 方法由 He 等人于 2022 年提出,采用了 Large-Sparse 策略来训练适配器层。在这种策略中,他们为添加的模块使用较大的隐藏维度,并在初始化时剪枝约 40% 的值。Large-Sparse 策略在保持相同可训练参数数量的情况下,始终优于其非稀疏对应物。然而,训练和推理成本可能会更高,这取决于硬件对稀疏张量和操作的支持。值得注意的是,计算此方法的剪枝掩码可能需要获取所有新添加参数的梯度。
MAM Adapters
He 等人于 2022 年对适配器位置和软提示进行了彻底的调查。他们得出结论,经过缩放的并行适配器优于顺序放置的适配器,并且放置在 FFN 并行的适配器优于多头注意力并行的适配器。他们还注意到,软提示可以通过仅改变 0.1% 的参数来有效修改注意力,并提出“混合匹配”(MAM)这些想法。他们的最终模型 MAM 适配器是 FFN 层的缩放并行适配器和软提示的结合。
def transformer_block_mam(x):
x = concat([x, soft_prompt], dim=seq)
residual = x
x = SelfAttention(x)
x = LN(x + residual)
x_a = FFN(x) # parallel adapter
x_a = scale * x_a
x = LN(x + x_adapter)
return x
MAM 方法在性能上大幅超越了 BitFit 和 Prompt Tuning,并且一直优于 LoRa、适配器和前缀调整方法。
UniPELT
UniPELT 方法由 Mao 等人于 2021 年提出,是 LoRa、前缀调整和适配器的门控组合。更具体地说,LoRa 重参数化用于 WQ 和 WV 注意力矩阵,前缀调整应用于每层的键和值,适配器添加在 Transformer 块的前馈层之后。对于每个模块,门控实现为将模块输入投影到大小为一的维度的线性层,sigmoid 激活,并在序列长度上平均得到的向量。可训练参数包括 LoRa 矩阵 WA、WB、提示调整参数 Pq、Pk、适配器参数和门控函数权重。
def transformer_block_mam(x):
x = concat([x, soft_prompt], dim=seq)
residual = x
x = SelfAttention(x)
x = LN(x + residual)
x_a = FFN(x) # parallel adapter
adapter_gate = gate(x)
x_a = scale * x_a
x = LN(x + x_adapter)
return x
UniPELT 在只有 100 个样本的低数据场景中,表现出比单独的 LoRa、适配器和前缀调整方法显著的改进。在更高数据场景中,UniPELT 的性能与这些方法相当或更好。
Compacter
Compacter 方法由 Karimi Mahabadi 等人于 2021 年提出,利用 Kronecker 乘积、低秩矩阵和跨层参数共享来产生适配器权重。每个适配器中的参数 W 等于 Kronecker 乘积的和。这种参数化的线性层 xW + b 被称为参数化超复数乘法(PHM)层。Compacter 进一步采用这种思想,将 Bi 参数化类似于 LoRa,其中所有矩阵的秩最多为 r。Ai 矩阵在所有适配器层中共享,以进一步参数效率。
def compacter(x):
x = LPHM(x) # Essentially an FFN
x = gelu(x) # but
x = LPHM(x) # LPHM replaces linear
return x
Compacter 有两种变体:每个 Transformer 块两个适配器或单个适配器在前馈层之后。Compacter++ 仅使用 0.05% 的额外参数,性能与具有 0.8% 额外参数的适配器相当或更好。
S4
S4 方法由 Chen 等人于 2023 年提出,对各种参数高效微调技术的不同组合进行了广泛探索。他们的方法 S4 将层分为四个组(G1,2,3,4),使用“纺锤”模式:更多层分配给中间组,更少层分配给顶部和底部组。所有组都是可训练的,可训练参数均匀分配在层(非组)上。不同组应用不同的 PEFT 方法组合。
比较问题与最佳实践
在参数高效微调(PEFT)方法研究中存在一些挑战和不一致性,这些问题让直接比较不同方法的性能较为困难。其中主要的挑战来自于研究者报告参数计数方式的差异。这些不一致是问题的固有复杂性所致。通常,参数计数可以分为三种类型:可训练参数的数量、原始模型和微调模型之间变化的参数数量,以及原始和微调模型之间差异的秩。例如,Intrinsic SAID 方法学习模型参数的低秩(约100-1000)变换,但它改变了所有模型参数。而 DiffPruning 方法学习了0.5%参数的更新,但实际上训练了200%的参数:微调模型和学习二进制掩码。对于基于重参数化的方法,内存需求可能会根据实现设计选择而变化。
评估PEFT方法时使用的模型大小的变化带来了另一个挑战。较大的模型在微调期间需要更新的参数较少,无论是在百分比上还是在模型足够大时,有时甚至在绝对数量上。因此,在比较PEFT方法时,不仅要考虑可训练参数的比率,还要考虑模型大小。
缺乏标准基准和指标使得比较变得更加复杂。新方法通常在不同的模型/数据集组合上进行评估,这使得得出有意义的结论变得具有挑战性。例如,KronA 在GLUE基准上评估了T5-base,并在保持相同数量的可训练参数的同时报告了准确性、训练时间和推理时间。UniPELT 在GLUE基准上评估了BERT,并报告了准确性、训练时间和推理延迟,尽管它对各种方法使用了不同的参数计数。LST 在GLUE基准上评估了不同大小的T5,并报告了准确性、训练时间、更新参数的数量和内存使用情况。尽管如此,这些论文由于评估设置的差异,如变化的参数计数或缺少某些指标(如内存比较)而缺乏完全的可比性。
遇到的另一个问题是发布实现的状态。许多代码库只是Transformers库或其他存储库的副本,只进行了微小的修改。这些副本通常不使用git分支,除非在README文件中突出显示,否则很难识别差异。即使差异容易找到,代码通常也不可重用。用户通常需要安装Transformers库的修改版本,这与最新版本冲突,并且缺乏文档或如何在现有代码库之外重用方法的示例。
为了解决参数高效微调文献中识别的不同问题,提出以下最佳实践:
- 明确报告参数计数类型:鼓励作者在论文中明确指定报告的参数计数,或者理想情况下,报告所有三种类型的参数计数:可训练的、变化的和秩。
- 使用不同模型大小进行评估:使用不同模型大小评估方法很重要,因为这可以更全面地了解每种方法的优势和局限性。
- 与类似方法进行比较:除了将方法与流行的方法(如LoRa、BitFit、Adapters)进行比较外,还应该将方法与在概念和架构上具有相似性其他技术一起分析。
- 标准化PEFT基准和竞赛:提议开发标准化的PEFT基准和竞赛,这将要求参与者在相同条件下竞争,促进结果的直接比较。
- 强调代码清晰和最小实现:优先考虑易于理解且具有简单、可重用实现的代码。在某些情况下,这样的实现为论文提供了额外的见解,并且可以以简洁的方式编写。易于重用的方法可能会变得更受欢迎,因此被更多引用。
以上研究者们希望能够推动大型语言模型的进一步发展和应用,使其在资源有限的环境中也能发挥出强大的能力。