LLM Tuning

Lora-Tuning

什么是Lora微调?

LoRA(Low-Rank Adaptation) 是一种参数高效微调方法(PEFT, Parameter-Efficient Fine-Tuning),它通过引入低秩矩阵到预训练模型的权重变换中,实现无需大规模修改原模型参数即可完成下游任务的微调。即你微调后模型的参数 = 冻结模型参数 + Lora微调参数。

什么是微调?

在早期的机器学习中,构建一个模型并对其进行训练是可行的。但到了深度学习阶段,模型的参数量大且训练的数据多,因此要从0到1训练一个模型是非常耗时和耗资源的过程。

训练,在其最简单的意义上。您将一个未经训练的模型,提供给它数据,并获得一个高性能的模型。

对于简单问题来说,这仍然是一种流行的策略,但对于更复杂的问题,将训练分为两个部分,即“预训练”和“微调”,可能会很有用。总体思路是在一个大规模数据集上进行初始训练,并在一个定制的数据集上对模型进行优化。

最基本的微调形式 是使用与预训练模型相同的过程来微调新数据上的模型。例如,您可以在大量的通用文本数据上训练模型,然后使用相同的训练策略,在更具体的数据集上微调该模型。

目前的话,在深度学习中,你所用的预训练的模型就是别人从0到1训练好给你用的,你后面的基于特定数据集所做的训练其实是基于已有模型参数的基础上去进行微调。

那在深度学习阶段,这种方式消耗GPU的程度还可以接收,那到了LLM阶段,如果想通过微调全部参数来微调上一个已预训练好的没有冻结参数模型的话,那消费的GPU就不是一个量级上的,因此Lora就是针对LLM微调消耗资源大所提出优化方案。

Lora的思想

“低秩适应”(LoRA)是一种“参数高效微调”(PEFT)的形式,它允许使用少量可学习参数对大型模型进行微调 。LoRA改善微调的几个关键点:

  1. 将微调视为学习参数的变化(\Delta W),而不是调整参数本身(W)。  
  2. 通过删除重复信息,将这些变化压缩成较小的表示。  
  3. 通过简单地将它们添加到预训练参数中来“加载”新的变化。

正如之前讨论的,微调的最基本方法是迭代地更新参数。就像正常的模型训练一样,你让模型进行推理,然后根据推理的错误程度更新模型的参数(反向传播)。

与其将微调视为学习更好的参数,LoRA 将微调视为学习参数变化:冻结模型参数,然后学习使模型在微调任务中表现更好所需的这些参数的变化。类似于训练,首先让模型推理,然后根据error进行更新。但是,不更新模型参数,而是更新模型参数的变化。如下面所示,蓝色箭头反向传播只是去微调模型所需要的参数变化,没有去微调模型原有的参数。

在微调的过程中可以不去微调W,去微调\Delta W来捕捉W所需要进行的参数变化,那随后二者相加就得到了微调后模型的参数。
那Lora体现的降低资源在哪?如W如果形状为[ 1000, 200 ] 的话,那如果我去微调原模型参数的话,那需要微调的参数有 1000 * 200 = 200,000。聪明的你可能想到了,那我去微调获得参数的变化不也是一个[ 1000, 200 ]的矩阵,不然后面矩阵怎么相加。这就是Lora的巧妙之处,它将所需微调的\Delta W矩阵分解为低秩表示,你在这个过程不需要显示计算\Delta W,只需要学习\Delta W的分解表示。比如\Delta W= [ 1000, 200 ] 可以被划分为 [1000, 1] * [1, 200],那这样的话所需要微调的参数就只有1000+200=1200,与200,000比的话,我们就可以明显看出来Lora节省计算资源的秘密了。

