CV算法工程师的LLM日志(2)PEFT训练技术——10分钟快速理解DORA【原理&&代码】

文章探讨了DORA,一种改进的LORA微调方法,旨在解决LORA在训练大型语言模型时内存占用问题。通过权重分解和方向更新,DORA接近全参微调的效果,减少过拟合风险。文章详细解释了DORA的原理、动机及其实验验证。
摘要由CSDN通过智能技术生成

摘要

对于LLM的训练,目前主流用的基本都是Lora\q-lora系列的微调与全参的方式(freeze和hypernetwork基本用的很少,蒸馏以及对抗蒸馏也不在讨论范围),最近还新出了一个基于优化器优化内存的训练技术,不过先按顺序来,逐个方法分享下原理和代码,不说废话,原论文为了证明其理论前提,做了一些实验证明,这里我只压缩为结论的叙述,并不影响读者理解,且提高阅读效率。今天分享的是LORA系列的一种改进的微调方法——DORA,为了使LoRA的学习能力更接近FT,研究者们首先通过权重分解分析来探究FT和LoRA之间的内在差异。基于这些发现,他们提出了DoRA,该方法将预训练权重分解为幅度(magnitude)和方向(direction)两个部分,并分别对它们进行微调。
dora paper


一、动机以及原理

回顾下LORA,因为LLM的训练是针对多层的transfromer,因此大参数模型在训练过程中本身以及其优化器的参数更新会对显卡内存产生大量的寻求,因此市面上才围绕多卡或者单卡微调的方式去研发训练和推理算法框架,比如训练deepspeed,推理VLLM等主流的三方库。Lora系列通过在指定的网络层上进行新分支以A\B两个矩阵作低秩分解去训练来逼近原始权重,这样大量节省了训练内存开销,因为通过矩阵分解实际上你的权重矩阵DXD,变成了D x rank* (rank xD),相当于每一个lora标记的训练层节省了 D/rank*2倍的参数训练量。并且独立的训练的Lora还具备灵活插拔性质。(A\B两个矩阵初始化任意一个就行,只要保证一个是0即可,既保证第一次前向时候是原始参数的推理。)LORA相比全参训练就是对世界知识的保留能力稍强,但是对于训练效果一般理论上来说不如全参微调。

在这里插入图片描述

因此基于LORA训练效果不如全参的这个缺点,这篇论文提出了改进LORA的训练技术,简单来说就是再做一步权重分解,如下图:
绿的模型是Dora的可训练参数,可以明显看出是在Lora的流程上,做了改动,先做一步权重分解后,在进行lora中的rank分解,最后再Merge。
在这里插入图片描述
论文中除了DORA的流程和动机,主要还要解释为什么(为什么要做权重分解)和实验证明,和这样做对于全参来说减少过拟合风险和相比于lora训练的更好的效果。具体地:
权重矩阵可以被分解为幅度和方向两个组件。具体而言,给定权重矩阵 W ∈ ℝ^(d×k),我们可以表示为以下公式:
V 是保持方向的矩阵,且每个列向量都是单位向量(即其范数为1)。
权重矩阵W可以分解为幅度m和方向V两个组件,即W = m * V,其中m是幅度向量(通过权重矩阵的列范数计算得到),V是方向矩阵。
微调福哦城中的梯度原始的预训练权重(W0)冻结,而通过DoRA方法,可以训练幅度(m)和方向(V+∆V)的更新。这些更新是通过合并低秩矩阵B和A来实现的,即∆V = BA。

梯度分析

DoRA的更新V,即W’ = m * (V + ∆V),其中∆V按照类似LoRA的方法进行更新,发现权重分解使得梯度的协方差矩阵更趋近于单位矩阵,这对优化过程有益。
对于损失函数 L 关于权重向量 m 和更新后的权重向量 W’ = W + ΔV’

权重分解的重要性:DoRA能够更稳定地优化方向更新 ΔV,因为分解使得优化过程更加直接,减少了参数更新的复杂性。
通过对方向变化(ΔD)和幅度变化(ΔM)的分析,展示了全量微调(FT)和低秩权重适应(LoRA)之间的学习模式差异。
全量微调(FT):在FT中,幅度和方向的变化往往呈现出负相关性。这意味着FT方法在适应下游任务时能够进行更细致的调整。
低秩权重适应(LoRA):相比之下,LoRA显示出正相关性,即幅度和方向的变化之间存在一定的一致性
这些差异有助于我们理解FT和LoRA之间的不同学习行为,以及它们在模型训练中的作用。

这个意思简单来说就是,lora是等比例的在幅度和方向上,而FT并不是,所以Dora要在幅度和方向上作分解,使得其更接近全量的FT。
我们开始讲过LORA的训练参数,类比dora就是多了一个幅度权重m的可训练参数
训练开销降低:为减少反向传播中的内存消耗,DoRA把方向更新的范数当作常数处理,以此减少梯度图的内存使用。

