常见PEFT方法原理

·2232·5 分钟·
AI摘要: 本文讨论了在大规模通用数据集上训练的LLM模型微调方法,特别是如何通过适配器(Adapter)、前缀(Prefix)和引导词(Prompt)等方法来适应特定任务。特别介绍了微软提出的低秩自适应(LoRA)技术,该方法通过分解更新量矩阵为两个低秩矩阵的乘积来减少运算量,并取得了与全量微调相近的效果。文章还探讨了LoRA的具体原理、应用以及面临的挑战。

为什么要PEFT

目前LLM模型都非常大,且通常是在大规模通用数据集上训练的,如果想要迁移到特定领域来实现某些任务,就需要微调。在bert时代还能全量微调,在模型的输出末尾再加上一个输出层,然后用垂直领域的数据集重新训练。但是LLM时代的模型由于参数量过多,全量微调耗时昂贵。所以作为基座模型的LLM的权重参数不再更新,而是通过其他方法更新少量参数来适应特定任务。

有哪些方法

LLM的SFT方法通常如下:

  1. Adapter Tuning:设计一个Adapter结构嵌入到Transformer的每一层中,冻结住原来Transformer的参数,只更新Adapter结构的参数。一般Adapter的结构就是先降维、再非线性激活函数、最后升维,Adapter(x)=W2ReLU(W1x)Adapter(x)=W_2⋅ReLU(W_1⋅x)

  2. Prefix Tuning:为输入语句添加前缀的“引导词”来引导模型适应新的任务,只不过这里的“引导词”是一组随机可训练的向量,插入到模型的每一层输入中。具体而言,加入每一层的输入是[天, 气, 真, 好], 那么插入Prefix向量之后变成 [P1, P2, P3, 天, 气, 真, 好], 将这组向量当做每一层的输入。

  3. Prompt Tuning:和Prefix Tuning类似,用一组随机可训练的向量作为“引导词”, 但是Prompt引导词向量只作用在整个模型的第一次输入中,PrefixTuning是在模型的内部每一层中都作为输入

  4. LoRA:将模型的更新量矩阵分解成两个低秩矩阵的乘积,能够大幅减少运算量,后文将仔细描述。

上述方法中比较热门通用的就是微软提出的LoRA(Low-Rank Adaptation)。实验证明,LoRA能够取得与全量微调差不多的效果,可谓是四两拨千斤。

LoRA的具体原理

微调的本质就是参数沿着梯度方向更新,即W1=W0αWW_1 = W_0 - \alpha \nabla W , 我们记更新矩阵为ΔW\Delta W , 只要能够算出每次反向传播的ΔW\Delta W即可,那么对于一个大小为6B的LLM,ΔW\Delta W的参数量也为6B,这是难以接受的。

LoRA采用了近似方案,选择两个矩阵Ad×r,Br×k(r<<d,k)A_{d\times r}, B_{r\times k} (r << {d, k}) , 满足ΔW=Ad×rBr×k\Delta W = A_{d\times r} * B_{r \times k} , 此时A,BA, B的参数量之和为(d+k)r(d + k) * r , 原来的ΔW\Delta W的参数量为dkd*k, 参数量大大减少。

但是我们知道,能够进行低秩分解的矩阵终究是少数,所以LoRA的缺点就是表达能力欠佳

具体应用

由于Lora训练出来的参数非常少,可能就只有不到10MB的大小,因此常常用于模型的个性化适配。

  • 在图像生成diffusion model中,社区会分享出不同风格的lora参数,这样用户就能根据选择需要得到不同的图像生成风格。

  • 在大模型的生产环境中,我们往往希望为用户提供个性化模型,那么就可以尝试为不同用户单独训练lora参数,实现不同用户问答的时候给大模型套上它独有的lora参数。

代码实现


from transformers import AutoModelForCausalLM

from peft import get_peft_config, get_peft_model, LoraConfig, TaskType



model_name_or_path = "facebook/opt-350m"



peft_config = LoraConfig(

    task_type=TaskType.CAUSAL_LM,

    r=8, # 低秩

    lora_alpha=32, # 放缩因子

    lora_dropout=0.1,

)



model = AutoModelForCausalLM.from_pretrained(model_name_or_path)

model = get_peft_model(model, peft_config)

model.print_trainable_parameters()













LoraConfig中的 rrlora_alphalora\_alpha 在公式中为 W1=W0+lora_alpharΔW=W0+lora_alpharABW_1 = W_0 + \frac{lora\_alpha}{r} \Delta W = W_0 + \frac{lora\_alpha}{r} AB

lora_alpha 的选择:

  • 如果想要更激进的适应,设置 α > r

  • 如果想要更保守的适应,设置 α < r

  • 如果不确定,可以设置 α = r 作为起点

Kaggle学习赛初探