补充:

  1. 那Lora为什么是低秩?首先我们要明确矩阵的秩的概念,矩阵秩在我们学线性代数中存在的概念,其定义为:矩阵中行(或列)向量线性无关的最大数量。换句话说,换句话说,矩阵的秩表示其可以提供多少个独立的信息维度。如果秩越大,表示矩阵的行(列)越独立,它们不能被其他另外的行(列)进行线性表示获得;相反,如果秩越小,那么表示矩阵的行(列)独立程度低,那么我可以根据其中所有独立的行(列)来得到矩阵所有的行(列)。
  2. 为什么要谈到秩?就是因为你\Delta W可以分解为两个表示来进行表示,那这两个表示为什么不是[1000,100000] * [100000, 200] 呢,这就是为什么利用到秩,因为你两个分解表示里并不是所有信息都需要我去获取的,我只需要获取到其中独立的表示,那矩阵中其他的表示我就都能获取到的,这样的话我还直接获取那些独立的表示就行,因此就利用到了矩阵的秩。

Lora微调的过程

  1. 首先冻结模型参数。使用这些参数进行推理,但不会更新它们。然后创建两个矩阵,当它们相乘时,它们的大小将与我们正在微调的模型的权重矩阵的大小相同。在一个大型模型中,有多个权重矩阵,为每个权重矩阵创建一个这样的配对。

    \Delta W是初始化为0,其中矩阵B初始化为零矩阵,矩阵A随机初始化。两个矩阵相乘也是得到的结果所得到的\Delta W为0,为什么矩阵A不初始化为0,矩阵A的初始化为Kaiming 初始化(也称 He 初始化)是一种针对 ReLU 激活函数设计的初始化方法,它有助于保持激活值在网络层之间传递时具有相似的方差,从而避免梯度消失或爆炸。而矩阵B初始化为0是为了输出\Delta W为0.
  2. LoRA将这些矩阵称为矩阵“A”和“B”。这些矩阵一起代表了LoRA微调过程中的可学习参数。

  3. 将输入通过冻结的权重和变化矩阵传递。

  4. 根据两个输出的组合计算损失,然后根据损失更新矩阵A和B。

这些变化矩阵\Delta W是即时计算的,从未被存储,这就是为什么LoRA的内存占用如此小的原因。实际上,在训练期间只存储模型参数、矩阵A和B以及A和B的梯度。\Delta W = \Delta A \times \Delta B
当我们最终想要使用这个微调模型进行推断时,我们只需计算变化矩阵,并将变化添加到权重中。这意味着LoRA不会改变模型的推断时间

Lora在Transformer的应用

在大模型中(如BERT、GPT-3),全参数微调需要对模型的所有参数进行更新,代价非常高,尤其是当模型规模达到数十亿甚至百亿参数时。

例如

  1. 通常,在Transformer的多头自注意力层中,密集网络(用于构建Q、K和V)的深度只有1。也就是说,只有一个输入层和一个由权重连接的输出层
  2. 这些浅层密集网络是Transformer中大部分可学习参数,非常非常大。可能有超过100,000个输入神经元连接到100,000个输出神经元,这意味着描述其中一个网络的单个权重矩阵可能有10B个参数。因此,尽管这些网络的深度只有1,但它们非常宽,因此描述它们的权重矩阵非常大。

LoRA 认为:

神经网络中某些层的权重矩阵(如自注意力中的 W_q, W_k, W_v, W_o)在特定任务微调时,其更新矩阵是低秩的

因此,LoRA不直接更新原始大权重矩阵 W,而是将权重的变化用一个低秩矩阵来表达,从而减少需要训练的参数数量

Lora Rank

LoRA有一个超参数,称为Rank,它描述了用于构建之前讨论的变化矩阵的深度。较高的值意味着更大的和矩阵,这意味着它们可以在变化矩阵中编码更多的线性独立信息。(联想矩阵的秩)

“r"参数可以被视为"信息瓶颈”。较小的r值意味着A和B可以用更小的内存占用编码较少的信息。较大的r值意味着A和B可以编码更多的信息,但内存占用更大。(100张1块钱,就能够表达一张100块钱,那你给我更多我钱我也愿意啊,能让我住豪宅开跑车我也愿意啊(doge))。

一个具有r值等于1和2的LoRA的概念图。在这两个例子中,分解的A和B矩阵导致相同大小的变化矩阵,但是r=2能够将更多线性独立的信息编码到变化矩阵中,因为A和B矩阵中包含更多信息。

