简介:个人学习分享,如有错误,欢迎批评指正。
Adapter是一种高效的微调方法,旨在在保持大型预训练模型(如BERT、GPT等)核心参数不变的情况下,通过添加小型可训练模块(称为“Adapter层”)来适应特定下游任务。这种方法在参数效率和灵活性方面具有显著优势,尤其适用于资源受限的环境或需要同时适应多个任务的场景。
背景与动机
随着预训练语言模型规模的不断扩大,直接对整个模型进行微调变得计算资源消耗巨大,且不易于在多任务或多领域中复用。传统微调方法需要为每个下游任务保存一套完整的模型参数,这在存储和管理上带来了挑战。为了解决这一问题,Adapter方法应运而生,通过仅添加少量参数来实现高效的任务适应。
一. Adapter的设计理念
在深度学习中,特别是自然语言处理(NLP)领域,预训练模型如BERT、GPT等因其强大的表示能力被广泛应用。然而,随着模型规模的增大,直接对整个模型进行微调(即调整所有参数以适应特定任务)变得既计算资源消耗巨大,又不利于多任务或多领域的模型复用。
Adapter方法的核心理念是通过在预训练模型中插入小型、可训练的模块(即Adapter层)
,在保持原有预训练参数不变的情况下,实现对特定任务的适应。这种方法极大地提高了参数效率,减少了存储需求,并且支持多任务学习。
二. Adapter的组件结构
一个典型的Adapter模块通常由以下几个部分组成:
1. 瓶颈层(Bottleneck Layer):
-
下采样(Down-Projection):将输入特征从高维空间映射到低维空间,以减少参数量和计算复杂度。通常使用一个
全连接层
实现,参数矩阵维度为 d m o d e l × d b o t t l e n e c k d_{model} \times d_{bottleneck} dmodel×dbottleneck。 -
非线性激活函数(Non-linear Activation):常用的激活函数包括ReLU、GELU等,用于增加模型的非线性表达能力。
-
上采样(Up-Projection):将低维特征映射回高维空间,与输入特征进行融合。通常也是一个
全连接层
,参数矩阵维度为 d b o t t l e n e c k × d m o d e l d_{bottleneck} \times d_{model} dbottleneck×dmodel。
- 残差连接(Residual Connection):
- Adapter模块的输出与输入通过残差连接相加,确保原始特征能够直接传递,避免信息丢失。
- 归一化层(Layer Normalization)(可选):
- 在某些实现中,Adapter模块前后会加入LayerNorm,以稳定训练过程。
2. Adapter模块的数学表示
设输入为 x ∈ R d m o d e l x \in \mathbb{R}^{d_{model}} x∈Rdmodel,则Adapter模块的输出可以表示为:
A d a p t e r ( x ) = x + W u p ⋅ σ ( W d o w n ⋅ x ) Adapter(x) = x + W_{up} \cdot \sigma(W_{down} \cdot x) Adapter(x)=x+Wup⋅σ(Wdown⋅x)
其中:
-
W
d
o
w
n
∈
R
d
b
o
t
t
l
e
n
e
c
k
×
d
m
o
d
e
l
W_{down} \in \mathbb{R}^{d_{bottleneck} \times d_{model}}
Wdown∈Rdbottleneck×dmodel 是
下采样矩阵
。 - σ \sigma σ 是非线性激活函数,如ReLU。
-
W
u
p
∈
R
d
m
o
d
e
l
×
d
b
o
t
t
l
e
n
e
c
k
W_{up} \in \mathbb{R}^{d_{model} \times d_{bottleneck}}
Wup∈Rdmodel×dbottleneck 是
上采样矩阵
。
3. Adapter与Transformer架构的集成
为了更好地理解Adapter在Transformer架构中的集成,以下以BERT为例进行说明:
-
Transformer层的组成:
- 每个Transformer层包括多头自注意力机制和前馈神经网络(Feed-Forward Network)。
-
Adapter的插入位置:
- Adapter模块通常插入在自注意力机制之后、前馈网络之前。具体流程如下:
Attention Output = Self-Attention ( Q , K , V ) \text{Attention Output} = \text{Self-Attention}(Q, K, V) Attention Output=Self-Attention(Q,K,V)
Adapter Output = Adapter ( Attention Output ) \text{Adapter Output} = \text{Adapter}(\text{Attention Output}) Adapter Output=Adapter(Attention Output)
FFN Output = Feed-Forward ( Adapter Output ) \text{FFN Output} = \text{Feed-Forward}(\text{Adapter Output}) FFN Output=Feed-Forward(Adapter Output)
Layer Output = FFN Output \text{Layer Output} = \text{FFN Output} Layer Output=FFN Output
- 这样,Adapter模块对自注意力机制的输出进行调整,使其更适应特定任务。
-
多头注意力与Adapter的交互:
- 在多头注意力机制中,每个注意力头独立处理不同的子空间表示。
Adapter模块
在这种情况下处理的是合并后的多头输出,使其适应整体任务需求
。
- 在多头注意力机制中,每个注意力头独立处理不同的子空间表示。
三. Adapter的工作机制
Adapter模块通过两个线性变换和一个非线性激活函数,可以近似任何非线性映射(根据通用函数逼近定理)。因此,尽管Adapter模块参数量较少,但其在特征空间中的变换能力仍然强大,足以适应多种任务。
Adapter的工作机制主要包括以下几个步骤:
1. 插入位置:
- Adapter模块通常被
插入到预训练模型的每个Transformer层
中,具体位置可以是自注意力层(Self-Attention)之后,前馈网络(Feed-Forward Network)之前
,或其它适合的位置。选择插入位置取决于具体任务和模型架构。
2. 前向传播:
-
当输入通过Transformer层时,经过自注意力机制和前馈网络处理后,Adapter模块对中间表示进行调整。
-
具体来说,
输入特征先经过下采样映射到低维空间,通过激活函数进行非线性变换,随后再通过上采样映射回高维空间,最后与原始输入特征进行残差连接
。
3. 参数更新:
3.1 冻结预训练模型参数
在Adapter微调过程中,预训练模型的所有参数
(例如Transformer层中的权重矩阵和偏置)均保持冻结状态
,不参与梯度更新。只有Adapter模块中的参数
W
d
o
w
n
W_{down}
Wdown 和
W
u
p
W_{up}
Wup 需要进行训练。
3.2 损失函数与梯度更新
假设任务的损失函数为 L L L,则整个模型的损失函数可以表示为:
L = Loss ( Model with Adapters ( x ) , y ) \mathcal{L} = \text{Loss}(\text{Model with Adapters}(\mathbf{x}), \mathbf{y}) L=Loss(Model with Adapters(x),y)
由于预训练模型的参数被冻结,梯度只需计算相对于Adapter参数:
∂ L ∂ W d o w n and ∂ L ∂ W u p \frac{\partial \mathcal{L}}{\partial W_{down}} \quad \text{and} \quad \frac{\partial \mathcal{L}}{\partial W_{up}} ∂Wdown∂Land∂Wup∂L
3.3 反向传播中的梯度计算
考虑Adapter模块的前向传播:
a = W d o w n ⋅ x \mathbf{a} = W_{down} \cdot \mathbf{x} a=Wdown⋅x
b = σ ( a ) \mathbf{b} = \sigma(\mathbf{a}) b=σ(a)
c = W u p ⋅ b \mathbf{c} = W_{up} \cdot \mathbf{b} c=Wup⋅b
y = x + c \mathbf{y} = \mathbf{x} + \mathbf{c} y=x+c
在反向传播过程中,假设损失对输出的梯度为 ∂ L ∂ y \frac{\partial \mathcal{L}}{\partial \mathbf{y}} ∂y∂L,则梯度计算如下:
-
梯度传播到 W u p W_{up} Wup:
∂ L ∂ W u p = ∂ L ∂ y ⋅ b T \frac{\partial \mathcal{L}}{\partial W_{up}} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}} \cdot \mathbf{b}^T ∂Wup∂L=∂y∂L⋅bT
-
梯度传播到 W d o w n W_{down} Wdown:
首先,计算 ∂ L ∂ b \frac{\partial \mathcal{L}}{\partial \mathbf{b}} ∂b∂L:
∂ L ∂ b = W u p T ⋅ ∂ L ∂ y \frac{\partial \mathcal{L}}{\partial \mathbf{b}} = W_{up}^T \cdot \frac{\partial \mathcal{L}}{\partial \mathbf{y}} ∂b∂L=WupT⋅∂y∂L