[大模型]Phi-3-mini-4k-Instruct Lora 微调

news2024/12/28 21:22:30

本节我们简要介绍如何基于 transformers、peft 等框架,对 Phi-3-mini-4k-Instruct 模型进行 Lora 微调。Lora 是一种高效微调方法,深入了解其原理可参见博客:知乎|深入浅出 Lora。

这个教程会在同目录下给大家提供一个 nodebook 文件,来让大家更好的学习。

环境准备

在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器,如下图所示镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1
接下来打开刚刚租用服务器的 JupyterLab,并且打开其中的终端开始环境配置、模型下载和运行演示。

在这里插入图片描述

环境配置

在完成基本环境配置和本地模型部署的情况下,你还需要安装一些第三方库,可以使用以下命令:

python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

pip install modelscope==1.9.5
pip install "transformers>=4.40.0"
pip install streamlit==1.24.0
pip install sentencepiece==0.1.99
pip install accelerate==0.29.3
pip install datasets==2.19.0
pip install peft==0.10.0

MAX_JOBS=8 pip install flash-attn --no-build-isolation

考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Phi-3 的环境镜像,该镜像适用于该仓库的所有部署环境。点击下方链接并直接创建 Autodl 示例即可。
https://www.codewithgpu.com/i/datawhalechina/self-llm/Phi-3-Lora

在本节教程里,我们将微调数据集放置在根目录 /dataset。

模型下载

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

在 /root/autodl-tmp 路径下新建 model_download.py 文件并在其中输入以下内容,粘贴代码后记得保存文件,如下图所示。并运行 python /root/autodl-tmp/model_download.py 执行下载

import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os

model_dir = snapshot_download('LLM-Research/Phi-3-mini-4k-instruct', cache_dir='/root/autodl-tmp', revision='master')

指令集构建

LLM 的微调一般指指令微调过程。所谓指令微调,是说我们使用的微调数据形如:

{
  "instruction": "回答以下用户问题,仅输出答案。",
  "input": "1+1等于几?",
  "output": "2"
}

其中,instruction 是用户指令,告知模型其需要完成的任务;input 是用户输入,是完成用户指令所必须的输入内容;output 是模型应该给出的输出。

即我们的核心训练目标是让模型具有理解并遵循用户指令的能力。因此,在指令集构建时,我们应针对我们的目标任务,针对性构建任务指令集。例如,在本节我们使用由笔者合作开源的 Chat-甄嬛 项目作为示例,我们的目标是构建一个能够模拟甄嬛对话风格的个性化 LLM,因此我们构造的指令形如:

{
  "instruction": "你是谁?",
  "input": "",
  "output": "家父是大理寺少卿甄远道。"
}

我们所构造的全部指令数据集在根目录下。

数据格式化

Lora 训练的数据是需要经过格式化、编码之后再输入给模型进行训练的,如果是熟悉 Pytorch 模型训练流程的同学会知道,我们一般需要将输入文本编码为 input_ids,将输出文本编码为 labels,编码之后的结果都是多维的向量。我们首先定义一个预处理函数,这个函数用于对每一个样本,编码其输入、输出文本并返回一个编码后的字典:

def process_func(example):
    MAX_LENGTH = 384    # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer(f"<|user|>\n{example['instruction'] + example['input']}<|end|>\n<|assistant|>\n", add_special_tokens=False)  # add_special_tokens 不在开头加 special_tokens
    response = tokenizer(f"{example['output']}<|end|>\n", add_special_tokens=False)
    input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
    attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]  # 因为eos token咱们也是要关注的所以 补充为1
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
    if len(input_ids) > MAX_LENGTH:  # 做一个截断
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }

Phi-3-mini-4k-Instruct 采用的Prompt Template格式如下:

<|system|>
You are a helpful assistant<|end|>
<|user|>
你是谁?<|end|>
<|assistant|>
我是一个有用的助手。<|end|>

加载 tokenizer 和半精度模型

模型以半精度形式加载,如果你的显卡比较新的话,可以用torch.bfolat形式加载。对于自定义的模型一定要指定trust_remote_code参数为True

tokenizer = AutoTokenizer.from_pretrained('/root/autodl-tmp/LLM-Research/Phi-3-mini-4k-instruct', use_fast=False, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_toke
model = AutoModelForCausalLM.from_pretrained('/root/autodl-tmp/LLM-Research/Phi-3-mini-4k-instruct', device_map="auto",torch_dtype=torch.bfloat16, trust_remote_code=True)

定义 LoraConfig

LoraConfig这个类中可以设置很多参数,但主要的参数没多少,简单讲一讲,感兴趣的同学可以直接看源码。

  • task_type:模型类型
  • target_modules:需要训练的模型层的名字,主要就是attention部分的层,不同的模型对应的层的名字不同,可以传入数组,也可以字符串,也可以正则表达式。
  • rlora的秩,具体可以看Lora原理
  • lora_alphaLora alaph,具体作用参见 Lora 原理

Lora的缩放是啥嘞?当然不是r(秩),这个缩放就是lora_alpha/r, 在这个LoraConfig中缩放就是 4 倍。

config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    inference_mode=False, # 训练模式
    r=8, # Lora 秩
    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
    lora_dropout=0.1# Dropout 比例
)