事实证明,LoRA论文所做的核心假设,即模型参数的变化具有低隐式秩(即你用较少独立的行(列)来表示一个完整的矩阵是可行的),是一个相当强的假设。微软(LoRA的出版商)的人员尝试了一些值,并发现即使是秩为一的矩阵也表现出色。

LoRA论文中建议:当数据与预训练中使用的数据相似时,较低的r值可能就足够了。当在非常新的任务上进行微调时,可能需要对模型进行重大的逻辑更改,这时可能需要较高的r值。(遇到新的问题,需要更多信息来辅助判断)

图源:【大模型微调】LoRA — 其实大模型微调也没那么难!_lora微调-CSDN博客

Prefix-Tuning

P-Tuning

Lora Tuning 是针对 encoding部分的微调,而在P-tuning中是针对embedding的微调。

什么是P-tuning?

P-Tuning,它是一种微调大语言模型(Large Language Model, LLM)的方法。与传统的全参数微调(Fine-tuning)不同,P-Tuning 只在模型输入层或中间层插入可学习的“Prompt Embeddings”(也称 Prompt Tokens/Prefix 等),从而极大减少微调参数量。其核心思想可以归纳为:

  • 冻结(freeze)大部分或全部原始模型参数 
  • 引入少量可训练的参数(Prompt Embeddings) 
  • 通过梯度反向传播仅更新这部分可训练参数

通过学习连续的、可训练的“软提示”(soft prompts)来引导预训练模型完成下游任务,而不是像传统微调那样直接修改或微调模型的全部参数。模型在训练过程中会将这些 Prompt Embeddings 拼接到原输入或模型内部隐藏层的输入里,从而让预训练模型更好地针对任务进行表征/生成。因为只训练这部分 Prompt Embeddings,而模型的主体参数并未改变,所以对硬件资源和训练数据需求更小,微调速度也更快。

两阶段对比,Prompt Tuning v.s. P Tuning

第一阶段,Prompt Tuning

冻结主模型全部参数,在训练数据前加入一小段Prompt,只训练Prompt的表示层,即一个Embedding模块。论文实验表明,只要模型规模够大,简单加入 Prompt tokens 进行微调,就能取得很好的效果。

第二阶段,在Prompt Tuning的基础上,对 Prompt部分 进行进一步的encoding计算,加速收敛。具体来说,PEFT中支持两种编码方式,一种是LSTM,一种是MLP。与Prompt-Tuning不同的是,Prompt的形式只有Soft Prompt。

硬提示(Hard Prompt):离散的、人工可读的; 软提示(Soft Prompt):连续的、可训练的。

总结:P Tuning将Prompt转换为可以学习的Embedding层,并用MLP+LSTM的方式来对Prompt Embedding进行一层处理。 

  • 相比Prefix Tuning,P Tuning仅限于输入层,没有在每一层都加virtual token ◦
  • 经过预训练的LM的词嵌入已经变得高度离散,如果随机初始化virtual token,容易优化到局部最优值,而这些virtual token理论是应该有相关关联的。因此,作者通过实验发现用一个prompt encoder来编码会收敛更快,效果更好。即用一个LSTM+MLP去编码这些virtual token以后,再输入到模型。 
  • 作者在实验中发现,相同参数规模,如果进行全参数微调,Bert的在NLU(自然语言理解)任务上的效果,超过GPT很多;但是在P-Tuning下,GPT可以取得超越Bert的效果。

图源:参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2-CSDN博客

P-tuning v.s. Prompt Engineering 

Prompt Engineering 是人工提示工程,属于离散提示。它的做法是通过精心设计的自然语言提示(例如“请完成这个句子:...”)可以诱导模型完成任务,而无需微调。但这需要手动设计和筛选提示,效率低下且效果不稳定。

而P-tuning 则在这两者之间找到了一个平衡点。它的核心思想是:

  • 不再使用离散的、人工设计的自然语言提示。
  • 引入一小段可训练的连续向量(soft prompt)作为模型输入的前缀或嵌入,而不是直接修改模型的内部参数。
  • 在训练过程中,只优化这部分软提示的参数,而冻结预训练模型的绝大部分参数。

