【大模型】基于LoRA微调Gemma大模型(1)

文章目录

  • 一、LoRA工作原理
    • 1.1 基本原理
    • 1.2 实现步骤
  • 二、LoRA 实现
    • 2.1 PEFT库:高效参数微调
      • LoraConfig类:配置参数
    • 2.2 TRL库
      • SFTTrainer 类
  • 三、代码实现
    • 3.1 核心代码
    • 3.2 完整代码
  • 参考资料

大模型微调技术有很多,如P-TuningLoRA 等,我们在之前的博客中也介绍过,可以参考:大模型高效参数微调技术(Prompt-Tuning、Prefix Tuning、P-Tuning、LoRA…)

在本篇文章中,我们就 LoRA (Low-Rank Adaptation) 即低秩适应的微调方法工作原理及代码实践进行介绍。

完整的微调步骤可以参考我们的博客:【大模型】基于LoRA微调Gemma大模型(2)

一、LoRA工作原理

1.1 基本原理

LoRA 是 Low-Rank Adaptation 或 Low-Rank Adaptors的首字母缩写词,它提供了一种高效且轻量级的方法,用于微调预先训练好的的大语言模型。

LoRA的核心思想是用一种低秩的方式来调整这些参数矩阵。LoRA通过保持预训练矩阵(即原始模型的参数)冻结(即处于固定状态),并且只在原始矩阵中添加一个小的增量,其参数量比原始矩阵少很多。

例如,考虑矩阵 W,它可以是全连接层的参数,也可以是来Transformer中计算自注意力机制的矩阵之一:

显然,如果 W o r i g W_{orig} Worig 的维数为 n×m,而假如我们只是初始化一个具有相同维数的新的增量矩阵进行微调,虽然我们也实现类似的功能,但是我们的参数量将会加倍。 LoRA使用的Trick就是通过训练低维矩阵 B 和 A ,通过矩阵乘法来构造 ΔW ,来使 ΔW 的参数量低于原始矩阵。

这里我们不妨定义秩 r,它明显小于基本矩阵维度 r≪n 和 r≪m。则矩阵 B 为 n×r,矩阵 A 为 r×m。将它们相乘会得到一个维度为 nxm的W 矩阵,但构建的参数量减小了很多。

LoRA原理见下图:具体来说就是固定原始模型权重,然后定义两个低秩矩阵作为新增weight参与运算,并将两条链路的结果求和后作为本层的输出,而在微调时,只梯度下降新增的两个低秩矩阵。

此外,我们希望我们的增量ΔW在训练开始时为零,这样微调就会从原始模型一样开始。因此,B通常初始化为全零,而 A初始化为随机值(通常呈正态分布)。

1.2 实现步骤

(1)选择目标层

首先,在预训练神经网络模型中选择要应用LoRA的目标层。这些层通常是与特定任务相关的,如自注意力机制中的查询Q和键K矩阵。

值得注意的是,原则上,我们可以将LoRA应用于神经网络中权矩阵的任何子集,以减少可训练参数的数量。在Transformer体系结构中,自关注模块(Wq、Wk、Wv、Wo)中有四个权重矩阵,MLP模块中有两个权重矩阵。我们将Wq(或Wk,Wv)作为维度的单个矩阵,尽管输出维度通常被切分为注意力头。

(2)初始化映射矩阵和逆映射矩阵

为目标层创建两个较小的矩阵A和B,然后进行变换。

参数变换过程:将目标层的原始参数矩阵W通过映射矩阵A和逆映射矩阵B进行变换,计算公式为: W ′ = W + A ∗ B W' = W + A * B W=W+AB,这里W’是变换后的参数矩阵。

其中,矩阵的大小由LoRA的秩(rank)和alpha值确定。
在这里插入图片描述

(3)微调模型
使用新的参数矩阵替换目标层的原始参数矩阵,然后在特定任务的训练数据上对模型进行微调。

(4)梯度更新
在微调过程中,计算损失函数关于映射矩阵A和逆映射矩阵B的梯度,并使用优化算法(如Adam、SGD等)对A和B进行更新。