自定义 TrainingArguments 参数

TrainingArguments这个类的源码也介绍了每个参数的具体作用,当然大家可以来自行探索,这里就简单说几个常用的。

  • output_dir:模型的输出路径
  • per_device_train_batch_size:顾名思义 batch_size
  • gradient_accumulation_steps: 梯度累加,如果你的显存比较小,那可以把 batch_size 设置小一点,梯度累加增大一些。
  • logging_steps:多少步,输出一次log
  • num_train_epochs:顾名思义 epoch
  • gradient_checkpointing:梯度检查,这个一旦开启,模型就必须执行model.enable_input_require_grads(),这个原理大家可以自行探索,这里就不细说了。
args = TrainingArguments(
    output_dir="./output/Phi-3",
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    logging_steps=10,
    num_train_epochs=3,
    save_steps=100,
    learning_rate=1e-4,
    save_on_each_node=True,
    gradient_checkpointing=True
)

使用 Trainer 训练

trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_id,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)
trainer.train()

保存 lora 权重

lora_path='./Phi-3_lora'
trainer.model.save_pretrained(lora_path)
tokenizer.save_pretrained(lora_path)

加载 lora 权重推理

训练好了之后可以使用如下方式加载lora权重进行推理:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import PeftModel

model_path = '/root/autodl-tmp/LLM-Research/Phi-3-mini-4k-instruct'
lora_path = './Phi-3_lora' # lora权重路径

# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_path, padding_side='left')

# 加载模型
model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16)

# 加载lora权重
model = PeftModel.from_pretrained(model, model_id=lora_path, config=config)

prompt = "你是谁?"
messages = [
    {"role": "user", "content": prompt}
]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)

model_inputs = tokenizer([text], return_tensors="pt").to('cuda')

generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512,
    eos_token_id=tokenizer.encode('<|endoftext|>')[0]
)

outputs = generated_ids.tolist()[0][len(model_inputs[0]):]
response = tokenizer.decode(outputs).split('<|end|>')[0]

print(response)

完整微调代码下载地址:
https://github.com/datawhalechina/self-llm/blob/master/phi-3/Phi-3-mini-4k-Instruct-Lora.ipynb

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

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

相关文章

简单了解RS485与RS232(UART)

简单了解RS485与RS232&#xff08;UART&#xff09; 一、UART和RS232、RS485的关系1、UART2、RS232/RS4853、RS232 与 RS485 的区别与联系 二、Modbus协议说明1、什么是协议2、Modbus协议说明3、Modebus通信过程4、Modbus存储区5、Modbus协议类型6、Modbus功能码 三、stm32HC-S…

【StableDiffusion】采样方法对比优缺点及评估,采样器 调度器(目前已有的 采样器介绍与评估)

采样器 Sampler 采样方法 决定了 如何从 噪声 生成 图像 的过程&#xff0c;也就是去噪过程如何进行 包含 DPM 的采样方法&#xff08;逆转扩散采样&#xff09; DPM → Diffusion Probabilistic Models&#xff08;扩散概率模型&#xff09; DPM、DPM2 包含 DPM 的采样方…

FastAPI 作为H5中流式输出的后端

FastAPI 作为H5中流式输出的后端 最近大家都在玩LLM&#xff0c;我也凑了热闹&#xff0c;简单实现了一个本地LLM应用&#xff0c;分享给大家&#xff0c;百分百可以用哦&#xff5e;^ - ^ 先介绍下我使用的三种工具&#xff1a; Ollama&#xff1a;一个免费的开源框架&…

Redisson原理解析

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

智能对话画画音乐创作歌曲三合一系统源码 前后端分离 附带完整的源代码包+搭建部署教程

系统概述 创想无界是一个高度集成的创意生态系统&#xff0c;它巧妙地融合了人工智能的三大核心领域&#xff1a;自然语言处理&#xff08;NLP&#xff09;用于智能对话&#xff0c;计算机视觉&#xff08;CV&#xff09;实现自动画画&#xff0c;以及音乐生成算法来创作个性化…

Redis中的Lua脚本

EVAL 命令 命令格式 EVAL script numkeys key [key ...] arg [arg ...]命令说明 1、script 参数&#xff1a; 一段Lua脚本程序&#xff0c;会在Redis服务器上下文中运行&#xff0c;不需要&#xff08;也不应该&#xff09;定义为一个Lua函数。 2、numkeys 参数&#xff1…

IT人的拖延——别让“需求沟通”耽误了你的正事

IT人的工作&#xff0c;很多“需求沟通”的场景&#xff0c;而在沟通需求时&#xff0c;又会因为沟通的不顺畅&#xff0c;没有结果而产生烦躁的情绪或者是悬而未决的不能开始行动&#xff0c;进而间接地造成了拖延。这种拖延的原因&#xff0c;需要从需求沟通的根源来找方案&a…

人工智能将成为数学家的“副驾驶”

