模型微调方法Adapter

简介:个人学习分享,如有错误,欢迎批评指正。

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

  1. 残差连接(Residual Connection)
  • Adapter模块的输出与输入通过残差连接相加,确保原始特征能够直接传递,避免信息丢失。
  1. 归一化层(Layer Normalization)(可选):
  • 在某些实现中,Adapter模块前后会加入LayerNorm,以稳定训练过程。

2. Adapter模块的数学表示

设输入为 x ∈ R d m o d e l x \in \mathbb{R}^{d_{model}} xRdmodel,则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σ(Wdownx)

其中:

  • 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}} WdownRdbottleneck×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}} WupRdmodel×dbottleneck上采样矩阵

3. Adapter与Transformer架构的集成

为了更好地理解Adapter在Transformer架构中的集成,以下以BERT为例进行说明:

  1. Transformer层的组成

    • 每个Transformer层包括多头自注意力机制和前馈神经网络(Feed-Forward Network)。
  2. 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模块对自注意力机制的输出进行调整,使其更适应特定任务。
  3. 多头注意力与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}} WdownLandWupL

3.3 反向传播中的梯度计算

考虑Adapter模块的前向传播:

a = W d o w n ⋅ x \mathbf{a} = W_{down} \cdot \mathbf{x} a=Wdownx

b = σ ( a ) \mathbf{b} = \sigma(\mathbf{a}) b=σ(a)

c = W u p ⋅ b \mathbf{c} = W_{up} \cdot \mathbf{b} c=Wupb

y = x + c \mathbf{y} = \mathbf{x} + \mathbf{c} y=x+c

在反向传播过程中,假设损失对输出的梯度为 ∂ L ∂ y \frac{\partial \mathcal{L}}{\partial \mathbf{y}} yL,则梯度计算如下:

  1. 梯度传播到 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 WupL=yLbT

  2. 梯度传播到 W d o w n W_{down} Wdown

    首先,计算 ∂ L ∂ b \frac{\partial \mathcal{L}}{\partial \mathbf{b}} bL

    ∂ 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}} bL=WupTyL

    上一篇:牛客编程初学者入门训练——BC53 判断是元音还是辅音


    下一篇:面向对象彻底性、权限访问、垃圾回收