首页 > 其他分享 >大模型微调技术LoRA与QLoRA

大模型微调技术LoRA与QLoRA

时间:2023-06-26 18:23:42浏览次数:37  
标签:weight QLoRA LoRA self 微调 fan lora 模型

LoRA: Low-Rank Adaptation of Large Language Models

动机

大模型的参数量都在100B级别,由于算力的吃紧,在这个基础上进行所有参数的微调变得不可能。LoRA正是在这个背景下提出的解决方案。

原理

虽然模型的参数众多,但其实模型主要依赖低秩维度的内容(low intrinsic dimension),由此引出低秩自适应方法lora,通过低秩分解来模拟参数的改变量,从而以极小的参数量来实现大模型的间接训练。

LoRA的思想也很简单,在原始PLM旁边增加一个旁路,做一个降维再升维的操作,来模拟所谓的 intrinsic rank 。

训练的时候固定PLM的参数,只训练降维矩阵A与升维矩阵B。而模型的输入输出维度不变,输出时将BA与PLM的参数叠加。

用随机高斯分布初始化A,用0矩阵初始化B,保证训练的开始此旁路矩阵依然是0矩阵。

这种思想有点类似于残差连接,同时使用这个旁路的更新来模拟full finetuning的过程。并且,full finetuning可以被看做是LoRA的特例(当r等于k时)

 LoRA详细过程

  • 在原模型旁边增加一个旁路,通过低秩分解(先降维再升维)来模拟参数的更新量;
  • 训练时,原模型固定,只训练降维矩阵A和升维矩阵B;
  • 推理时,可将BA加到原参数上,不引入额外的推理延迟;
  • 初始化,A采用高斯分布初始化,B初始化为全0,保证训练开始时旁路为0矩阵;
  • 可插拔式的切换任务,当前任务W0+B1A1,将lora部分减掉,换成B2A2,即可实现任务切换;
  • 秩的选取:对于一般的任务,rank=1,2,4,8足矣,而对于一些领域差距比较大的任务可能需要更大的rank。

总的来说,lora就是冻结预先训练的模型权重,并将可训练的秩分解矩阵注入Transformer架构的每一层。

目前对于大多数实验只在 Wq 和 Wv使用LoRA,可训练参数的数量由秩r和原始权值的形状决定。

 代码

源码:https://github.com/microsoft/LoRA

LoRALayer层

class LoRALayer():
    def __init__(
        self, 
        r: int, 
        lora_alpha: int, 
        lora_dropout: float,
        merge_weights: bool,
    ):
        self.r = r
        self.lora_alpha = lora_alpha
        # Optional dropout
        if lora_dropout > 0.:
            self.lora_dropout = nn.Dropout(p=lora_dropout)
        else:
            self.lora_dropout = lambda x: x
        # Mark the weight as unmerged
        self.merged = False
        self.merge_weights = merge_weights

Linear层

class Linear(nn.Linear, LoRALayer):
    # LoRA implemented in a dense layer
    def __init__(
        self, 
        in_features: int, 
        out_features: int, 
        r: int = 0, 
        lora_alpha: int = 1, 
        lora_dropout: float = 0.,
        fan_in_fan_out: bool = False, # Set this to True if the layer to replace stores weight like (fan_in, fan_out)
        merge_weights: bool = True,
        **kwargs
    ):
        nn.Linear.__init__(self, in_features, out_features, **kwargs)
        LoRALayer.__init__(self, r=r, lora_alpha=lora_alpha, lora_dropout=lora_dropout,
                           merge_weights=merge_weights)

        self.fan_in_fan_out = fan_in_fan_out
        # Actual trainable parameters
        if r > 0:
            self.lora_A = nn.Parameter(self.weight.new_zeros((r, in_features)))
            self.lora_B = nn.Parameter(self.weight.new_zeros((out_features, r)))
            self.scaling = self.lora_alpha / self.r
            # Freezing the pre-trained weight matrix
            self.weight.requires_grad = False
        self.reset_parameters()
        if fan_in_fan_out:
            self.weight.data = self.weight.data.transpose(0, 1)

    def reset_parameters(self):
        nn.Linear.reset_parameters(self)
        if hasattr(self, 'lora_A'):
            # initialize A the same way as the default for nn.Linear and B to zero
            nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
            nn.init.zeros_(self.lora_B)

    def train(self, mode: bool = True):
        def T(w):
            return w.transpose(0, 1) if self.fan_in_fan_out else w
        nn.Linear.train(self, mode)
        if mode:
            if self.merge_weights and self.merged:
                # Make sure that the weights are not merged
                if self.r > 0:
                    self.weight.data -= T(self.lora_B @ self.lora_A) * self.scaling
                self.merged = False
        else:
            if self.merge_weights and not self.merged:
                # Merge the weights and mark it
                if self.r > 0:
                    self.weight.data += T(self.lora_B @ self.lora_A) * self.scaling
                self.merged = True       

    def forward(self, x: torch.Tensor):
        def T(w):
            return w.transpose(0, 1) if self.fan_in_fan_out else w
        if self.r > 0 and not self.merged:
            result = F.linear(x, T(self.weight), bias=self.bias)
            if self.r > 0:
                result += (self.lora_dropout(x) @ self.lora_A.transpose(0, 1) @ self.lora_B.transpose(0, 1)) * self.scaling
            return result
        else:
            return F.linear(x, T(self.weight), bias=self.bias)

