peft库lora源码逐行解读


前言

随着各大企业和高校研发的模型越来越大,模型的性能也逐渐涌现。但是这些大模型在实际应用到具体领域时,依然会存在缺乏领域知识的问题,往往需要进一步领域微调。而巨额参数量的大模型微调需要很多的资源支持,使很多研发人员望而却步。
PEFT(Parameter-Efficient Fine-Tuning)是一种用于大型预训练模型微调的技术。它在近年来因应对大型模型的实际应用需求而被广泛研究和采用。PEFT技术通过在保持大部分预训练参数固定的前提下,只对模型的一小部分参数进行调整,以实现对特定任务的微调。这种方法的目的是提高微调的效率和可行性,尤其是在资源受限的情况下。


一、lora是什么?

LoRA(Low-Rank Adaptation)就属于大型预训练语言模型的参数高效微调技术的一种。这种方法的核心思想是通过引入低秩矩阵来修改模型中的特定权重矩阵,从而使模型适应新的任务或数据集,而不必改变原始的预训练权重。
lora原理图

LoRA的实现步骤:
1、选择权重:首先,选择模型中需要被调整的权重矩阵。这些通常是深度神经网络中关键层(如Transformer中的自注意力层)的权重。
2、引入低秩矩阵:为每个选定的权重矩阵引入两个低秩矩阵A和B。这些矩阵比原始权重矩阵小得多,因此包含的参数数量也少得多。
3、修改权重:在模型的前向传播过程中,原始的权重矩阵W通过W + BA来修改。这里,BA是A和B的乘积,它是一个低秩矩阵,可以看作是对原始权重的一个增量调整。
4、训练低秩矩阵:在微调过程中,不改变原始的权重W,只更新低秩矩阵A和B。这样,就可以通过训练相对较少的参数来调整模型的行为。

使用这种方式微调大模型,需要训练的参数量仅为A、B两个矩阵的权重,远低于模型的全量参数。

二、peft仓库代码实现逐行解读

1. lora层的具体计算细节

代码路径:peft/src/peft/tuners/lora/layer.py

def _apply_dora(self, x, lora_A, lora_B, scaling, active_adapter):
        """
        For DoRA, calculate the extra output from LoRA with DoRA applied. This should be added on top of the base layer
        output.
        """
        lora_weight = lora_B.weight @ lora_A.weight	# YoungL: 这行代码通过矩阵乘法合并两个权重矩阵 lora_A.weight 和 lora_B.weight。这两个矩阵是LoRA技术中使用的低秩矩阵,用来调整模型的参数。
        magnitude = self.lora_magnitude_vector[active_adapter] 	# YoungL: 从 lora_magnitude_vector 中获取当前激活适配器对应的幅度值。这个幅度值用于后续调整LoRA调整的规模。
        weight = self.get_base_layer().weight	# YoungL: 从 lora_magnitude_vector 中获取当前激活适配器对应的幅度值。这个幅度值用于后续调整LoRA调整的规模。
        quant_state = getattr(self.get_base_layer(), "state", None)	# YoungL: 尝试获取基础层权重的量化状态,如果没有则返回 None。
        weight = dequantize_bnb_weight(weight, state=quant_state)  # no-op if not bnb	# YoungL: 如果权重被量化,这行代码将进行反量化处理,确保权重以正确的格式用于计算。
        weight = weight.to(x.dtype)	# YoungL: 将权重的数据类型转换为与输入 x 相同,确保数据类型一致。
        weight_norm = self._get_weight_norm(weight, lora_weight, scaling)	# YoungL: 在初始权重上增加scaling处理过的lora权重(看后续对self._get_weight_norm的解读)。

        weight_norm = weight_norm.detach()	# YoungL: 将处理后的权重从梯度计算中分离出来,遵循DoRA文献中的建议,使其在反向传播时不更新。
        mag_norm_scale = (magnitude / weight_norm).view(1, -1)	# YoungL: 根据获取的幅度和计算出的权重,计算缩放因子。调整其形状以便于后续运算。
        result_dora = (mag_norm_scale - 1) * (
            F.linear(x, transpose(weight, self.fan_in_fan_out))
        ) + mag_norm_scale * lora_B(lora_A(x)) * scaling	# YoungL: 这行代码计算最终的DoRA结果。首先,使用基础权重进行线性变换,然后应用LoRA调整,并通过缩放因子进行调整。结果是两部分的加和,一部分是基础变换,另一部分是LoRA调整。
        
        return result_dora

上述代码中的 _get_weight_norm 函数的解析如下:

    def _get_weight_norm(self, weight, lora_weight, scaling) -> torch.Tensor:
        # calculate L2 norm of weight matrix, column-wise
        weight = transpose(weight, self.fan_in_fan_out)	# YoungL: 权重矩阵的转置
        weight = weight + scaling * lora_weight	# YoungL: 这一步将LoRA技术调整的权重(lora_weight)缩放后加到原始的权重矩阵上。这里的 scaling 是一个缩放因子,用于控制LoRA权重调整的影响程度。
        weight_norm = torch.linalg.norm(weight, dim=1).to(weight.dtype)	# YoungL: 使用PyTorch的 torch.linalg.norm 函数计算权重矩阵每一列的L2范数。dim=1 参数指定沿着矩阵的列(每行一个元素组成的列)进行范数计算。
        return weight_norm

2. peft仓库对lora层的封装细节

(1)_apply_dora函数的上层调用者为Linear8bitLt、Linear4bit的forward函数,将lora处理分装成线性层的处理
代码路径:peft/src/peft/tuners/lora/bnb.py

        def forward(self, x: torch.Tensor, *args, **kwargs) -> torch.Tensor:
            self._check_forward_args(x, *args, **kwargs)	# YoungL: 参数校验
            adapter_names = kwargs.pop("adapter_names", None)	# YoungL: 需要处理的线性层
            
			# YoungL: 获取初始模型层赋值给result
            if self.disable_adapters:
                if self.merged:
                    self.unmerge()
                result = self.base_layer(x, *args, **kwargs)
            elif adapter_names is not None:
                result = self._mixed_batch_forward(x, *args, adapter_names=adapter_names, **kwargs)
            elif self.merged:
                result = self.base_layer(x, *args, **kwargs)
            else:
                result = self.base_layer(x, *args, 
  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在实战操作中,PEFT可以用来微调BERT模型,以进行文本情感分类任务。首先,我们需要准备一个包含大量文本和标签的数据集,用于训练和验证BERT模型。然后,我们需要利用PEFT中提供的工具和接口,将数据集转换成BERT模型可接受的格式,并进行数据预处理,如分词和填充等操作。 接着,我们可以利用PEFT中提供的预训练模型,加载BERT模型的参数和网络结构,并在数据集上进行微调。微调的过程中,我们可以通过调整学习率、批大小和训练轮数等超参数,来优化模型的性能。在每个训练轮数结束后,我们可以利用PEFT中的评估工具对模型进行评估,以了解模型在验证集上的性能表现。 最后,当模型在验证集上的性能达到满意的水平后,我们可以使用PEFT提供的保存模型工具,将微调后的BERT模型保存下来,以备在实际应用中使用。通过PEFT的实战操作,我们可以有效地利用BERT模型进行文本情感分类任务,提高模型的准确性和泛化能力,从而更好地满足实际应用的需求。 PEFT的实战操作不仅帮助我们更好地理解和使用BERT模型,也为我们提供了一套完整的工具和流程,使得模型训练和应用变得更加简单和高效。 PEFT实战(一): lora微调BERT(文本情感分类) 的操作流程清晰,易于上手,为我们在文本情感分类任务中的应用提供了有力的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值