注意:在更新过程中,原始参数矩阵W保持不变。其实也就是训练的时候固定原始PLM的参数,只训练降维矩阵A与升维矩阵B (W is frozen and does not receive gradient updates, while A and B contain trainableparameters )

(5)重复更新
在训练的每个批次中,重复步骤3-5,直到达到预定的训练轮次(epoch)或满足收敛条件。

且当需要切换到另一个下游任务时,可以通过减去B A然后添加不同的B’ A’来恢复W,这是一个内存开销很小的快速操作。

When we need to switch to another downstream task, we can recover W0 by subtracting BA andthen adding a different B0A0, a quick operation with very little memory overhead.

总之,LoRA的详细步骤包括:选择目标层、初始化映射矩阵和逆映射矩阵、进行参数变换和模型微调。在微调过程中,模型会通过更新映射矩阵U和逆映射矩阵V来学习特定任务的知识,从而提高模型在该任务上的性能。

二、LoRA 实现

这里主要介绍几个与 LoRA 实现相关的类库。

2.1 PEFT库:高效参数微调

Huggingface公司推出的 PEFT (Parameter-Efficient Fine-Tuning,即高效参数微调之意) 库封装了LoRA这个方法,PEFT库可以使预训练语言模型高效适应各种下游任务,而无需微调模型的所有参数,即仅微调少量(额外)模型参数,从而大大降低了计算和存储成本。

peft:全称为Parameter-Efficient Fine-Tuning,PEFT。peft是一种专门为高效调参而设计的深度学习库,其使用了类似于只是蒸馏的技术,通过在预训练模型上添加少量数据来进行微调,从而实现将预训练模型的知识迁移到新的微调模型中。
Github地址:https://github.com/huggingface/peft

LoraConfig类:配置参数

from peft import LoraConfig

LoraConfig是Hugging Face transformers库中用于配置LoRA(Low-Rank Adaptation)的类。LoraConfig允许用户设置以下关键参数来定制LoRA训练:

  • r: 低秩矩阵的秩,即添加的矩阵的第二维度,控制了LoRA的参数量。
  • alpha: 权重因子,用于在训练后将LoRA适应的权重与原始权重相结合时的缩放。
  • lora_dropout: LoRA层中的dropout率,用于正则化。
  • target_modules: 指定模型中的哪些模块(层)将应用LoRA适应。这允许用户集中资源在对任务最相关的部分进行微调。
  • bias: 是否在偏置项上应用LoRA,通常设置为’none’或’all’。
  • task_type: 指定任务类型,如’CAUSAL_LM’,以确保LoRA适应正确应用到模型的相应部分。

2.2 TRL库

trl 库:全称为Transformer Reinforcement Learning,TRL是使用强化学习的全栈Transformer语言模型。trl 是一个全栈库,其中我们提供一组工具,用于通过强化学习训练Transformer语言模型和稳定扩散模型,从监督微调步骤(SFT)到奖励建模步骤(RM)再到近端策略优化(PPO)步骤。该库建立在Hugging Face 的 transformers 库之上。
Github地址:TRL - Transformer Reinforcement Learning

SFTTrainer 类

from trl import SFTTrainer

SFTTrainertransformers.Trainer的子类,增加了处理PeftConfig的逻辑,可轻松在自定义数据集上微调语言模型或适配器。

三、代码实现

3.1 核心代码

(1)训练阶段

  • LoraConfig:定义LoRA微调参数
from peft import LoraConfiglora_config = LoraConfig(r=8,# lora_alpha=16,target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],# lora_dropout=0.05,task_type="CAUSAL_LM",  # 因果语言模型
)
  • SFTTrainer:基于Lora进行微调
