常见PEFT方法原理
AI摘要: 本文讨论了在大规模通用数据集上训练的LLM模型微调方法,特别是如何通过适配器(Adapter)、前缀(Prefix)和引导词(Prompt)等方法来适应特定任务。特别介绍了微软提出的低秩自适应(LoRA)技术,该方法通过分解更新量矩阵为两个低秩矩阵的乘积来减少运算量,并取得了与全量微调相近的效果。文章还探讨了LoRA的具体原理、应用以及面临的挑战。
为什么要PEFT
目前LLM模型都非常大,且通常是在大规模通用数据集上训练的,如果想要迁移到特定领域来实现某些任务,就需要微调。在bert时代还能全量微调,在模型的输出末尾再加上一个输出层,然后用垂直领域的数据集重新训练。但是LLM时代的模型由于参数量过多,全量微调耗时昂贵。所以作为基座模型的LLM的权重参数不再更新,而是通过其他方法更新少量参数来适应特定任务。
有哪些方法
LLM的SFT方法通常如下:
-
Adapter Tuning:设计一个Adapter结构嵌入到Transformer的每一层中,冻结住原来Transformer的参数,只更新Adapter结构的参数。一般Adapter的结构就是先降维、再非线性激活函数、最后升维,
-
Prefix Tuning:为输入语句添加前缀的“引导词”来引导模型适应新的任务,只不过这里的“引导词”是一组随机可训练的向量,插入到模型的每一层输入中。具体而言,加入每一层的输入是
[天, 气, 真, 好]
, 那么插入Prefix向量之后变成[P1, P2, P3, 天, 气, 真, 好]
, 将这组向量当做每一层的输入。 -
Prompt Tuning:和Prefix Tuning类似,用一组随机可训练的向量作为“引导词”, 但是Prompt引导词向量只作用在整个模型的第一次输入中,PrefixTuning是在模型的内部每一层中都作为输入
-
LoRA:将模型的更新量矩阵分解成两个低秩矩阵的乘积,能够大幅减少运算量,后文将仔细描述。
上述方法中比较热门通用的就是微软提出的LoRA
(Low-Rank Adaptation)。实验证明,LoRA
能够取得与全量微调差不多的效果,可谓是四两拨千斤。
LoRA的具体原理
微调的本质就是参数沿着梯度方向更新,即 , 我们记更新矩阵为 , 只要能够算出每次反向传播的即可,那么对于一个大小为6B
的LLM,的参数量也为6B,这是难以接受的。
LoRA采用了近似方案,选择两个矩阵 , 满足 , 此时的参数量之和为 , 原来的的参数量为, 参数量大大减少。
但是我们知道,能够进行低秩分解的矩阵终究是少数,所以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
中的 和 在公式中为
lora_alpha 的选择:
-
如果想要更激进的适应,设置 α > r
-
如果想要更保守的适应,设置 α < r
-
如果不确定,可以设置 α = r 作为起点