从零开始编写Lora

一、引言

LoRA,英文全称为Low-Rank Adaptation, 是一种更有效地微调 LLMs 的流行技术。 LoRA 不调整深度神经网络的所有参数,而是专注于仅更新一小组低秩矩阵。在没有LoRA之前,进行微调意味着模型的所有layer参数都要更新( 一般是一个矩阵的大小),这个计算量会非常巨大。而使用LoRA,则是将一个大矩阵(假设为5000 * 10000,即参数为5千万),分解成两个小矩阵(比如为5000 * 8, 8 * 10000,参数为4万加8万),那么其参数就大大减少,自然其参数更新过程就加快了。当然,参数少了那么能抓住的特征也会减少,所以这中间会有取舍的问题。下面以具体代码展开说明。

二、LoRA层

如上所说,LoRA本质上是一个layer,所以我们先看代码怎么实现

可以看到代码中的A和B,就是我们上文提到过的两个中间矩阵

让我们来逐个讲解这个layer的各个参数。

in_dim, 代表的是上一个layer的维度

out_dim, 代表的是LoRA 这一层输出的维度

rank,代表的就是A和B进行乘法运算时的中间维度,可以认为这是一个超参数

alpha,是rank之外的另外一个超参数,一个缩放因子,通过forward里的代码,可以看到本质上就是对输出到下一层之前,进行一个缩放。alpha越高,说明LoRA层的作用,即对模型的调整作用越大。

和基本的深度学习一样,在LoRA中,我们的目标就是获得A和B的矩阵(即模型参数),本质上他们就是\omega ,所以我们也需要对他们进行初始化。对于A,我们使用rank的的平方根来决定一个标准差,然后来初始化A,而对于B,就是初始化为零矩阵。为什么要初始化B为零矩阵尼?我们先看下一个简化的使用LoRA的模型代码

可以看到,模型中,计算过程是使用之前的linear加上lora的输出,而Lora本质上就是一个微调,所以一开始,我们不希望Lora会影响到原输出。通过初始化B为零矩阵,我们在一开始消除了LoRA带来的影响。

三、简单实践

首先,我们使用 DistilBERT 做为我们的预训练模型,使用如下代码看下模型架构

结果为

我们可以看到该模型由 6 个包含线性层(Linear)的 Transformer 层组成,此外,该模型还有两个 Linear 输出层:pre_classifier和classifier。

我们使用如下代码,来对线性层来开启lora

应用后,再次print(model), 得到结果如下,可以看到,已经如预期,对query和value两个层使用了lora

现在,你就得到了一个使用了lora的模型,可以对它进行训练了。通过调整诸如rank和alpha这些超参数,你可以通过训练更少的参数,来获得接近之前性能的模型!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容