【llm对话系统】大模型 Llama 源码分析之 LoRA 微调
1. 引言
微调 (Fine-tuning) 是将预训练大模型 (LLM) 应用于下游任务的常用方法。然而,直接微调大模型的所有参数通常需要大量的计算资源和内存。LoRA (Low-Rank Adaptation) 是一种高效的微调方法,它通过引入少量可训练参数,固定预训练模型的权重,从而在保持性能的同时大大减少了计算开销。
本文将深入分析 LoRA 的原理,并结合 Llama 源码解读其实现逻辑,最后探讨 LoRA 的优势。
2. LoRA 原理
LoRA 的核心思想是:预训练模型中已经包含了大量的低秩 (low-rank) 特征,微调时只需要对这些低秩特征进行微调即可。
具体来说,LoRA 假设权重更新矩阵 ΔW 也是低秩的。对于一个预训练的权重矩阵 W ∈ R^(d×k),LoRA 将其更新表示为:
W' = W + ΔW = W + BA
其中:
W是预训练的权重矩阵。ΔW是权重更新矩阵。B ∈ R^(d×r)和A ∈ R^(r×k)是两个低秩矩阵,r远小于d和k,r被称为 LoRA 的秩 (rank)。
在训练过程中,W 被冻结,只有 A 和 B 是可训练的。
直观理解:
可以将 W 看作一个编码器,将输入 x 编码成一个高维表示 Wx。LoRA 认为,在微调过程中,我们不需要完全改变这个编码器,只需要通过 BA 对其进行一个低秩的调整即可。
3. Llama 中 LoRA 的实现
虽然 Llama 官方代码没有直接集成 LoRA,但我们可以使用一些流行的库 (例如 peft by Hugging Face) 来实现 Llama 的 LoRA 微调。peft 库提供了 LoraConfig 和 get_peft_model 等工具,可以方便地将 LoRA 应用于各种 Transformer 模型。
3.1 使用 peft 库实现 Llama 的 LoRA 微调
以下是一个使用 peft 库实现 Llama 的 LoRA 微调的简化示例:
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import get_peft_model, LoraConfig, TaskType# 加载预训练的 Llama 模型和分词器
model_name = "meta-llama/Llama-2-7b-hf" # 假设使用 Llama 2 7B
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)# LoRA 配置
config = LoraConfig(task_type=TaskType.CAUSAL_LM,inference_mode=False,r=8, # LoRA 的秩lora_alpha=32, # LoRA 的缩放因子lora_dropout=0.1, # Dropout 比例target_modules=["q_proj", "v_proj"], # 需要应用 LoRA 的模块
)# 获取支持 LoRA 的模型
model = get_peft_model(model, config)# 打印可训练参数的比例
model.print_trainable_parameters()# ... (加载数据,进行训练) ...
代码解释:
- 加载预训练模型:使用
transformers库加载预训练的 Llama 模型和分词器。 - LoRA 配置:创建一个
LoraConfig对象,指定 LoRA 的配置参数:task_type:任务类型,这里是因果语言模型 (Causal Language Modeling)。r:LoRA 的秩。lora_alpha:LoRA 的缩放因子,用于控制 LoRA 模块的权重。lora_dropout:Dropout 比例。target_modules: 指定需要应用 LoRA 的模块, 通常是注意力层中的q_proj,v_proj, 还可以是k_proj,o_proj,gate_proj,up_proj,down_proj等。不同的模型需要根据实际情况配置。
- 获取支持 LoRA 的模型:使用
get_peft_model函数将原始的 Llama 模型转换为支持 LoRA 的模型。 - 打印可训练参数:使用
model.print_trainable_parameters()可以查看模型中可训练参数的比例,通常 LoRA 的可训练参数比例非常小。
3.2 peft 库中 LoRA 的实现细节 (部分)
peft 库中 LoraModel 类的部分代码 (为了清晰起见,已进行简化):
class LoraModel(torch.nn.Module):# ...def _find_and_replace(self, model):# ... (遍历模型的每一层) ...if isinstance(module, nn.Linear) and name in self.config.target_modules:new_module = Linear(module.in_features,module.out_features,bias=module.bias is not None,r=self.config.r,lora_alpha=self.config.lora_alpha,lora_dropout=self.config.lora_dropout,)# ... (将原模块的权重赋值给新模块) ...# ...class Linear(nn.Linear):def __init__(self,in_features: int,out_features: int,r: int = 0,lora_alpha: int = 1,lora_dropout: float = 0.0,**kwargs,):super().__init__(in_features, out_features, **kwargs)# LoRA 参数self.r = rself.lora_alpha = lora_alpha# 初始化 A 和 Bif r > 0:self.lora_A = nn.Parameter(torch.randn(r, in_features))self.lora_B = nn.Parameter(torch.zeros(out_features, r)) # B 初始化为全 0self.scaling = self.lora_alpha / self.rdef forward(self, x: torch.Tensor):result = F.linear(x, self.weight, bias=self.bias) # W @ xif self.r > 0:result += (self.lora_B @ self.lora_A @ x.transpose(-2, -1) # (B @ A) @ x).transpose(-2, -1) * self.scalingreturn result
代码解释:
_find_and_replace函数:遍历模型的每一层,找到需要应用 LoRA 的线性层 (例如,q_proj,v_proj),并将其替换为Linear层。Linear类:继承自nn.Linear,并添加了 LoRA 的参数lora_A和lora_B。lora_A初始化为随机值。lora_B初始化为全 0,这是为了保证在训练开始时,LoRA 部分的输出为 0,不影响预训练模型的原始行为。scaling是一个缩放因子,用于控制 LoRA 模块的权重。
forward函数:F.linear(x, self.weight, bias=self.bias)计算原始的线性变换W @ x。(self.lora_B @ self.lora_A @ x.transpose(-2, -1)).transpose(-2, -1) * self.scaling计算 LoRA 部分的输出(B @ A) @ x,并乘以缩放因子。- 将两者相加,得到最终的输出。
4. LoRA 的优势
- 高效的参数利用:LoRA 只需微调少量的参数 (A 和 B),而冻结了预训练模型的大部分参数,大大减少了训练时的内存占用和计算开销。
- 快速的训练速度:由于可训练参数较少,LoRA 的训练速度通常比全量微调快得多。
- 防止过拟合:LoRA 的低秩约束起到了一定的正则化作用,有助于防止过拟合。
- 性能相当:在许多任务上,LoRA 可以达到与全量微调相当的性能。
- 易于部署:训练完成后,可以将
W和BA相加,得到新的权重矩阵W',然后像使用原始的预训练模型一样进行部署,无需额外的计算开销。
相关文章:
【llm对话系统】大模型 Llama 源码分析之 LoRA 微调
1. 引言 微调 (Fine-tuning) 是将预训练大模型 (LLM) 应用于下游任务的常用方法。然而,直接微调大模型的所有参数通常需要大量的计算资源和内存。LoRA (Low-Rank Adaptation) 是一种高效的微调方法,它通过引入少量可训练参数,固定预训练模型…...
蓝桥杯刷题DAY2:二维前缀和 一维前缀和 差分数组
闪耀的灯光 📌 题目描述 蓝桥公园是一个适合夜间散步的好地方,公园可以被视为由 n m 个矩形区域构成。每个区域都有一盏灯,初始亮度为 a[i][j]。 小蓝可以选择一个大的矩形区域,并按下开关一次,这将使得该区域内每盏…...
网件r7000刷回原厂固件合集测评
《网件R7000路由器刷回原厂固件详解》 网件R7000是一款备受赞誉的高性能无线路由器,其强大的性能和可定制性吸引了许多高级用户。然而,有时候用户可能会尝试第三方固件以提升功能或优化网络性能,但这也可能导致一些问题,如系统不…...
算法随笔_35: 每日温度
上一篇:算法随笔_34: 最后一个单词的长度-CSDN博客 题目描述如下: 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升…...
C++初阶 -- 手撕string类(模拟实现string类)
目录 一、string类的成员变量 二、构造函数 2.1 无参版本 2.2 有参版本 2.3 缺省值版本 三、析构函数 四、拷贝构造函数 五、c_str函数 六、operator重载 七、size函数 八、迭代器iterator 8.1 正常版本 8.2 const版本 九、operator[] 9.1 正常版本 9.2 const版…...
【Unity3D】实现2D角色/怪物死亡消散粒子效果
核心:这是一个Unity粒子系统自带的一种功能,可将粒子生成控制在一个Texture图片网格范围内,并且粒子颜色会自动采样图片的像素点颜色,之后则是粒子编辑出消散效果。 Particle System1物体(爆发式随机速度扩散10000个粒…...
构建一个数据分析Agent:提升分析效率的实践
在上一篇文章中,我们讨论了如何构建一个智能客服Agent。今天,我想分享另一个实际项目:如何构建一个数据分析Agent。这个项目源于我们一个金融客户的真实需求 - 提升数据分析效率,加快决策速度。 从分析师的痛点说起 记得和分析师团队交流时的场景: 小张ÿ…...
85.[1] 攻防世界 WEB easyphp
进入靶场 属于代码审计 <?php // 高亮显示当前 PHP 文件的源代码,常用于调试或展示代码 highlight_file(__FILE__);// 初始化两个标志变量,用于后续条件判断 $key1 0; $key2 0;// 从 GET 请求中获取参数 a 和 b $a $_GET[a]; $b $_GET[b];// 检…...
嵌入式硬件篇---CPUGPUTPU
文章目录 第一部分:处理器CPU(中央处理器)1.通用性2.核心数3.缓存4.指令集5.功耗和发热 GPU(图形处理器)1.并行处理2.核心数量3.内存带宽4.专门的应用 TPU(张量处理单元)1.为深度学习定制2.低精…...
pytorch图神经网络处理图结构数据
人工智能例子汇总:AI常见的算法和例子-CSDN博客 图神经网络(Graph Neural Networks,GNNs)是一类能够处理图结构数据的深度学习模型。图结构数据由节点(vertices)和边(edges)组成&a…...
海外问卷调查,最常用到的渠道查有什么特殊之处
市场调研,包含市场调查和市场研究两个步骤,是企业和机构根据经营方向而做出的决策问题,最终通过海外问卷调查中的渠道查,来系统地设计、收集、记录、整理、分析、研究市场反馈的工作流程。 市场调研的工作流程包括:确…...
【Uniapp-Vue3】解决uni-popup弹窗在安全区显示透明问题
我们在使用uni-popup时,如果想要给弹出内容添加一个背景颜色,我们会发现在安全区域是不显示该背景颜色的。 首先根据如下的目录结构找到uni-popup.vue文件 在该文件中找到bottom配置,将红箭头所指代码注释掉 下面的安全区域就没有了ÿ…...
什么是麦克斯韦方程
飞书链接,格式更好,⭐⭐⭐:长尾 - 什么是麦克斯韦方程 基于作者的内容,做了一些扩展(问了 DeepSeek) 最美的公式:你也能懂的麦克斯韦方程组(积分篇) 04通量的引入 用一个…...
webrtc peerconnection_client peerconnection_server 连接失败问题解决 win10 win11
0 常见问题 (1) webrtc peerconnection_client 连接 peerconnection_server 无连接列表 (2)连接导致崩溃debug状态下因为这个断言 RTC_DCHECK_RUN_ON(&capture_checker_); 1 在 peerconnection\client\main.cc 当中 定义类 class CustomSock…...
项目练习:重写若依后端报错cannot be cast to com.xxx.model.LoginUser
文章目录 一、情景说明二、解决办法 一、情景说明 在重写若依后端服务的过程中 使用了Redis存放LoginUser对象数据 那么,有存就有取 在取值的时候,报错 二、解决办法 方法1、在TokenService中修改如下 getLoginUser 方法中:LoginUser u…...
2025年2月1日(Keep calm and code Python)
“Keep calm and code Python” 的意思是 “保持冷静,编写 Python 代码”。 这句话来源于 “Keep Calm and Carry On”(保持冷静,继续前进),这是二战时期英国政府的宣传口号。后来,这种句式被广泛模仿&…...
核心集:DeepCore: A Comprehensive Library for CoresetSelection in Deep Learning
目录 一、TL;DR 二、为什么研究核心集? 三、问题定义和如何做 3.1 问题定义 3.2 业界方法 3.2.1 基于几何的方法 3.2.2 基于不确定性的方法 3.2.3 基于误差/损失的方法 3.2.5 GraNd 和 EL2N 分数 3.2.6 重要性采样 3.2.7 基于决策边界的办法 …...
Hot100之矩阵
73矩阵置零 题目 思路解析 收集0位置所在的行和列 然后该行全部初始化为0 该列全部初始化为0 代码 class Solution {public void setZeroes(int[][] matrix) {int m matrix.length;int n matrix[0].length;List<Integer> list1 new ArrayList<>();List<…...
可视化相机pose colmap形式的相机内参外参
目录 内参外参转换 可视化相机pose colmap形式的相机内参外参 内参外参转换 def visualize_cameras(cameras, images):fig plt.figure()ax fig.add_subplot(111, projection3d)for image_id, image_data in images.items():qvec image_data[qvec]tvec image_data[tvec]#…...
第十二章 I 开头的术语
文章目录 第十二章 I 开头的术语以 I 开头的术语被识别 (identified by)识别关系 (identifying relationship)身份 (identity)idkey隐式全局引用 (implicit global reference)隐含命名空间 (implied namespace)包含文件 (include file)传入锁 (incoming lock) 索引 (index)索引…...
C# 类与对象详解
.NET学习资料 .NET学习资料 .NET学习资料 在 C# 编程中,类与对象是面向对象编程的核心概念。它们让开发者能够将数据和操作数据的方法封装在一起,从而构建出模块化、可维护且易于扩展的程序。下面将详细介绍 C# 中类与对象的相关知识。 一、类的定义 …...
Windsurf cursor vscode+cline 与Python快速开发指南
Windsurf简介 Windsurf是由Codeium推出的全球首个基于AI Flow范式的智能IDE,它通过强大的AI助手功能,显著提升开发效率。Windsurf集成了先进的代码补全、智能重构、代码生成等功能,特别适合Python开发者使用。 Python环境配置 1. Conda安装…...
深度解析:网站快速收录与服务器性能的关系
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/37.html 网站快速收录与服务器性能之间存在着密切的关系。服务器作为网站运行的基础设施,其性能直接影响到搜索引擎对网站的抓取效率和收录速度。以下是对这一关系的深度解析&am…...
Linux tr 命令使用详解
简介 tr (translate)命令用于在 Linux 中翻译或删除输入流(通常是 stdin )中的字符。它主要用于文本操作,并且可以作为转换或删除文本文件或流中的特定字符的方便工具。 基本语法 tr [OPTION] [SET1] [SET2]SET1&am…...
数据库内存与Buffer Pool
数据库内存与Buffer Pool 文章目录 数据库内存与Buffer Pool一:MySQL内存结构1:MySQL工作组件2:工作线程的本地内存3:共享内存区域4:存储引擎缓冲区 二:InnoDB的核心:Buffer Pool1:数…...
程序员学英文之At the Airport Customs
Dialogue-1 Making Airline Reservation预定机票 My cousin works for Xiamen Airlines. 我表哥在厦航上班。I’d like to book an air ticket. 我想预定一张机票。Don’t judge a book by its cover. 不要以貌取人。I’d like to book / re-serve a table for 10. 我想预定一…...
Redis代金卷(优惠卷)秒杀案例-单应用版
优惠卷表:优惠卷基本信息,优惠金额,使用规则 包含普通优惠卷和特价优惠卷(秒杀卷) 优惠卷的库存表:优惠卷的库存,开始抢购时间,结束抢购时间.只有特价优惠卷(秒杀卷)才需要填写这些信息 优惠卷订单表 卷的表里已经有一条普通优惠卷记录 下面首先新增一条秒杀优惠卷记录 { &quo…...
51单片机 01 LED
一、点亮一个LED 在STC-ISP中单片机型号选择 STC89C52RC/LE52RC;如果没有找到hex文件(在objects文件夹下),在keil中options for target-output- 勾选 create hex file。 如果要修改编程 :重新编译-下载/编程-单片机重…...
MusicFree-开源的第三方音乐在线播放和下载工具, 支持歌单导入[对标落雪音乐]
MusicFree 链接:https://pan.xunlei.com/s/VOI0RrVLTTWE9kkpt0U7ofGBA1?pwd4ei6#...
消息队列篇--原理篇--常见消息队列总结(RabbitMQ,Kafka,ActiveMQ,RocketMQ,Pulsar)
1、RabbitMQ 特点: AMQP协议:RabbitMQ是基于AMQP(高级消息队列协议)构建的,支持多种消息传递模式,如发布/订阅、路由、RPC等。多语言支持:支持多种编程语言的客户端库,包括Java、P…...
