当前位置: 首页 > news >正文

llamafactory使用8张昇腾910b算力卡lora微调训练qwen2-72b大模型

说明

我需要在昇腾服务器上对Qwen2-72B大模型进行lora微调,改变其自我认知。
我的环境下是8张910B1卡。显存约512GB。

准备:安装llamafactory

请参考官方方法安装llamafactory:https://github.com/hiyouga/LLaMA-Factory

特别强调下,deepspeed一定要按照文档中要求的版本安装,太新或者太旧,多卡训练都有问题。

准备数据集和训练配置

我准备的工作目录如下:

./
├── data
│   ├── dataset_info.json
│   └── self_cognition.json
├── deepspeed
│   └── ds_z3_config.json
├── models
├── start_train.sh
└── train_config.yaml

其中data目录下self_cognition.json是我准备的数据集,他是alpaca格式的,dataset_info.json是数据集的入口配置文件,一会训练要指定它。

dataset_info.json内容如下:

{
"train_data_name": {"file_name": "self_cognition.json"}}

我在这里只写了一个数据集,其实可以配置很多的。

deepspeed目录下的ds_z3_config.json是deepspeed的配置文件,使用多卡训练必须要有这个文件。
这个文件在LLaMA-Factory代码工程下examples/deepspeed下有参考文件,我直接复制了一个过来。
其内容如下:

{"train_batch_size": "auto","train_micro_batch_size_per_gpu": "auto","gradient_accumulation_steps": "auto","gradient_clipping": "auto","zero_allow_untested_optimizer": true,"fp16": {"enabled": "auto","loss_scale": 0,"loss_scale_window": 1000,"initial_scale_power": 16,"hysteresis": 2,"min_loss_scale": 1},"bf16": {"enabled": "auto"},"zero_optimization": {"stage": 3,"overlap_comm": true,"contiguous_gradients": true,"sub_group_size": 1e9,"reduce_bucket_size": "auto","stage3_prefetch_bucket_size": "auto","stage3_param_persistence_threshold": "auto","stage3_max_live_parameters": 1e9,"stage3_max_reuse_distance": 1e9,"stage3_gather_16bit_weights_on_model_save": true}
}

models目录是空的,用来存放训练生成的模型。

train_config.yaml是训练配置文件,起内容如下:

### model
model_name_or_path: /data/xxx/mindformer_share/Qwen2-72B-Instruct/### method
stage: sft
do_train: true
finetuning_type: lora
lora_target: all### ddp
ddp_timeout: 180000000
deepspeed: ./deepspeed/ds_z3_config.json### dataset
dataset: train_data_name
template: qwen
cutoff_len: 1024
max_samples: 200
overwrite_cache: true
preprocessing_num_workers: 16### output
output_dir: ./models/
logging_steps: 10
save_steps: 50
plot_loss: true
overwrite_output_dir: true#report_to: tensorboard#logging_dir: /data/xxx/mindformer_share/llamaFactory/tensorboard/### train
per_device_train_batch_size: 1
gradient_accumulation_steps: 2
learning_rate: 1.0e-4
num_train_epochs: 40.0
lr_scheduler_type: cosine
warmup_ratio: 0.1
fp16: true### eval
val_size: 0.1
per_device_eval_batch_size: 1
eval_strategy: steps
eval_steps: 500

其中model_name_or_path用爱指定基础模型的路径,output_dir用来指定训练生成模型的输出路径。num_train_epochs是训练的轮数,max_samples是最大样本的数量,可根据实际情况修改这个值。save_steps是多少步保存一次中间checkpoint。

重点要说下deepspeed配置,如果不指定deepspeed配置文件,则默认使用数据并行,一旦模型无法在单张卡上加载就会出错。而配置了deepspeed之后,则模型会被切分到各张卡上,大模型可以平均分布在多张卡上。

我的训练启动脚本是start_train.sh,其内容如下:

#!/bin/shsource /usr/local/Ascend/ascend-toolkit/set_env.shset -x
#export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7llamafactory-cli train ./train_config.yaml

执行训练

在命令行执行start_train.sh脚本

sh start_train.sh