P-tuning与Prompt Engineering的区别,关键就在你提示的语言是什么类型的,Prompt Engineering所使用的提示语言是人类语言,而P-tuning所使用的提示语言是我们给预训练模型“悄悄地”加上的一段“指令”,这段指令不是用人类语言写成的,而是模型自己“学出来”的最有效的连续向量,能够最大化地引导模型在特定任务上给出正确的输出。

一张图总结各种Tuning

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/84272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现tdx-hs300-mcp

文章目录 项目简介功能说明使用方法配置说明项目简介 tdx-hs300-mcp是一个Model Context Protocol (MCP)的服务 功能说明 下载数据自动保存为CSV格式文件使用方法 确保已安装Python 3.7+和依赖库: pip install pytdx fastapi uvicorn启动MCP服务: mcp run MCP.py使用MCP工具…

《100天精通Python——基础篇 2025 第20天:Thread类与线程同步机制详解》

目录 一、概念简单回顾二、Python的线程开发2.1 Thread类2.1.1 线程启动2.1.2 线程退出2.1.3 线程的传参2.1.4 threading的属性和方法2.1.5 Thread实例的属性和方法2.1.6 start和run方法 2.2 多线程2.3 线程安全2.4 daemon线程2.5 threading.local类2.6 __slots__拓展 三、线程…

【web应用】前后端分离开源项目联调运行的过程步骤ruoyi

文章目录 ⭐前言⭐一、项目运行环境准备⭐二、数据库创建🌟1、新建数据库🌟2、导入数据脚本 ⭐三、运行后端项目🌟1、打开后端项目🌟2、后端项目配置项修改 ⭐四、运行前端项目VUE3🌟1、在IDEA另一个窗口中打开前端项目…

【深度剖析】三一重工的数字化转型(下篇1)

在数字经济持续发展的背景下,企业数字化转型方案成为实现转型的关键。不同行业内的企业因转型动机和路径的差异,其转型成效也各异。三一重工作为机械制造行业的领军企业,较早地实施了数字化转型,并积累了丰富的经验。本研究选取三一重工作为案例,通过梳理相关文献,对其数…

Nacos适配GaussDB超详细部署流程

1部署openGauss 官方文档下载 https://support.huaweicloud.com/download_gaussdb/index.html 社区地址 安装包下载 本文主要是以部署轻量级为主要教程 1.1系统环境准备 操作系统选择 系统AARCH64X86-64openEuler√√CentOS7√Docker√√1.2软硬件安装环境 版本轻量版(单…

国际前沿知识系列五:时间序列建模方法在头部撞击运动学测量数据降噪中的应用

目录 国际前沿知识系列五:时间序列建模方法在头部撞击运动学测量数据降噪中的应用 一、引言 二、时间序列建模方法 (一)ARIMA 模型 (二)指数平滑法 (三)小波变换 三、实际案例分析 &…

线性代数中的向量与矩阵:AI大模型的数学基石

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…

第十七次CCF-CSP算法(含C++源码)

第十七次CCF-CSP认证 小明种苹果AC代码 小明种苹果&#xff08;续&#xff09;AC代码 后面好难哈哈 小手冰凉 小明种苹果 输入输出&#xff1a; 题目链接 AC代码 #include<iostream> using namespace std; int n,m; int res,res3; int sum; int res21; int main(){cin …

curl常用指令

curl使用记录 curl常用指令安装请求get请求post请求错误排查 curl常用指令 安装 sudo apt update sudo apt install curl -y请求 get请求 curl [URL]如果能正常请求&#xff0c;则会返回正常的页面信息 post请求 发送 JSON 数据​ curl -X POST [URL] -H "Content-…

C++ 输入输出流示例代码剖析

一、开篇&#xff1a;代码核心概述 本文围绕一段融合输入输出流操作、自定义类型重载、文件读写的C代码展开&#xff0c;深入探究其底层原理与实践应用。代码通过类型转换、操作符重载等技术&#xff0c;实现自定义类型与标准输入输出流的交互&#xff0c;同时借助文件流完成数…

