使用奇异值分解微调 LLM
这篇博文将讨论一种通过截断奇异值分解 (SVD) 以参数开销较低的方式微调语言模型的方法。这项技术类似于LoRA,但可训练参数数量要少得多。
接下来,主要目标是重现最近论文LoRA-XS:使用极少量参数的低秩适应中的结果,并将其作为 Python 包轻松提供。
使用低秩适应 (LoRA) 进行训练
LoRA 的主要思想是将每个线性变换中的权重分解为两部分:一个不可训练的矩阵(包含初始权重)和一组可训练的权重,它们在低维潜在空间(通常是 2 的小幂次)之间进行变换。
上图中,原始权重矩阵是冻结的,只有两个投影矩阵是可训练的。
这项技术在允许更便宜的 GPU 设置上进行微调方面取得了令人难以置信的成功。通过严格将训练限制在低秩投影矩阵上,可以使用原始参数数量的约 1/1000 来微调模型的所有层。
仅训练奇异值
奇异值分解通过线性代数技术将矩阵分解为三个元素来近似矩阵。给定一个原始 权重矩阵 和一个整数 ,SVD 构建一个近似矩阵
通过计算 矩阵 , 矩阵 ,以及对角方阵 矩阵 。
请注意,尽管 是一个方阵,但唯一的非零元素位于对角线上,并被称为**奇异值**。 的值是近似中选择的奇异值的数量。在本帖中,原始 矩阵的**秩** r 定义为 。
这是 SVD 训练的核心要素:*我们只训练奇异值,而不是训练整个权重矩阵 M。*
更具体地说,我们注意到矩阵 M 等价于
可以改写为
其中
如果我们冻结 、 和 的参数,那么只有奇异值会在训练循环中更新。从内存角度来看,这比 LoRA 更便宜,因为矩阵 和 保持不变。
上图中,只有奇异值是可训练的。所有其他参数都被冻结。
此方法是 **SVD 训练**技术,与 LoRA-XS 中描述的方法非常相似。主要区别在于 LoRA-XS 直接使用 ,而不是 。
可训练参数的数量
接下来,我将对 Microsoft Research 开发的模型 Phi-3-mini-128k-instruct 进行一些实验。
使用 SVD 训练技术,可训练参数的数量取决于近似中使用的秩分数 。SVD 分解应用于所有线性层。下表展示了 LoRA 和 SVD 训练的典型超参数之间的差异。这些是使用 SVD 训练时常用的值
SVD 秩分数 | 可训练参数 |
---|---|
0.1 | 239_283 |
0.2 | 278_886 |
0.5 | 397_824 |
这需要与以下常见的 LoRA 配置进行比较
低秩维度 | 可训练参数 |
---|---|
8 | 12_864_000 |
16 | 25_728_000 |
32 | 51_456_000 |
请注意,低秩维度与 SVD 秩分数不直接对应。这是因为 SVD 近似应用于所有线性层——每个层具有不同的维度。秩分数为 0.1 会根据权重产生可变数量的 。
为了便于比较,上述可训练参数的数量不包括两种情况下的 token 嵌入。该数字是一个常数,对于所考虑的模型,为 98,500,608。
SVD 训练库
一个利用 SVD 训练的简单库是 *svd-training*
pip install svd-training
此库需要对模型进行预处理,以生成矩阵 、、 和 。
from transformers import AutoTokenizer, AutoModelForCausalLM
from svd_training.svd_model import SVDForCausalLM
filename = "mistralai/Mistral-7B-Instruct-v0.1"
tokenizer = AutoTokenizer.from_pretrained(filename)
model = AutoModelForCausalLM.from_pretrained(filename)
svd_model = SVDForCausalLM.create_from_model(model, rank_fraction=0.1) # Create the SVD model
### Train the model using your favourite training loop
...
###
svd_model.merge() # Merge the SVD layers back into the model
svd_model.save_pretrained("svd_model/") # Save the model
最终,所有元素都合并到原始权重矩阵中。合并操作后,模型可以像任何其他 HF 模型一样保存和加载。
在 Ultrachat 上进行微调
作为测试,上述 Phi-3 模型在 Ultrachat 数据集上进行了微调。此测试包括完整模型微调、8 维 LoRA 和秩分数为 0.1 的 SVD 训练。据我所知,Ultrachat 数据集不属于 Phi-3 原始训练集的一部分。
所有这些模型均使用标准的 SFTTrainer 和不同的学习率进行训练。这些是经过简短超参数扫描后为每个模型选择的值。
模型 | 学习率 |
---|---|
完整模型微调(除了嵌入) | 5e-5 |
8 维 LoRA | 1e-4 |
SVD 训练,r=0.1 | 1e-2 |
Ultrachat 数据集上的评估损失如下(越低越好)
模型 | Ultrachat 评估损失 |
---|---|
原始 Phi-3-mini-128k-instruct | 4.01 |
完整模型微调(除了嵌入) | 2.60 |
8 维 LoRA | 2.78 |
SVD 训练,r=0.1 | 2.67 |
最佳结果来自完整模型微调。次优结果来自 SVD 训练技术。
结论
SVD 训练方法似乎与**参数更重的 LoRA 表现不相上下**。这令人瞩目,因为 **SVD 使用的参数数量要少两个数量级**。虽然还需要更多工作来证实这些结果,但该方法非常有前景。
参数较少的模型显然对数据需求较少。这可能意味着 SVD 技术在小型数据集上进行微调时特别有用。未来的工作将更好地定义使该技术最成功的条件。