训练完成后./models目录下文件如下:

./models/
├── adapter_config.json
├── adapter_model.safetensors
├── added_tokens.json
├── all_results.json
├── checkpoint-100
├── checkpoint-150
├── checkpoint-200
├── checkpoint-50
├── eval_results.json
├── merges.txt
├── README.md
├── runs
├── special_tokens_map.json
├── tokenizer_config.json
├── tokenizer.json
├── trainer_log.jsonl
├── trainer_state.json
├── training_args.bin
├── training_loss.png
├── train_results.json
└── vocab.json

我的模型训练了40轮,每50步保存一次模型。通过查看trainer_log.jsonl,发现checkpoint-150之后loss就已经很稳定了,我决定就使用checkpoint-150这个中间结果做后面的操作。

{"current_steps": 10, "total_steps": 200, "loss": 4.1278, "lr": 4e-05, "epoch": 2.0, "percentage": 5.0, "elapsed_time": "0:03:03", "remaining_time": "0:58:11"}
{"current_steps": 20, "total_steps": 200, "loss": 2.4438, "lr": 9e-05, "epoch": 4.0, "percentage": 10.0, "elapsed_time": "0:05:48", "remaining_time": "0:52:20"}
{"current_steps": 30, "total_steps": 200, "loss": 1.0016, "lr": 9.951340343707852e-05, "epoch": 6.0, "percentage": 15.0, "elapsed_time": "0:08:35", "remaining_time": "0:48:39"}
{"current_steps": 40, "total_steps": 200, "loss": 0.4434, "lr": 9.755282581475769e-05, "epoch": 8.0, "percentage": 20.0, "elapsed_time": "0:11:18", "remaining_time": "0:45:13"}
{"current_steps": 50, "total_steps": 200, "loss": 0.0837, "lr": 9.414737964294636e-05, "epoch": 10.0, "percentage": 25.0, "elapsed_time": "0:13:59", "remaining_time": "0:41:58"}
{"current_steps": 60, "total_steps": 200, "loss": 0.0096, "lr": 8.940053768033609e-05, "epoch": 12.0, "percentage": 30.0, "elapsed_time": "0:17:36", "remaining_time": "0:41:06"}
{"current_steps": 70, "total_steps": 200, "loss": 0.0059, "lr": 8.345653031794292e-05, "epoch": 14.0, "percentage": 35.0, "elapsed_time": "0:20:22", "remaining_time": "0:37:50"}
{"current_steps": 80, "total_steps": 200, "loss": 0.0019, "lr": 7.649596321166024e-05, "epoch": 16.0, "percentage": 40.0, "elapsed_time": "0:23:07", "remaining_time": "0:34:41"}
{"current_steps": 90, "total_steps": 200, "loss": 0.0026, "lr": 6.873032967079561e-05, "epoch": 18.0, "percentage": 45.0, "elapsed_time": "0:25:51", "remaining_time": "0:31:36"}
{"current_steps": 100, "total_steps": 200, "loss": 0.0011, "lr": 6.0395584540887963e-05, "epoch": 20.0, "percentage": 50.0, "elapsed_time": "0:28:36", "remaining_time": "0:28:36"}
{"current_steps": 110, "total_steps": 200, "loss": 0.0007, "lr": 5.174497483512506e-05, "epoch": 22.0, "percentage": 55.0, "elapsed_time": "0:32:03", "remaining_time": "0:26:13"}
{"current_steps": 120, "total_steps": 200, "loss": 0.001, "lr": 4.3041344951996746e-05, "epoch": 24.0, "percentage": 60.0, "elapsed_time": "0:34:44", "remaining_time": "0:23:09"}
{"current_steps": 130, "total_steps": 200, "loss": 0.0009, "lr": 3.4549150281252636e-05, "epoch": 26.0, "percentage": 65.0, "elapsed_time": "0:37:25", "remaining_time": "0:20:08"}
{"current_steps": 140, "total_steps": 200, "loss": 0.0008, "lr": 2.6526421860705473e-05, "epoch": 28.0, "percentage": 70.0, "elapsed_time": "0:40:08", "remaining_time": "0:17:12"}
{"current_steps": 150, "total_steps": 200, "loss": 0.0009, "lr": 1.9216926233717085e-05, "epoch": 30.0, "percentage": 75.0, "elapsed_time": "0:42:48", "remaining_time": "0:14:16"}
{"current_steps": 160, "total_steps": 200, "loss": 0.0009, "lr": 1.2842758726130283e-05, "epoch": 32.0, "percentage": 80.0, "elapsed_time": "0:46:37", "remaining_time": "0:11:39"}
{"current_steps": 170, "total_steps": 200, "loss": 0.0007, "lr": 7.597595192178702e-06, "epoch": 34.0, "percentage": 85.0, "elapsed_time": "0:49:21", "remaining_time": "0:08:42"}
{"current_steps": 180, "total_steps": 200, "loss": 0.0007, "lr": 3.6408072716606346e-06, "epoch": 36.0, "percentage": 90.0, "elapsed_time": "0:52:05", "remaining_time": "0:05:47"}
{"current_steps": 190, "total_steps": 200, "loss": 0.0007, "lr": 1.0926199633097157e-06, "epoch": 38.0, "percentage": 95.0, "elapsed_time": "0:54:53", "remaining_time": "0:02:53"}
{"current_steps": 200, "total_steps": 200, "loss": 0.0007, "lr": 3.04586490452119e-08, "epoch": 40.0, "percentage": 100.0, "elapsed_time": "0:57:36", "remaining_time": "0:00:00"}
{"current_steps": 200, "total_steps": 200, "epoch": 40.0, "percentage": 100.0, "elapsed_time": "0:58:26", "remaining_time": "0:00:00"}