常见嵌入式软件架构

常见的嵌入式软件架构 一、ASW文件夹&#xff08;Application Software&#xff0c;应用软件&#xff09;定义与作用常见子目录结构特点 二、BSP文件夹&#xff08;Board Support Package&#xff0c;板级支持包&#xff09;定义与作用常见子目录结构特点 三、OS文件夹&#xf…

【PostgreSQL】数据探查工具1.0研发可行性方案

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 想抢先解锁数据自由的宝子,速速戳我!评论区蹲一波 “蹲蹲”,揪人唠唠你的超实用需求! 【PostgreSQL】数据探查工具1.0研发可行性方案,数据调研之秒解析数据结构,告别熬夜写 SQL【PostgreSQL】数据探查工具…

Lambda表达式与匿名内部类的对比详解

Lambda表达式与匿名内部类的对比详解 1. 语法简洁性 Lambda表达式&#xff1a; 仅适用于函数式接口&#xff08;只有一个抽象方法的接口&#xff09;&#xff0c;语法简洁。 示例&#xff1a; Runnable r () -> System.out.println("Hello Lambda");匿名内部类&…

Seata Server 1.6.1 高可用部署终极指南:Nacos配置中心+DB存储+多实例实战

文章目录 高可用 - 关键因素存储模式配置中心注册中心高可用 - 步骤第 1 步:使用 db 作为存储模式第 2 步:使用 Nacos 配置中心自定义 seata-server 配置添加 seata-server.properties 到 Nacos第 3 步:修改 application.yml使用 Nacos 作为配置中心使用 Nacos 作为注册中心…

JS 中判断 null、undefined 与 NaN 的权威方法及场景实践

在 JavaScript 中&#xff0c;null、undefined 和 NaN 是三个特殊的「非正常值」&#xff0c;正确判断它们是保证代码健壮性的关键。本文结合 ECMA 规范与 MDN 权威文档&#xff0c;系统梳理三者的判断方法、原理及典型场景&#xff0c;帮助开发者规避常见误区。 一、理解三个…

基于DenseNet的医学影像辅助诊断系统开发教程

本文源码地址: https://download.csdn.net/download/shangjg03/90873921 1. 简介 本教程将使用DenseNet开发一个完整的医学影像辅助诊断系统,专注于胸部X光片的肺炎检测。我们将从环境搭建开始,逐步介绍数据处理、模型构建、训练、评估以及最终的系统部署。 2. 环境准备<…

ubuntu ollama /Dify/Docker部署大模型

电脑需要显卡&#xff1a; 执行下载并安装&#xff1a; curl -fsSL https://ollama.com/install.sh | sh 安装完后到Ollama Search 中查看ollama 可以部署的模型有哪些&#xff1a; 我选择gemma3,所以执行&#xff1a; ollma pull gemma3:latest 这样就把gemma3:latest 模…

课程发布与学习流程全解析

流程 课程发布Controller 获取课程发布信息 ApiOperation("获取课程发布信息") ResponseBody GetMapping("/course/whole/{courseId}") public CoursePreviewDto getPreviewInfo(PathVariable("courseId") Long courseId) {CoursePreviewDto c…

Linux的读写屏障

在 Linux 中&#xff0c;读写屏障&#xff08;Read-Write Barriers&#xff0c;简称 RWB&#xff09;是对内存访问顺序的一种控制机制&#xff0c;用来保证在多核处理器环境下&#xff0c;内存访问的正确顺序&#xff0c;避免因乱序执行导致的数据一致性问题。它是操作系统内核…

Spring AI 和 Elasticsearch 作为你的向量数据库

作者&#xff1a;来自 Elastic Josh Long, Philipp Krenn 及 Laura Trotta 使用 Spring AI 和 Elasticsearch 构建一个完整的 AI 应用程序。 Elasticsearch 原生集成了业界领先的生成式 AI 工具和服务提供商。查看我们关于超越 RAG 基础或使用 Elastic 向量数据库构建生产级应用…