大模型技术飞速发展,像Rag、Agent以及Moe等,1月份抽空看了蛮多大模型的博客和论文,感觉知识点太多了并且更新速度也贼快,后续就慢慢进行总结输出。这篇文章主要主要围绕ptuning v2、lora、qlora以及全量微调等方法进行介绍,末尾也会分享自己参加的相关大模型比赛的微调心得总结以及一些学习的参考。
大模型的基础概念
大模型的训练主要包括预训练阶段、指令微调阶段以及强化学习阶段。不过最近刷到过论文或者博客文章提到,通过高质量的有监督微调数据训练大模型,即使不进行强化学习阶段,也能模仿人类进行输出。预训练阶段,通常是在大量的无标签数据上进行训练,其目的是给模型注入丰富的知识,通常也被称作为基座模型(Base Model)。训练一个好的基座模型一定程度上决定了微调模型的效果,打好下层建筑是很重要的。指令微调阶段, 可以使用训练好的基座模型在对应的任务数据上做进一步迁移训练,以其让模型适应该任务,往往只需要几个epoch的微调即可。
大模型微调的方法
全量微调。 在chatgpt出来之前,像bert、bart这些轻量级的预训练模型,通常是进行全量微调,也就是直接对模型的所有层进行训练以及参数调参,通过一张3090或者4090的显卡就能够轻松训练。然而对于大模型的全量微调,普通的消费级显卡则是很难满足训练的显存需求以及训练速度,一般都得A100 80G的显卡起步,才能达到较快的速度微调出结果。当然也可以通过多张24G 显卡并行来训练大模型,但训练速度可能会比较慢,推理速度就更慢了。
ptuning v2微调。 在了解ptuning v2微调之前,可以先简单了解一下prefix tuning以及ptuning这两种微调方法,这样就更能够明白ptuning v2的精髓。当然在这些方法之前,还有一个人工构造离散模版,也就是设置一句话与数据一起输入到模型中,然后起到提示模型生成对应结果的作用。然而人工构建的离散模版会导致模型对输入易于敏感,所以提出了prefix tuning,其主要思想是在模型的每一层transformer中添加一些虚拟化的token,然后通过训练反向传播只更新这些参数,这样添加不同任务的上文前缀就能够更灵活去指导模型生成对应任务的下文了。ptuning 则与prefix tuning不同,其区别在于添加可训练的虚拟token在embedding层,从而指导模型生成。而ptuning中,由于连续提示是被插入到embedding层,存在两个明显的问题,首先是虚拟化token的长度不能过长,因为模型的输入长度是一定的,其次是随着模型层数的过深,第一层的propmt对后面层的影响不确定。
所以ptuning v2,直接将这些可训练的提示不仅仅只插入到第一层的输入,还插入到后续的模型层输入中,也就是说在每层输入前面添加可微调的参数,这样就可以增加可训练的优化参数以更加适应复杂的任务。具体的代码实现可以参考清华给出的chatglm2-6b中ptuning v2代码[6]。
lora微调。 lora引用原文的话就是它冻结了预训练的模型权重,并将可训练的秩分解矩阵注入到 Transformer 架构的每一层中,大大减少了下游任务的可训练参数的数量。如下图所示,lora微调冻结大模型本身的参数,视为一个矩阵,然后通过两个小的矩阵相乘来近似逼近模型,在训练过程中,数据输入到模型中后,经过模型本身的参数和lora矩阵的输出,然后与label计算loss之后仅仅更新lora矩阵的参数,而在推理阶段,只需要将模型的权重与lora矩阵的权重进行合并得到一个新的权重进行推理即可。使用lora微调还需要注