合并lora模型到基础模型

merge方法1:llamafactory-cli export

llamafactory的命令行工具自带了lora合并功能,参考源码工程目录examples/merge_lora/下的配置文件编写一个合并的配置文件即可。

首先编写一个合并用的配置文件qwen_merge_lora_config.yaml:

### Note: DO NOT use quantized model or quantization_bit when merging lora adapters### model
model_name_or_path: /data/xxx/mindformer_share/Qwen2-72B-Instruct/
adapter_name_or_path: /data/xxx/mindformer_share/llamaFactory/models/checkpoint-150/
template: qwen
finetuning_type: lora### export
export_dir: /data/xxx/mindformer_share/llamaFactory/export_merge_lora/
export_size: 2
export_device: cpu  # 也可以写npu
export_legacy_format: false

上面文件中,model_name_or_path是基础模型路径,adapter_name_or_path是lora训练输出路径,export_dir是合并后输出的模型路径。template时模型的架构,跟lora训练配置里一致即可。

然后在命令行窗口执行:

llamafactory-cli export qwen_merge_lora_config.yaml

执行完毕,在export_dir定义路径下就是合并后的完整模型。

merge方法2:

也可以使用python,通过调用peft来合并lora模型。

import torch
import torch_npu
from torch_npu.npu import amp
from torch_npu.contrib import transfer_to_npu
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation.utils import GenerationConfig
from peft import PeftModelmodel_path="/data/xxx/mindformer_share/Qwen2-72B-Instruct/"
lora_path="/data/xxx/mindformer_share/llamaFactory/models/checkpoint-150/"
merge_path="./export_python_merge"print(f"Loading the Base model from {model_path}")
tokenizer = AutoTokenizer.from_pretrained(model_path,revision="v2.0",use_fast=False,trust_remote_code=True)
base_model = AutoModelForCausalLM.from_pretrained(model_path,revision="v2.0",device_map="auto",torch_dtype=torch.float16,trust_remote_code=True)#trust_remote_code=True).eval().half().npu()print(f"Loading the LoRA from {lora_path}")
lora_model = PeftModel.from_pretrained(base_model,lora_path,torch_dtype=torch.float16,)print("Applying the LoRA")
model = lora_model.merge_and_unload()print(f"Saving the target model to {merge_path}")
model.save_pretrained(merge_path)
print(f"Saving the tokenizer to {merge_path}")
tokenizer.save_pretrained(merge_path)