Peft实现

from peft import LoraConfig, get_peft_model, prepare_model_for_int8_training, TaskType

# Define LoRA Config
lora_config = LoraConfig(
 r=16,
 lora_alpha=32,
 target_modules=["q", "v"],
 lora_dropout=0.05,
 bias="none",
 task_type=TaskType.SEQ_2_SEQ_LM
)
# prepare int-8 model for training
model = prepare_model_for_int8_training(model)

# add LoRA adaptor
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

# trainable params: 18874368 || all params: 11154206720 || trainable%: 0.16921300163961817

 参考链接:

https://zhuanlan.zhihu.com/p/631077870

https://zhuanlan.zhihu.com/p/636759194

https://zhuanlan.zhihu.com/p/514033873

QLoRA:Efficient Finetuning of Quantized LLMs

动机

微调非常大的模型的成本过高;对650亿参数的LLaMA模型进行进行16位微调需要超过780GB的GPU内存,QLORA使用一种新的高精度技术将预训练模型量化为int4,然后添加一小组可学习的低秩适配器权重。它是通过量化权重反向传播梯度来调整的。QLORA将65B参数模型进行微调的平均内存需求从 >780GB 的 GPU 内存减少到 <48GB,而不会降低运行时间或预测性能。这标志着LLM微调可访问性的显著转变:现在最大的公开可用的模型,迄今为止在单个GPU上进行微调。

创新

首先分析下LoRA微调中的痛点:

  1. 参数空间小:LoRA中参与训练的参数量较少,解空间较小,效果相比全量微调有一定的差距。

  2. 微调大模型成本高:对于上百亿参数量的模型,LoRA微调的成本还是很高。

  3. 精度损失:针对第二点,可以采用int8或int4量化,进一步对模型基座的参数进行压缩。但是又会引发精度损失的问题,降低模型性能。

今天的主角QLoRA优点:

  1. 4-bit NormalFloat:提出一种理论最优的4-bit的量化数据类型,优于当前普遍使用的FP4与Int4。对于正态分布权重而言,一种信息理论上最优的新数据类型,该数据类型对正态分布数据产生比 4 bit整数和 4bit 浮点数更好的实证结果。QLORA包含一种低精度存储数据类型(通常为4-bit)和一种计算数据类型(通常为BFloat16)。在实践中,QLORA权重张量使用时,需要将将张量去量化为BFloat16,然后在16位计算精度下进行矩阵乘法运算。模型本身用4bit加载,训练时把数值反量化到bf16后进行训练。

  2. Double Quantization:对第一次量化后的那些常量再进行一次量化,减少存储空间。相比于当前的模型量化方法,更加节省显存空间。每个参数平均节省0.37bit,对于65B的LLaMA模型,大约能节省3GB显存空间。

  3. Paged Optimizers:使用NVIDIA统一内存特性,该特性可以在在GPU偶尔OOM的情况下,进行CPU和GPU之间自动分页到分页的传输,以实现无错误的 GPU 处理。该功能的工作方式类似于 CPU 内存和磁盘之间的常规内存分页。使用此功能为优化器状态(Optimizer)分配分页内存,然后在 GPU 内存不足时将其自动卸载到 CPU 内存,并在优化器更新步骤需要时将其加载回 GPU 内存。

  4. 增加Adapter:4-bit的NormalFloat与Double Quantization,节省了很多空间,但带来了性能损失,作者通过插入更多adapter来弥补这种性能损失。在LoRA中,一般会选择在query和value的全连接层处插入adapter。而QLoRA则在所有全连接层处都插入了adapter,增加了训练参数,弥补精度带来的性能损失。

 

参考:

https://zhuanlan.zhihu.com/p/632164305

https://zhuanlan.zhihu.com/p/636215898

https://zhuanlan.zhihu.com/p/634256206

https://zhuanlan.zhihu.com/p/632229856

https://blog.csdn.net/qq_39970492/article/details/131048994

