一文略解参数有效性微调

Intro

参数有效性微调(PEFT)是一种在自然语言处理(NLP)领域中广泛使用的技术,它可以在不牺牲性能的情况下,大大减少微调预训练语言模型(PLM)所需的参数数量和计算资源。PEFT的主要动机是解决PLM规模不断增长所带来的挑战,例如显存限制、训练时间过长、通信开销过大等。PEFT的目标是在保持或提高PLM在下游任务上的表现的同时,降低微调过程中的参数更新量和梯度传播量。

PEFT的方法可以分为四大类:附加法(Additive)、选择法(Selective tuning)、重参数化法(Reparameterization-based)和混合(Mix)法。附加法是指在PLM的结构中添加一些额外的可训练参数或层,例如适配器(adapter)或软提示(soft prompt),并只更新这些新增加的参数。选择法是指只更新PLM中的一部分参数,例如最上层、偏置项或稀疏选择的参数。重参数化法是指使用低秩或其他形式的表征来重新参数化PLM的权重更新,从而减少可训练参数的数量。混合法是指结合了以上多种方法的思想,例如同时使用适配器和提示微调,或者对适配器做重参数化。

本文将对PEFT的各种方法进行详细的介绍和比较,分析它们各自的优缺点和适用场景,并给出一些实际应用的案例和代码示例。本文旨在为读者提供一个全面而深入的PEFT指南,帮助读者理解、选择和使用PEFT技术来优化PLM。

Method

本节依次介绍selective tuning、Additive Tuning、Reparameterization-based,Mix method。以下将为每种方法选择一至两个案例进行介绍。

Selective Tuning 

本方法旨在不改变模型的参数,在训练时,仅微调模型的部分参数,冻结模型的大部分参数。此方法不会引入额外的参数,同时微调模型部分参数,对模型原始的性能影响较小。

BitFit

bitfit一种仅仅微调模型中bias的方法。下面给出伪代码实现。

params = (p for n, p in model.named_parameters() if "bias" in n)
optimizer = Optimizer(params)

Additive Tuning

这种方法通过引入额外的参数,这种额外的引入的参数可能是一些额外的网络层或者是与额外的计算参数。通过仅仅微调少量的参数,从而使得模型可以更好地适应下游任务。

Adapter

适配器是一种通过引入额外网络层,来对模型进行参数有效性微调的方法。这种方法比较灵活多变,可以通过在原始模型中间插入额外的网络或者在原始网络并行地引入副网络。下面给出这两种方法的实现。

"""
adapter:adapter可以是任何的网络结构,比如transformer或者低秩矩阵
"""
def sequential_adapter(adapter):
    x = block1(x)
    x = adapter(x)
    x = block2(x)
    return x


def parallel_adapter(adapter):
    x = block1(x)
    residual = x
    x1 = block2(x)
    x2 = adapter(residaul)
    return x1 + x2

Prefix tuning(p tuningv2)

prefix tuning顾名思义是对前缀进行调优,即句子前面的token表征。但是其在实现过程上是有难度的,所以这里引入了新的参数作为前缀进行调优。在训练时,仅训练新引入的token参数。

def embed_mlp(nn.Module):
    """prefix网络及参数"""
    def __init__(self, pre_len):
        super().__init__()
        self.embed = nn.Embedding(pre_len,128)
        self.linear1 = nn.Linear(128, 256)
        self.linear2 = nn.Linear(256, 128)
    
    def forward(self, x):
        """x = [0,1,2,3,4,5,6,7,8,9]"""
        x = self.embed(x)
        x = self.linear1(x)
        return self.linear2(x)
        

def prefix_tuning(embed_mlp):
    
    for block in transformer:
        ...        
        q = q
        k = concat(k, embed_bilstm)
        v = concat(v, embed_bilstm)
        x = selfattention(q, k, v)
    return x

Reparameterization-based

这种方法的核心思想是使用低秩矩阵来重参数化模型网络权重的方法,简单点来说是保证模型参数不动,通过引入新的网络层来对网络参数进行优化。

Lora

直接看代码

class Lora(nn.Module):
    """低秩矩阵"""
    def __init__(self,d_model, bottleneck_dim,scale = 1.00):
        super().__init__()

        self.down_proj = torch.nn.Parameter(torch.zeros(d_model, bottleneck_dim))
        self.up_proj = torch.nn.Parameter(torch.zeros(bottleneck_dim, d_model))
        
        nn.init.kaiming_uniform_(self.down_proj, a = math.sqrt(5))
        nn.init.zeros_(self.up_proj)

    def forward(self, x): 
        return x @ self.down_proj @ self.up_proj


def Lora_Reparameterization(Lora):
    """lora是不相同的多个实例化低秩矩阵"""
    for block in transformer:
        ...        
        q = query(x) + Lora(x)
        k = key(x) + Lora(x)
        v = value(x)
        x = selfattention(q, k, v)
    return x

Mix

mix方法简单来说就是对各种不同的方法进行组合,没什么好说的。

Comparisons

Method

extra parameter

compute efficiency

inference efficiency

anti-forgetting

performance

lora

2

1

1

1

2

prefix tuning

3

2

4

1

3

parallel adapter

4

3

1

3

4

full params

1

4

1

4

1

猜你喜欢

转载自blog.csdn.net/qq_38901850/article/details/132475078