大模型LLM | 参数高效微调-Prefix Tuning、Adapter Tuning、LoRA

一、Prefix Tuning

在这里插入图片描述

在prefix-tuning之前的工作主要是人工设计离散的template或者自动化搜索离散template,问题在于最终的性能对人工设计的template的特别敏感:加一个词或者少一个词,或者变动位置,都会造成很大的变化,所以这种离散化的token的搜索出来的结果可能并不是最优的。

Prefix Tuning方法使用连续的virtual token embedding来代替离散的token,且与Full-finetuning更新所有参数的方式不同。简而言之就是Prefix Tuning在原始文本进行词嵌入之后,在前面拼接上一个前缀矩阵,或者将前缀矩阵拼在模型每一层的输入前。

Prefix Tuning相关设置:

  • 前缀初始化时,[前缀长度, 嵌入维度],其中嵌入维度与模型词嵌入的维度相同。前缀长度可以根据任务需求进行调整。

  • 更长的前缀意味着更多的可微调参数,效果也变好,不过长度还是有阈值限制的(table-to-text是10,summarization是200)

(上):针对表格描述(Table-to-text)、文章总结(Summarization)、翻译(Translation)三种任务,Fine-Tuning需微调三个LM,且需保存每个特定任务的LM参数,臃肿和低效;(下):然而,Prefix Tuning要清爽得多,针对三类任务,只需训练三个Prefix生成器,原LM参数可直接复用。

推理阶段,只需要将任务相关的输入序列与训练好的前缀嵌入进行拼接,然后输入到模型中即可得到预测结果。

代码过程,下面这个类旨在将输入的前缀有效地编码为适合后续处理的向量形式。

参考:https://github.com/THUDM/P-tuning-v2/blob/main/model/prefix_encoder.py

import torch


class PrefixEncoder(torch.nn.Module):
    r'''
    The torch.nn model to encode the prefix

    Input shape: (batch-size, prefix-length)

    Output shape: (batch-size, prefix-length, 2*layers*hidden)
    '''
    def __init__(self, config):
        super().__init__()
        self.prefix_projection = config.prefix_projection
        if self.prefix_projection:
            # Use a two-layer MLP to encode the prefix
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.hidden_size)
            self.trans = torch.nn.Sequential(
                torch.nn.Linear(config.hidden_size, config.prefix_hidden_size),
                torch.nn.Tanh(),
                torch.nn.Linear(config.prefix_hidden_size, config.num_hidden_layers * 2 * config.hidden_size)
            )
        else:
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.num_hidden_layers * 2 * config.hidden_size)

    def forward(self, prefix: torch.Tensor):
        if self.prefix_projection:
            prefix_tokens = self.embedding(prefix)
            past_key_values = self.trans(prefix_tokens)
        else:
            past_key_values = self.embedding(prefix)
        return past_key_values

二、Adapter Tuning

通过引入少量可训练参数(适配器模块)来进行特定任务的优化。适配器模块是一组轻量级的参数,被添加到模型的中间层,以保护原有预训练模型的参数。这种方法的目标是在不改变整体模型结构的情况下,通过调整适配器模块的参数来适应新任务。

在这里插入图片描述

Adapter Tuning针对Transformer的添加方式。左:针对每个Transformer层,Adapter参数在两个残差前插入。在Tuning中,图中的绿色模块是可训练的,其他模块的参数固定。

Adapter Tuning的核心思想是在预训练模型的中间层中插入小的可训练层或“适配器”。这些适配器通常包括一些全连接层、非线性激活函数等,它们被设计用来捕获特定任务的知识,而不需要对整个预训练模型进行大规模的微调。

下面举个例子看下Adapter Tuning过程:

Adapters还可以和HuggingFace的Transformer包无缝整合,可以直接加载HuggingFace上的模型进行Adapter微调。

以文本分类为例,BERT预训练模型加载:

from transformers import AutoTokenizer, AutoConfig
from adapters import AutoAdapterModel
 
model_path = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_path)
config = AutoConfig.from_pretrained(model_path, num_labels=3)
model = AutoAdapterModel.from_pretrained(model_path, config=config)

然后为预训练模型设置适配器。这里需要注意,在Adapters包里,本节所介绍的适配器结构被称为瓶颈适配器(Bottleneck adapters)(如上图1),使用BnConfig类来配置。这里需要为适配器取一个名字,之后可以通过这个名字来激活或者禁用这个适配器。

from adapters import BnConfig

adapter_name = "trouble_shooting"
# 添加一个新的adapter,类型为Bn adapter,即bottleneck adapter
config = BnConfig(mh_adapter=True, output_adapter=True, reduction_factor=16, non_linearity="relu")