局限性:

模型复杂性: 尽管DoRA减少了参数数量,但它引入了权重分解和低秩更新的额外复杂性。这可能需要更多的技术知识和经验实施和调整。

泛化能力:DoRA在特定任务上表现出色,但其泛化能力到其他类型的任务或数据集上可能存在局限性。FT由于更新了所有参数,可能在某些情况下提供更广泛的泛化能力。

调参需求: DoRA可能需要仔细的超参数调整来达到最佳性能,例如确定分解的幅度和方向组件的适当比例。这可能需要额外的实验和验证。
适用性: DoRA的设计是为了提高特定类型的预训练模型(如Transformer架构)的微调效率。它可能不适用于所有类型的模型或架构。

二、代码

代码很简单,就是在Lora基础上,先分解出一个m 幅度,一维向量权重,然后使用Lora更新流程加上merger后,L2范式提取单位方向的向量,最后再以幅度和单位方向乘积形式merge.


import torch
import torch.nn as nn
import torch.nn.functional as F

class DoRALayer(nn.Module):
    def __init__(self, d_in, d_out, rank=4, weight=None, bias=None):
        super().__init__()  # 调用父类 nn.Module 的构造函数

        # 初始化权重和偏置,如果提供了预训练权重,则直接使用它们
        if weight is not None:
            self.weight = nn.Parameter(weight, requires_grad=False)  # 冻结预训练权重,不进行梯度更新
        else:
            self.weight = nn.Parameter(torch.Tensor(d_out, d_in), requires_grad=False)  # 初始化权重为全零

        if bias is not None:
            self.bias = nn.Parameter(bias, requires_grad=False)  # 如果提供了预训练偏置,则直接使用它们
        else:
            self.bias = nn.Parameter(torch.Tensor(d_out), requires_grad=False)  # 否则初始化偏置为全零

        # 计算权重矩阵的幅度(每列的 L2 范数)
        self.m = nn.Parameter(self.weight.norm(p=2, dim=0, keepdim=True))

        # 初始化 LoRA 方法中的两个低秩矩阵
        # self.lora_A 是输出维度上的随机初始化矩阵
        # self.lora_B 是输入维度上的零矩阵
        std_dev = 1 / torch.sqrt(torch.tensor(rank).float())  # 根据秩计算标准差初始化
        self.lora_A = nn.Parameter(torch.randn(d_out, rank) * std_dev)
        self.lora_B = nn.Parameter(torch.zeros(rank, d_in))

    def forward(self, x):
        # 计算 LoRA 更新
        lora = torch.matmul(self.lora_A, self.lora_B)

        # 计算调整后的权重(原始权重加上 LoRA 更新)
        adapted = self.weight + lora

        # 计算调整后权重矩阵的列范数
        column_norm = adapted.norm(p=2, dim=0, keepdim=True)

        # 将调整后的权重矩阵转换为单位方向权重矩阵
        norm_adapted = adapted / column_norm

        # 计算最终的权重(幅度乘以单位方向权重矩阵)
        calc_weights = self.m * norm_adapted

        # 使用 PyTorch 的线性层操作执行前向传播
        return F.linear(x, calc_weights, self.bias)

总结

介绍了dora在Lora基础上,增加了一次权重分解的流程,给其思路和流程作出解释性。在自己的业务数据集中,微调后效果和Lora并没有明显差距。另外Dora比较简单,也不做过多叙述,PEFT还是比较好水的😊,下篇预告glaore或者Longlora.

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LLM(Large Language Models)通常是指大型语言模型,如通义千问、InferSent等,它们基于深度学习特别是Transformer架构。这些模型的核心原理包括: 1. **神经网络基础**:利用大量的神经元(节点)构成多层结构,每一层处理输入信息并传递给下一层。 2. **自注意力机制(Self-Attention)**:这是Transformer的关键组件,允许模型关注输入序列的不同部分,而不是逐词地处理,增强了模型对上下文的理解。 3. **Transformer编码器-解码器结构**:通常由编码器负责处理输入序列生成中间表示,而解码器用于根据这些表示生成新的文本。 4. **预训练与微调**:模型通过大量无监督数据进行预训练,然后根据特定任务的数据进行有监督的微调,以优化其性能。 SD(Smart Devices 或 System-on-a-Chip)底层技术原理主要包括硬件层面的设计,比如: 1. **SoC集成**:System-on-Chip(片上系统)集成了CPU、GPU、内存控制器、I/O控制单元等多种功能在一个芯片上,减少信号传输距离,提高效率。 2. **硬件加速器**:为特定任务设计专用的硬件模块,如图形处理器加速图像处理,AI加速器加速机器学习计算。 3. **低功耗设计**:为了延长设备电池寿命,SD采用能效高的制程工艺和节能算法。 4. **嵌入式操作系统**:针对资源受限的设备定制轻量级的操作系统,支持设备的高效管理和通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值