上述代码中model_path是基础模型路径,lora_path是lora模型目录,merge_path是合并模型输出路径。

2种合并方法的比较

其中方法1中,export_device设置为cpu时,内存至少占140G(大约时模型尺寸大小),cpu会占用到100个核,NPU资源几乎不占。

方法1中export_device设置为npu时整体效果和方法2差不多。

2种方法合并模型的时间都约15分钟。

测试合并后的模型

合并后的模型就和huggingface上下载的模型使用同样的方法测试。这是我测试qwen2-72b合并后的模型的代码。

from transformers import AutoModelForCausalLM, AutoTokenizer
device = "npu" # the device to load the model onto#model_path="/data/yuanll/mindformer_share/Qwen2-72B-Instruct/"
#model_path="./export_merge_lora"
model_path="./export_python_merge"model = AutoModelForCausalLM.from_pretrained(model_path,torch_dtype="auto",device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_path)#{"role": "system", "content": "You are a helpful assistant."},
prompt = "告诉我你的身份和创造者"
messages = [{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(device)generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=512
)
generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(f"response:{response}")

参考资料

在昇腾开发环境合并baichuan2-13B模型的lora文件

Qwen/Qwen2-72B-Instruct

LLaMA-Factory 实战(一):采用 LoRA 方式对QWen2 做指令微调

LLaMA-Factory 8卡4090 deepspeed zero3 微调Qwen14B-chat

相关文章:

llamafactory使用8张昇腾910b算力卡lora微调训练qwen2-72b大模型

说明 我需要在昇腾服务器上对Qwen2-72B大模型进行lora微调,改变其自我认知。 我的环境下是8张910B1卡。显存约512GB。 准备:安装llamafactory 请参考官方方法安装llamafactory:https://github.com/hiyouga/LLaMA-Factory 特别强调下&…...

C++,设计模式,【目录篇】

文章目录 1. 简介2. 设计模式的分类2.1 创建型模式(Creational Patterns):2.2 结构型模式(Structural Patterns):2.3 行为型模式(Behavioral Patterns): 3. 使用设计模式…...

《目标检测数据集下载地址》

一、引言 在计算机视觉的广袤领域中,目标检测宛如一颗璀璨的明星,占据着举足轻重的地位。它宛如赋予计算机一双锐利的 “眼睛”,使其能够精准识别图像或视频中的各类目标,并确定其位置,以边界框的形式清晰呈现。这项技…...

C 语言的void*到底是什么?

一、void* 的类型任意性 void* 是一种通用指针类型。它可以指向任意类型的数据。例如,它可以指向一个整数(int)、一个浮点数(float)、一个字符(char)或者一个结构体等。在C语言中,当…...

Linux中的文件上传和下载

Linux中的文件上传和下载 一、连接 SFTP 在 SecureCRT 中,将鼠标移动到连接窗口的标题上,按鼠标右键,选择“连接 SFTP”标签,即可进入 SFTP 模式。 二、基本指令及用途 1. 显示当前目录 显示本地当前目录:lpwd 示例…...

DDD - 微服务落地的技术实践

文章目录 Pre概述如何发挥微服务的优势怎样提供微服务接口原则微服务的拆分与防腐层的设计 去中心化的数据管理数据关联查询的难题Case 1Case 2Case 3 总结 Pre DDD - 软件退化原因及案例分析 DDD - 如何运用 DDD 进行软件设计 DDD - 如何运用 DDD 进行数据库设计 DDD - 服…...

fgets、scanf存字符串应用

题目1 夺旗(英语:Capture the flag,简称 CTF)在计算机安全中是一种活动,当中会将“旗子”秘密地埋藏于有目的的易受攻击的程序或网站。参赛者从其他参赛者或主办方偷去旗子。 非常崇拜探姬的小学妹最近迷上了 CTF&am…...

鸿蒙动态路由实现方案

背景 随着CSDN 鸿蒙APP 业务功能的增加,以及为了与iOS、Android 端统一页面跳转路由,以及动态下发路由链接,路由重定向等功能。鸿蒙动态路由方案的实现迫在眉睫。 实现方案 鸿蒙版本动态路由的实现原理,类似于 iOS与Android的实…...

Spring-boot3.4最新版整合swagger和Mybatis-plus

好家伙,今天终于开始用spring-boot3开始写项目了,以后要彻底告别1.x和2.x了,同样的jdk也来到了最低17的要求了,废话不多说直接开始 这是官方文档的要求jdk最低是17 maven最低是3.6 一. 构建工程,这一步就不需要给大家解释了吧 二. 整合Knife4j 1.大于…...

基于Java的高校实习管理平台

基于Java的高校实习管理平台是一个专为高校设计的信息化管理工具,旨在通过信息化手段简化实习管理流程,提高管理效率,增强学校、企业与学生之间的沟通与协作。: 一、系统背景与意义 随着教育体系的不断完善和就业市场的日益竞争…...

全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之一维数组(应用技巧)

二、一维数组应用技巧2:打标记 实战训练1—开关灯 问题描述: 有 M个从1到M依次编号的人参加一项游戏。将K 盏从1到K依次编号的灯(K和M均为正整数,M≤K≤5000)进行一系列的熄灭与打开的操作,游戏开始时均处于亮灯的状态&#xf…...

【2024年华为OD机试】 (B卷,100分)- 路灯照明问题(Java JS PythonC/C++)

一、问题描述 路灯照明问题 题目描述 在一条笔直的公路上安装了 ( N ) 个路灯,从位置 0 开始安装,路灯之间间距固定为 100 米。每个路灯都有自己的照明半径。请计算第一个路灯和最后一个路灯之间,无法照明的区间的长度和。 输入描述 第一…...

SVGAPlayer error 处理

提示错误 Call to undeclared function OSAtomicCompareAndSwapPtrBarrier; ISO C99 and later do not support implicit function declarations Conflicting types for OSAtomicCompareAndSwapPtrBarrier Declaration of OSAtomicCompareAndSwapPtrBarrier must be imported …...

2024年12月电子学会青少年机器人技术等级考试(二级)实际操作试卷

2024.12 青少年机器人技术等级考试(二级)实际操作试卷 一、多选题 第 1 题 关于后轮驱动车说法正确的有哪些?( ) A.起步加速表现比前轮驱动好 B.容易转向过度 C.车身重量比前轮驱动更均衡 D.造价比前轮驱动车更高…...

Swift 专题二 语法速查

一 、变量 let, var 变量是可变的,使用 var 修饰,常量是不可变的,使用 let 修饰。类、结构体和枚举里的变量是属性。 var v1:String "hi" // 标注类型 var v2 "类型推导" let l1 "标题" // 常量class a {…...

Api网关Zuul

网关分类与开放API 开放API (OpenAPI) 企业需要将自身数据、能力等作为开发平台向外开放,通常会以REST的方式向外提供,最好的例子就是淘宝开放平台、腾讯公司的QQ开发平台、微信开放平台。开放API平台必然涉及到客户应用的接入、API权限的管理、调用次数…...

01设计模式(D3_设计模式类型 - D3_行为型模式)

目录 一、模版方法模式 1. 基本介绍 2. 应用案例一:豆浆制作问题 需求 代码实现 模板方法模式的钩子方法 3. View的draw(Android) Android中View的draw方法就是使用了模板方法模式 模板方法模式在 Spring 框架应用的源码分析 知识小…...

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测

角点检测(Corner Detection)是计算机视觉和图像处理中重要的步骤,主要用于提取图像中的关键特征,以便进行后续的任务,比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…...

费解的开关

费解的开关 你玩过“拉灯”游戏吗? 25 盏灯排成一个 55 的方形。 每一个灯都有一个开关,游戏者可以改变它的状态。 每一步,游戏者可以改变某一个灯的状态。 游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也…...

【机器学习】机器学习引领数学难题攻克:迈向未知数学领域的新突破

我的个人主页 我的领域:人工智能篇,希望能帮助到大家!!!👍点赞 收藏❤ 一、引言 在数学的浩瀚领域中,存在着诸多长期未解的难题,这些难题犹如高耸的山峰,吸引着无数数…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

爬虫基础学习day2

# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性&#xf…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...