model.add_adapter(adapter_name, config=config)
# 添加一个分类头
model.add_classification_head(adapter_name,num_labels=3, activation_function="relu")
# 激活这个adapter
model.train_adapter(adapter_name)

主要参数:

  • mh_adapter:设置是否要在多头注意力模块之后添加适配器。
  • output_adapter:设置是否要在Transformer模块的输出层添加适配器。
  • reduction_factor:模型参数量与需调整的适配器参数量的比值。
  • non_linearity:设置非线性部分使用的激活函数。

trainer训练模型:

from transformers import TrainingArguments
from adapters import AdapterTrainer
training_args = TrainingArguments(
    num_train_epochs=5,
    per_device_train_batch_size = 16,
    logging_steps=2,
    save_steps = 10,
    gradient_accumulation_steps = 4,
    output_dir="bert-adapter",
)
 
trainer = AdapterTrainer (
model=model, tokenizer=tokenizer
args=training_args, train_dataset=train_dataset,
    optimizers=(optimizer, None)
)
trainer.train() # 开始训练
trainer.save_model() # 保存训练好的模型

三、LoRA

矩阵的秩(Rank):衡量了矩阵中行或列向量的线性无关性

低秩:秩远小于矩阵的行数或列数。

在这里插入图片描述

LoRA(Low-Rank Adaptation)假设模型在任务适配过程中权重的改变量可以是低秩的。 LoRA通过在预训练模型中引入一个额外的线性层(由低秩矩阵A和B组成),并使用特定任务的训练数据来微调这个线性层,从而实现对模型的高效微调。

假设预训练参数为,那么全量微调时的更新量自然也 是一个矩阵,LoRA将更新量约束为低秩矩阵来降低训练时的参数量,即设,其中以及,用新的替换模型原参数,并固定不变,只训练,如下图所示:

在这里插入图片描述

为了使得LoRA的初始状态跟预训练模型一致,通常会将之一全零初始化,这样可以得到,那么初始的就是。但这并不是必须的,如果都是非全零初始化,那么我们只需要将设置为

也就是说将固定不变的权重从换为,同样可以满足初始等于这一条件。

影响LoRA微调的相关参数如下:

  1. 秩(Rank)

    参数:lora_rank

    描述:秩是LoRA中最重要的参数之一,它决定了低秩矩阵的维度。秩的大小直接影响模型的性能和训练时间。

    常用值:对于小型数据集或简单任务,秩可以设置为1或2;对于更复杂的任务,秩可能需要设置为4、8或更高。

  2. 缩放系数(Alpha)

    参数:lora_alpha

    描述:缩放系数用于在训练开始时对低秩矩阵的更新进行缩放,以确保训练过程的稳定性。

    常用值:缩放系数的具体值取决于秩的大小和任务的复杂度。

  3. Dropout系数

    参数:lora_dropout

    描述:Dropout是一种正则化技术,用于防止模型过拟合。在LoRA Fine-tuning中,Dropout系数决定了在训练过程中随机丢弃低秩矩阵中元素的概率。

    常用值:Dropout系数的常用值范围在0到1之间,具体值取决于模型的复杂度和数据的规模。

  4. 学习率

    参数:learning_rate

    描述:学习率决定了模型在训练过程中权重更新的步长。适当的学习率可以帮助模型在训练过程中更快地收敛到最优解。

    常用值:学习率的具体值取决于多个因素,包括模型的复杂度、数据的规模以及训练过程中的其他超参数设置。

LoRA微调如今是高效微调LLM的重要手段,PEFT库也集成了相关方法: PEFT库:https://github.com/huggingface/peft

参考文献
Prefix-Tuning: Optimizing Continuous Prompts for Generation
Parameter-Efficient Transfer Learning for NLP
LoRA: Low-Rank Adaption of Large Language Models


如何学习大模型?

学习AI大模型是一个系统的过程,需要从基础开始,逐步深入到更高级的技术。

这里给大家精心整理了一份全面的AI大模型学习资源,包括:AI大模型全套学习路线图(从入门到实战)、精品AI大模型学习书籍手册、视频教程、实战学习、面试题等,资料免费分享!

1. 成长路线图&学习规划

要学习一门新的技术,作为新手一定要先学习成长路线图方向不对,努力白费

这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。
在这里插入图片描述

2. 大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

在这里插入图片描述

3. 大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

在这里插入图片描述

4. 大模型项目实战

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

在这里插入图片描述

5. 大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

在这里插入图片描述

全套的AI大模型学习资源已经整理打包,有需要的小伙伴可以微信扫描下方CSDN官方认证二维码,免费领取【保证100%免费

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值