总结

 QLORA 可以使用 4 位基础模型和低秩适配器 (LoRA) 复制 16 位完全微调性能。QLORA将微调65B参数模型的平均内存需求从>780GB的GPU内存降低到<48GB,与完全微调的16位基准相比,既不降低运行时间也不降低预测性能,这意味着可以在单个GPU上微调迄今为止最大的公开可用模型。

 

标签:weight,QLoRA,LoRA,self,微调,fan,lora,模型
From: https://www.cnblogs.com/xiaofengzai/p/17503544.html

相关文章

  • 什么时候需要微调你的大模型(LLM)?
    前言在AI盛起的当下,各类AI应用不断地出现在人们的视野中,AI正在重塑着各行各业。相信现在各大公司都在进行着不同程度的AI布局,有AI大模型自研能力的公司毕竟是少数,对于大部分公司来说,在一款开源可商用的大模型基础上进行行业数据微调也正在成为一种不错的选择。本文主要用于向大......
  • Diffusers框架使用Civitai上的checkpoit和lora模型
    1、实验室有一台带显卡的机器,能访问huggingface但访问不了Civitai,而Civitai上的模型多是webui训练来的也不能直接用到diffusers框架上,于是需要利用Colab把Civitai上的模型转化成diffusers可用再上传到huggingface上,再下载到本地。2、googlecolab上新建一个笔记本,再选修改==》笔......
  • 一文读懂:LoRA实现大模型LLM微调
    LoRA大模型LLM微调为什么要进行微调?LoRA思路提高权重更新效率选择低的秩实现LoRALoRA在LLaMA实现为什么要进行微调?在快速发展的人工智能领域中,以高效和有效的方式使用大型语言模型变得越来越重要。预训练的大型语言模型通常被称为优秀的基础模型,原因在于它们在各种任务上表现出......
  • 预训练和微调(Pre-training and Fine-tuning)概述
    预训练和微调(Pre-trainingandFine-tuning)是深度学习领域中常用的技术,特别是在自然语言处理(NLP)领域中取得了巨大成功。本文将介绍预训练和微调的概念、流程和应用,并探讨它们在NLP领域的重要性。预训练预训练是指在大规模无标签数据上训练模型的过程。在NLP领域,预训练的目标是通......
  • SX130芯片的LoRa网关吞吐量是SX127芯片的多少倍?
    1.吞吐量,LoRa网关的重要性能从广义上讲,网关是连接2个不同网络的设备。如果一个设备,它能将LoRa无线网络和Internet连接起来,它就是一个LoRa网关。目前,大部分的LoRa网关采用SX1301基带芯片,也有部分使用SX1276/8单信道芯片。那么,SX1301芯片的数据吞吐量是SX1276/8芯片的多少倍呢?我们......
  • 【了解LLM】——LoRA
    本文地址:https://www.cnblogs.com/wanger-sjtu/p/17470327.html论文链接:linkcode:github什么是LoRALoRA,英文全称Low-Rank AdaptationofLargeLanguageModels,直译为大语言模型的低阶适应,是一种PEFT(参数高效性微调方法),这是微软的研究人员为了解决大语言模型微调而开发的......
  • [人工智能-NLP]使用GPT-2预训练模型进行微调
    下面是一个使用GPT-2进行微调的示例。以文本生成为例,我们将微调GPT-2来生成新闻标题。此外,我们将使用PyTorch作为深度学习框架,以便于构建和训练模型。安装PyTorch和Transformers首先需要安装PyTorch和Transformers库。在终端中输入以下命令:pipinstalltorchtransformers......
  • stm32+sx1268 LORA通信
    前言:由于亿佰特的lora代码不好移植,基于stm8且是IAR编译器,对于代码的处理很大困难。所以我通过搜索资料发现了泽耀科技的同配置的lora模块写了关于stm32的代码。在实验中,我将买回来的lora模块的引脚按照手册上的需要引出并打板焊接(SPI通信的lora模块),通过stm32连接lora,lora的天线......
  • QLoRa:在消费级GPU上微调大型语言模型
    大多数大型语言模型(LLM)都无法在消费者硬件上进行微调。例如,650亿个参数模型需要超过780Gb的GPU内存。这相当于10个A10080gb的gpu。就算我们使用云服务器,花费的开销也不是所有人都能够承担的。而QLoRa(Dettmersetal.,2023),只需使用一个A100即可完成此操作。在这篇文章中......
  • 漂亮的输出-----prettytable和colorama的使用
    Python通过prettytable模块将输出内容如表格方式整齐输出,python本身并不内置,需要独立安装该第三方库。1pipinstallPrettyTable1#源码安装2wgethttps://pypi.python.org/packages/source/P/PrettyTable/prettytable-0.7.2.tar.gz3tar-zxvfprettytable-0.7.2.tar.g......