ChatGPT带领着大模型像雨后春笋一般层出不穷,大家都对大模型微调跃跃欲试,现在咱们聊聊其中的常见的算法
1 LORA 低秩适应
理论
Lora( Low-Rank Adaotation),低秩自适应模型微调的方法,它冻结预训练模型的权重,并将可训练的秩分解矩阵注入到transformer架构的每一层,从而大大减少下游任务的可训练参数的数量,
怎么微调下游任务:利用LoRA对下游任务数据训练时,只通过训练新加部分的参数来适配下游任务,当训练好新的参数后,将新的参数与老的参数合并,利用重参的方式,这样既能在新的任务上达到fine-tune整个效果,又不会在模型推理中增加耗时,
效果:以GPT3为例,Lora可以将训练参数的数量减少10000倍,GPU内存需求减少3倍,LoRA在RoBertTa,GPT2和3上的模型推理结果表现的于微调相当或者更好,并且多加网络层,所以推理没有延时,https://github.com/ microsoft/LoRA
实现的方法
1 低秩参数化更新矩阵
神经 网络 包 含许 多 执行 矩阵 乘 法的 密集 层 。这 些层 中 的权 重 矩阵 通常 是 满秩 的。 在 适应 特定 任 务时, ag hajya n 等 人 (202 0)表 明 , 预 训练 的 语 言模 型 具 有较 低 的“内 在 维度 ” , 尽管 随 机 投影 到 较小的 子空 间 ,但 仍 然可 以有 效 地学 习。 受 此启 发, 我 们假 设 在适 应过 程 中对 权重 的 更新 也具 有 较低的 “内 在秩 ”。 对于 预训 练的 权重 矩阵 W0 ∈ Rd ×k, 我们 用低 秩分 解 W 0 +∆ W = W 0 + BA 来表示它的 更新 ,其 中 B∈ Rd× r, a∈ Rr× k, 秩 R ? min(d, k) .在 训练 期间 , Wis 冻结 0 并 且不 接收 梯度 更新 ,而 A 和 B 包 含可 训练 的参 数。 注意 两个 Wa nd∆ W = B A0 乘以 相同 的输 入, 它们 各自 的输 出向 量按坐标求和。对于 h = Wx,修正 后的 正 向 0 传递 收益 率为 :
原始权重矩阵W0加上微调权重∆ W,两边参数相加就是整个模型,
整个过程通俗来讲,蓝色部分为预训练的模型参数,LoRA在预训练号的模型结构旁加上一个分支,这个分支包含A,B两个结构,这两个参数分别初始化为高斯分布和0,在训练刚开始,附加的参数就是0,A的输入维度和B的输出维度分别与原始模型的输入输出维度相同,而A的输出维度和和B的输入维度是一个远小于原始模型输入输出维度的值,这样做就可以极大的减少待训练的参数,在训练时只更新A,B的参数,预训练好的模型参数固定不变,将AB与原始模型参数矩阵W合并,这样九不会在推断中引入额外的计算,对于不同的下游任务只需要在预训练模型的基础上重新训练A,B就可以,
计算的过程例如,原始矩阵是512 * 512,假设r=4,现有用512 * 4的矩阵进行降维,最后的输出再用4 * 512 还原维度,r也可以取值为512,相当于对fine -tuing
作者通过实验表明,lora施加到transformer中的q,k,v,和原始矩阵w上时候,出现的效果是做好的,
并且r=4时候效果是最好的,
总结:冻结预训练模型权重,并将可训练的秩分解矩阵注入到Transformer层的每个权重中,大大减少了下游任务的可训练参数数量
LoRA 几个关键优势,
1,预训练模型可以共享,例如Chinese-LLaMA或者stable-difficution ,为不同的任务构建许多小型的LoRA模块,我们可以通过替换矩阵A和B来共享冻结模型并有效切换任务,从而降低存储需要和任务切换开销,
2,当使用Adam这种自适应优化器时候,LoRA可以让训练更有效,并将硬件门槛减低3倍,LORA不需要计算梯度或者维护大多数参数的优化器状态,只需要优化注入,小的多的低秩矩阵,
3,LoRA简单的显示设计允许在部署时将训练矩阵与冻结的权重合并,没有多加层,与完全微调模型相比,没有推理延时,
使用方式
HuggingFace的包peft对LoRA做了封装支持,调用api即可
模型并行计算
在并行训练过程中,各个显卡并行计算,每个模型使用同一份模型权重参数weights,在梯度下降更新时,各个进程会同步一次,致使每个进程的模型都跟新相同的梯度
具体实现,需要在model外套一层DistributedDataParallel,就可以实现backword前向更新梯度时,其他操作依旧,
使用DistributedDataParallel把model封装成ddp_model后,模型的参数名称里多了一个module,这是因为原来的模型model被保存到了ddp_model.module这个成员变量中。
在混用单GPU和多GPU的训练代码时,要注意这个参数名不兼容的问题,包括上面我们使用LoRA加载模型的时候,也会出现模型层名称变换了的情况。最好的做法是每次存取ddp_model.module,这样单GPU和多GPU的checkpoint可以轻松兼容。
人类反馈强化学习(RLHF)
RLHF-Stage1 是 supervised-fintuning,即使用上文提到的数据集进行模型微调。
RLHF-Stage2 训练了奖励模型,它通过对于同一个 prompt 的不同输出进行人工排序,得到对应分数,监督训练奖励模型。
RLHF-Stage3 使用了强化学习算法,是训练流程中最复杂的一部分:
RLHF(Reinforcement Learning Hyperparameter Optimization Framework)是一种用于强化学习模型的超参数优化框架。它结合了强化学习中的经典方法和贝叶斯优化技术,能够更高效地找到最佳超参数组合。下面是强化学习微调的完整 RLHF 流程:
数据预处理:根据需要对强化学习任务的数据进行处理,如归一化、去噪等。
确定超参数空间:为每个超参数指定范围和分布,以便进行超参数优化。
确定评估指标:根据强化学习任务的性质和目标,选择合适的评估指标,如累积回报、平均奖励等。
设计搜索策略:根据评估指标和超参数空间的特点,选择合适的搜索策略,如随机搜索、网格搜索、贝叶斯优化等。
进行超参数优化:使用选择的搜索策略在超参数空间中搜索最优超参数组合,并记录每个超参数组合的性能。
分析结果:分析每个超参数组合的性能和超参数之间的关系,以了解哪些超参数对模型性能有重要影响。
微调模型:根据分析结果,
vp tuning v2简单来说其实是soft prompt的一种改进,
soft prompt是只作用在embedding层中,实际测试下来只作用在embedding层的话交互能力会变弱,而且冻结模型所有参数去学习插入token,改变量偏小使得效果有时候不太稳定,会差于微调。p tuning v2则不只是针对embedding层,而是将连续型token插入每一层,增大改变量和交互性。
这是对于低资源微调大模型的共同点都是冻结大模型参数,通过小模块来学习微调产生的低秩改变。但目前存在的一些问题就是这两种训练方式很容易参数灾难性遗忘,因为模型在微调的时候整个模型层参数未改变,而少参数的学习模块微调时却是改变量巨大,容易给模型在推理时产生较大偏置,使得以前的回答能力被可学习模块带偏,在微调的时候也必须注意可学习模块不能过于拟合微调数据,否则会丧失原本的预训练知识能力,产生灾难性遗忘。
最好能够在微调语料中也加入通用学习语料一起微调,避免产生对微调语料极大的偏向,在instruct gpt论文中也提到在强化学习ppo的时候模型也会很容易对于ppo数据拟合,降低模型通用自然语言任务能力,所以在ppo loss中加入了SFT梯度和预训练梯度来缓解这种遗忘问题