from trl import SFTTrainertrainer = SFTTrainer(model=model,train_dataset=data["train"],args=transformers.TrainingArguments(per_device_train_batch_size=1,gradient_accumulation_steps=4,warmup_steps=2,max_steps=10,  # 最大迭代次数learning_rate=2e-4,fp16=True,logging_steps=1,output_dir="./outputs/gemma-new",  # 微调后模型的输出路径optim="paged_adamw_8bit"),peft_config=lora_config,formatting_func=formatting_func,
)# 开始训练
trainer.train()

(2)推理阶段

训练完成后,我们需要将 LoRA 模型基础模型 进行合并,来进行推理。核心代码如下:

base_model_path = "./model/gemma-2b"   
peft_model_path = "./outputs/gemma-new/checkpoint-500"base_model = AutoModelForCausalLM.from_pretrained(base_model_path, return_dict=True,  device_map=device, torch_dtype=torch.float16)
tokenizer = AutoTokenizer.from_pretrained(base_model_path)
# print(model)# 加载LoRA模型(基础模型+微调模型)
merged_model = PeftModel.from_pretrained(base_model, peft_model_path)
# print(model)

3.2 完整代码

这里,我们以微调gemma-2b 模型为例,完整的微调步骤可以参考博客:【大模型】基于LoRA微调Gemma大模型(2)

主要包含 train.pyinfer.py 两个文件,具体代码如下:

  • train.py
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '1'import torch
import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from datasets import load_dataset
from peft import LoraConfig
from trl import SFTTrainerdevice = "cuda:0"# 定义量化参数
bnb_config = BitsAndBytesConfig(load_in_4bit=True,  # 启用4位加载bnb_4bit_quant_type="nf4",  # 指定用于量化的数据类型。支持两种量化数据类型: fp4 (四位浮点)和 nf4 (常规四位浮点)bnb_4bit_compute_dtype=torch.bfloat16  # 用于线性层计算的数据类型
)model_path = "./model/gemma-2b"   # chatglm2-6b, gemma-2b
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True, device_map=device)  # quantization_config=bnb_config# 测试原始模型的输出
text = "Quote: Imagination is more"
inputs = tokenizer(text, return_tensors="pt").to(device)
outputs = model.generate(**inputs, max_new_tokens=30)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))# 加载微调数据集
# data = load_dataset(data_path)   # 加载远程数据集
data_path = "./data/english_quotes/quotes.jsonl"  # 本地数据文件路径
data = load_dataset('json', data_files=data_path)   # 加载本地数据文件
data = data.map(lambda samples: tokenizer(samples["quote"]), batched=True)
print(data)# 定义格式化函数
def formatting_func(example):raise RuntimeError("if you can read this, formatting_func was called")text = f"Quote: {example['quote'][0]}\nAuthor: {example['author'][0]}<eos>"return [text]print(formatting_func(data["train"]))# 定义LoRA微调参数
lora_config = LoraConfig(r=8,# lora_alpha=16,target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],# lora_dropout=0.05,task_type="CAUSAL_LM",  # 因果语言模型
)# 基于Lora进行微调
trainer = SFTTrainer(model=model,train_dataset=data["train"],args=transformers.TrainingArguments(per_device_train_batch_size=1,gradient_accumulation_steps=4,warmup_steps=2,max_steps=10,  # 最大迭代次数learning_rate=2e-4,fp16=True,logging_steps=1,output_dir="./outputs/gemma-new",  # 微调后模型的输出路径optim="paged_adamw_8bit"),peft_config=lora_config,formatting_func=formatting_func,
)trainer.train()
# trainer.save_model(trainer.args.output_dir)
  • infer.py
import torch
from peft import PeftModel, PeftConfig
from transformers import AutoModelForCausalLM, AutoTokenizerdevice = "cuda:1"base_model_path = "./model/gemma-2b"   # chatglm2-6b, gemma-2b
peft_model_path = "./outputs/gemma-new/checkpoint-500"base_model = AutoModelForCausalLM.from_pretrained(base_model_path, return_dict=True,  device_map=device, torch_dtype=torch.float16)
tokenizer = AutoTokenizer.from_pretrained(base_model_path)
# print(model)# 加载LoRA模型(基础模型+微调模型)
merged_model = PeftModel.from_pretrained(base_model, peft_model_path)
# print(model)# 测试1
text = "Quote: Imagination is more"
inputs = tokenizer(text, return_tensors="pt").to(device)

参考资料

  • google/gemma-7b官方示例:https://huggingface.co/google/gemma-7b/blob/main/examples/notebook_sft_peft.ipynb

  • 使用 Hugging Face 微调 Gemma 模型

  • 【AI大模型】Transformers大模型库(八):大模型微调之LoraConfig

  • 【机器学习】QLoRA:基于PEFT亲手量化微调Qwen2大模型

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

狗都能看懂的Actor-Critic强化学习算法讲解

Review Policy Gradient 上面的公式是Policy Gradient的更新函数&#xff0c;这个式子是指在 s t s_t st​时刻采取了 a t a_t at​&#xff0c;计算出对应发生的概率 p θ p_\theta pθ​&#xff0c;然后计算在采取了这个 a t a_t at​之后&#xff0c;所得到的reward有多大。…

table car vs. table cars:数据库命名用单数还是复数?

数据库的命名方式已经形成了许多共识&#xff0c;比如全部小写、下划线分隔、使用标准缩写等&#xff1b;其中就包括「使用单数名词」。 用户 jonr 在 reddit 网的程序员笑话&#xff08;ProgrammerHumor&#xff09;社区发了一篇帖子&#xff0c;调侃这些数据库命名方式的共识…

Hive3:基本介绍

一、概述 Apache Hive是一款分布式SQL计算的工具&#xff0c; 其主要功能是&#xff1a; 将SQL语句翻译成MapReduce程序运行 二、基本逻辑简介 主要由两大模块组成&#xff1a;元数据管理&#xff0c;SQL解析器 1、元数据管理 即&#xff1a;数据位置信息、数据结构信息、…

在jmeter中使用javascript脚本

工作上遇到一个压力测试的需求&#xff0c;需要测试几个考试相关的接口。其中有一个获取试题详情的接口&#xff0c;和一个提交答题信息的接口。后一个接口以上一接口的返回内容为参数&#xff0c;添加上用户的答案即可。jmeter提供了非常多的方式可以实现该需求&#xff0c;这…

Multi Range Read与Covering Index是如何优化回表的?

上篇文章末尾我们提出一个问题&#xff1a;有没有什么办法可以尽量避免回表或让回表的开销变小呢&#xff1f; 本篇文章围绕这个问题提出解决方案&#xff0c;一起来看看MySQL是如何优化的 回表 为什么会发生回表&#xff1f; 因为使用的索引并没有整条记录的所有信息&…

Vue3 Pinia/组件通信

2. pinaia 符合直觉的Vue.js状态管理库 集中式状态&#xff08;数据&#xff09;管理 官网 2.1 搭建pinaia环境 第一步&#xff1a;npm install pinia 第二步&#xff1a;操作src/main.ts import { createApp } from vue import App from ./App.vue/* 引入createPinia&…

案例分析:人工智能在航空航天领域的应用

作者主页: 知孤云出岫 目录 作者主页:案例分析&#xff1a;人工智能在航空航天领域的应用引言人工智能在航空航天中的主要应用案例分析案例一&#xff1a;AI优化航天器设计案例二&#xff1a;AI辅助飞行安全——预测维护案例三&#xff1a;AI自动驾驶系统案例四&#xff1a;A…

关键词查找【Boyer-Moore 算法】

1、【Boyer-Moore 算法】 【算法】哪种算法有分数复杂度&#xff1f;- BoyerMoore字符串匹配_哔哩哔哩_bilibili BM算法的精华就在于BM(text, pattern),也就是BM算法当不匹配的时候一次性可以跳过不止一个字符。即它不需要对被搜索的字符串中的字符进行逐一比较&#xff0c;而…

探索算法系列 - 滑动窗口

目录 长度最小的子数组&#xff08;原题链接&#xff09; 无重复字符的最长子串&#xff08;原题链接&#xff09; 最大连续1的个数 III&#xff08;原题链接&#xff09; 将 x 减到 0 的最小操作数&#xff08;原题链接&#xff09; 水果成篮&#xff08;原题链接&#x…

第六章:支持向量机

目录 6.1 间隔与支持向量 6.2 对偶问题 6.3 核函数 6.4 软间隔与正则化 6.4.1 软间隔 6.4.2 正则化 6.5 支持向量回归 6.6 核方法 6.1 间隔与支持向量 分类学习最基本的想法就是基于训练集D在样本空间中找到一个划分超平面,将不同类别的样本分开.但能将训练样本分开的…

【宝藏系列】模/数转换十大常用滤波算法

【宝藏系列】模/数转换十大常用滤波算法 文章目录 【宝藏系列】模/数转换十大常用滤波算法&#x1f468;‍&#x1f3eb;ADC&#xff08;Analog-to-Digital Converter&#xff0c;模数转换器&#xff09;1️⃣限幅滤波法2️⃣中位值滤波法3️⃣算术平均滤波法4️⃣递推平均滤波…

PLC通过IGT-SER系列智能网关快速实现WebService接口调用案例

IGT-SER系列智能网关支持PLC设备数据对接到各种系统平台&#xff0c;包括SQL数据库&#xff0c;以及MQTT、HTTP协议的数据服务端&#xff1b;通过其边缘计算功能和脚本生成的工具软件&#xff0c;非常方便快速实现PLC、智能仪表与WebService服务端通信。 本文是通过智能网关读取…

Ubuntu 22.04.4 LTS (linux) GoAccess 分析 Nginx 日志

1 安装goaccess sudo apt-get update sudo apt-get install goaccess 2 控制台运行 goaccess -a -d -f /usr/local/openresty/nginx/logs/access.log -p /etc/goaccess/goaccess.conf #sudo vim /etc/goaccess/goaccess.conf time-format %H:%M:%S date-format %d/%b…

van-dialog 组件调用报错

报错截图 报错原因 这个警告表明 vue 在渲染页面时遇到了一个未知的自定义组件 <van-dialog>&#xff0c;并且提示可能是由于未正确注册该组件导致的。在 vue 中&#xff0c;当我们使用自定义组件时&#xff0c;需要先在 vue 实例中注册这些组件&#xff0c;以便 vue 能…

Emacs之解决无法输入中文问题(一百四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

基于YOLO8的目标检测系统:开启智能视觉识别之旅

文章目录 在线体验快速开始一、项目介绍篇1.1 YOLO81.2 ultralytics1.3 模块介绍1.3.1 scan_task1.3.2 scan_taskflow.py1.3.3 target_dec_app.py 二、核心代码介绍篇2.1 target_dec_app.py2.2 scan_taskflow.py 三、结语 在线体验 基于YOLO8的目标检测系统 基于opencv的摄像头…

Provisional headers are shown Learn more

Provisional headers are shown Learn more 目录 Provisional headers are shown Learn more 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医…

什么情况下的网站要使用CDN加速呢?

CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。 CDN的通俗理解就是网站加速&#xff0c;CPU均衡负载&#xff0c;可以解决跨运营商&#xff0c;跨地区&#xff0c;服务器负载能力过低&#xff0c;带宽过少等带来的网站打开速度慢等问题。 原理就是在客户端…

如何解除maven打包编译的警告日志:[WARNING] 未与 -source 21 一起设置系统模块的位置

在用jdk较高的版本进行maven项目的打包编译时&#xff0c;经常遇到类似“[WARNING] 未与 -source 21 一起设置系统模块的位置”这样的警告日志&#xff0c;如下&#xff1a; 网上大量搜索该问题的解决方案&#xff0c;却未果&#xff0c;无耐去看了官网的用法&#xff0c;才获得…

Java项目中整合多个pdf合并为一个pdf

一、Java项目中整合多个pdf合并为一个pdf gitee笔记路径&#xff1a;https://gitee.com/happy_sad/drools一、依赖导入 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.6</version> …