人工智能将成为数学家的“副驾驶” 数学传统上是一门独立的科学。1986年&#xff0c;安德鲁怀尔斯为了证明费马定理&#xff0c;退到书房里呆了7年。由此产生的证明往往很难让同事们理解&#xff0c;有些至今仍有争议。但近年来&#xff0c;越来越多的数学领域被严格地分解为各…

汇编:EFLAGS寄存器

EFLAGS寄存器是x86架构处理器中的一个状态寄存器&#xff0c;用于存储当前处理器状态和控制特定操作&#xff1b;寄存器中的各个标志位可以影响指令执行&#xff0c;并且指令执行过程中也可以修改这些标志位&#xff0c;每个位都有特定的含义。 EFLAGS寄存器图示&#xff1a; …

振弦采集仪在隧道工程中的安全监测与控制研究

振弦采集仪在隧道工程中的安全监测与控制研究 隧道工程的安全监测与控制是保障隧道施工和运营安全的重要工作。隧道工程常面临的问题包括地层变形、地下水位变化、地震影响等&#xff0c;这些问题对隧道结构的安全性和使用寿命有着重要影响。因此&#xff0c;隧道工程中的安全…

【CS.AI】AI引领编程新时代:深度探索GitHub Copilot

文章目录 引言0. TOP TAKEAWAYS 重要要点1. Copilot的基本功能2. 技术原理3. 优势与局限优势局限 4. 使用体验4.1 初次使用4.2 在 JetBrains 全家桶中使用 GitHub Copilot1. 安装插件2. 配置插件3. 使用 GitHub Copilot 4.3 日常开发4.4 体验与反馈 5. 对开发者生态系统的影响5…

零碳产业园区建设指南案例

零碳产业园区的建设一直备受广泛关注&#xff0c;特别是在我国碳达峰碳中和的背景下。据不完全统计&#xff0c;目前&#xff0c;全国共有国家级和省级园区2500余家&#xff0c;这些园区在贡献了全国50%工业产出的同时&#xff0c;其CO2排放量也占到了全国排放总量的30%以上。作…

VMware安装ubuntu22.4虚拟机超详细图文教程

一 、下载镜像 下载地址&#xff1a;Index of /ubuntu-releases/22.04.4/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 二、创建虚拟机 打开VMware点击左上角文件&#xff0c;创建新的虚拟机&#xff0c;打开后如下图&#xff1a; 下一步&#xff0c;镜像文件就是…

光纤跳线(又称光纤连接器)的种类

光纤跳线&#xff08;又称光纤连接器&#xff09;&#xff0c;也就是接入光模块的光纤接头&#xff0c;也有好多种&#xff0c;且相互之间不可以互用。SFP模块接LC光纤连接器&#xff0c;而GBIC接的是SC光纤连接器。下面对网络工程中几种常用的光纤连接器进行详细的说明&#x…

3d交互式场景在线编辑平台的好处

在数字化教学的新时代&#xff0c;我们为您带来了革命性的产品——VR全景展示搭建编辑器。它将传统的教学方式升级为三维模式&#xff0c;让课程训练更加真实生动&#xff0c;为您带来前所未有的学习体验。 VR全景展示搭建编辑器不仅支持视频录播、PDF、图文等多种内容承载方式…

非阻塞IO简介和代码实例

接上篇 阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介-CSDN博客文章浏览阅读90次。阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介https://blog.csdn.net/CSDN_DU666666/article/details/139598410?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%2…

Matlab|基于主从博弈的智能小区代理商定价策略及电动汽车充电管理

目录 一、主要内容 二、部分代码 三、程序结果 四、下载链接 一、主要内容 主要做的是一个电动汽车充电管理和智能小区代理商动态定价的问题&#xff0c;将代理商和车主各自追求利益最大化建模为主从博弈&#xff0c;上层以代理商的充电电价作为优化变量&#xff0c;下层以…

用PlayCanvas打造一个3D模型

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 PlayCanvas 的 3D 物理场景开发 应用场景介绍 PlayCanvas 是一款功能强大的 3D 引擎&#xff0c;可用于创建各种类型的 3D 体验&#xff0c;包括游戏、模拟和交互式可视化。本技术博客将介绍如何使用 Pl…

低成本和颜值兼顾的 HomeLab 设备:HPE MicroServer Gen10(二)

本篇文章&#xff0c;继续分享另外一台端午假期折腾的设备&#xff0c;HP MicroServer Gen10 一代。同样分享下我的折腾思路&#xff0c;希望能够帮助到有类似需求的你。 写在前面 Gen10 “标准版”&#xff08;第一代&#xff09;和 Plus 版本设计风格一致&#xff0c;同样颜…

20240607在ubuntu下解压缩7z的压缩包文件

20240607在ubuntu下解压缩7z的压缩包文件 2024/6/7 10:26 百度&#xff1a;ubuntu 7z解压缩 在Ubuntu中&#xff0c;可以使用7z命令来解压.7z文件。首先&#xff0c;确保你已经安装了p7zip-full包&#xff0c;如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo …