B站同步视频 -> 点击进入> 点击进入> B站同步视频> 点击进入> 点击进入> B站同步视频> 点击进入>            

1. LLaMA-Factory项目介绍

  LLaMA Factory是一个在GitHub上开源的项目,该项目给自身的定位是:提供一个易于使用的大语言模型(LLM)微调框架,支持LLaMA、Baichuan、Qwen、ChatGLM等架构的大模型。更细致的看,该项目提供了从预训练、指令微调到RLHF阶段的开源微调解决方案。截止目前(2024年3月1日)支持约120+种不同的模型和内置了60+的数据集,同时封装出了非常高效和易用的开发者使用方法。而其中最让人喜欢的是其开发的LLaMA Board,这是一个零代码、可视化的一站式网页微调界面,它允许我们通过Web UI轻松设置各种微调过程中的超参数,且整个训练过程的实时进度都会在Web UI中进行同步更新。

  简单理解,通过该项目我们只需下载相应的模型,并根据项目要求准备符合标准的微调数据集,即可快速开始微调过程,而这样的操作可以有效地将特定领域的知识注入到通用模型中,增强模型对特定知识领域的理解和认知能力,以达到“通用模型到垂直模型的快速转变”。

  LLaMA-Factory目前支持微调的模型及对应的参数量:

Model

Sizes

Baichuan2

7B/13B

BLOOM

560M/1.1B/1.7B/3B/7.1B/176B

BLOOMZ

560M/1.1B/1.7B/3B/7.1B/176B

ChatGLM3

6B

DeepSeek (MoE)

7B/16B/67B

Falcon

7B/40B/180B

Gemma

2B/7B

InternLM2

7B/20B

LLaMA

7B/13B/33B/65B

LLaMA-2

7B/13B/70B

Mistral

7B

Mixtral

8x7B

Phi-1.5/2

1.3B/2.7B

Qwen

1.8B/7B/14B/72B

Qwen1.5

0.5B/1.8B/4B/7B/14B/72B

XVERSE

7B/13B/65B

Yi

6B/34B

Yuan

2B/51B/102B

  可以看到,当前主流的开源大模型,包括ChatGLM3、Qwen的第一代以及最新的1.5测试版本,还有Biachuan2等,已经完全支持不同规模的参数量。针对LLaMA架构的系列模型,该项目已经基本实现了全面的适配。而其支持的训练方法,也主要围绕(增量)预训练、指令监督微调、奖励模型训练、PPO 训练和 DPO 训练展开,具体情况如下:

方法

全参数训练

部分参数训练

LoRA

QLoRA

预训练(Pre-Training)

指令监督微调(Supervised Fine-Tuning)

奖励模型训练(Reward Modeling)

PPO 训练(PPO Training)

DPO 训练(DPO Training)

  • 预训练

  在大模型的早期阶段,也就是诞生的过程中,往往不会经过Supervised finetuning(监督式微调) 的过程,它在训练时仅仅是去学习大量的语言基本规律和知识理解,其训练数据是类似这种形式:

JSON
山西警方扫黑除恶行动集中收网打掉涉黑涉恶犯罪组织和团伙54个【消息】 本报太原2月14日讯(记者 雷清明)2月13日,山西省公安厅对外发布消息称,扫黑除恶专项行动启动以来,全省各级公安机关迅速对一大批在侦在办的涉黑涉恶案件实施了集中收网。截至目前,全省公安机关共打掉涉黑涉恶犯罪组织和团伙54个,其中,打掉涉嫌黑社会性质组织4个,打掉恶势力犯罪组织50个。在54个涉黑涉恶犯罪组织态势,不断形成对黑恶势力违法犯罪的凌厉攻势;将进一步摸排深挖线索,进一步增强主动发现犯罪的能力和水平;将进一步扩大扫黑除恶的社会宣传覆盖面,营造对黑恶势力同仇敌忾、人人喊打的浓厚氛围。

近年来,单片机以其体积小、价格廉、面向控制等独特优点,在各种工业控制、仪器仪表、设备、产品的自动化、智能化方面获得了广泛的应用。与此同时,单片机应用系统的可靠性成为人们越来越关注的重要课题。影响可靠性的因素是多方面的,如构成系统的元器件本身的可靠性、系统本身各部分之间的相互耦合因素等。其中系统的抗干扰性能是系统可靠性的重要指标。 ·加电、掉电以及供电电压下降情况下的复位输出,复位脉冲宽度典型值为200 ms。 ·独立的看门狗输出,如果看门狗输入在1.6 s内未被触发,其输出将变为高

...
...
...

上述数据截取自:Skyworkhttps://huggingface.co/datasets/Skywork/SkyPile-150B (注:需要开启科学上网才可以访问)

  预训练数据通常来自于多样化的文本来源,以覆盖尽可能广泛的主题、语境和语言风格。这些数据可以是结构化的文本,也可以是非结构化的,比如新闻文章、科学文献等等,对于基于这样训练数据训练得到的模型,很难听懂人类下达的具体指令从而去完成复杂的任务,更多的是使用其文本的生成能力。

  我们所一直提及的微调,从参数规模来看,大体上可以分为全参数微调和高效参数微调。全参数微调通常以预训练模型的初始权重为基础,在特定数据集上继续训练,更新模型的所有参数。相比之下,高效参数微调旨在使用更少的资源来更新模型参数,这包括仅更新部分参数或通过对参数施加某些结构化约束来实现。后者就涵盖了我们在之前课程中提到的高效微调技术,如PEFT、LoRA和QLoRA等方法。

  另一方面,如果按照在大模型哪个阶段使用微调,或者根据模型微调的目标来区分,也可以从提示微调、指令微调、有监督微调的方式来具体分类。

  • 指令微调

  指令微调,是一种通过在由(指令,输出)对组成的数据集上进一步训练LLMs的过程。其中,指令代表模型的人类指令,输出代表遵循指令的期望输出。这个过程有助于弥合LLMs的下一个词预测目标与用户让LLMs遵循人类指令的目标之间的差距。它可以被视为有监督微调(Supervised Fine-Tuning,SFT)的一种特殊形式。但是,它们的目标依然有差别。SFT是一种使用标记数据对预训练模型进行微调的过程,以便模型能够更好地执行特定任务。而指令微调是一种通过在包括(指令,输出)对的数据集上进一步训练大语言模型(LLMs)的过程,以增强LLMs的能力和可控性。指令微调的特殊之处在于其数据集的结构,即由人类指令和期望的输出组成的配对。这种结构使得指令微调专注于让模型理解和遵循人类指令。

  总的来说,指令微调是有监督微调的一种特殊形式,专注于通过理解和遵循人类指令来增强大语言模型的能力和可控性。其形式往往是这样的:

JSON
  {
    "instruction": "
保持健康的三个提示。",
    "input": "",
    "output": "以下是保持健康的三个提示:\n\n1. 保持身体活动。每天做适当的身体运动,如散步、跑步或游泳,能促进心血管健康,增强肌肉力量,并有助于减少体重。\n\n2. 均衡饮食。每天食用新鲜的蔬菜、水果、全谷物和脂肪含量低的蛋白质食物,避免高糖、高脂肪和加工食品,以保持健康的饮食习惯。\n\n3. 睡眠充足。睡眠对人体健康至关重要,成年人每天应保证 7-8 小时的睡眠。良好的睡眠有助于减轻压力,促进身体恢复,并提高注意力和记忆力。"
  },
  {
    "instruction": "三原色是什么?",
    "input": "",
    "output": "三原色通常指的是红色、绿色和蓝色(RGB)。它们是通过加色混合原理创建色彩的三种基础颜色。在以发光为基础的显示设备中(如电视、计算机显示器、智能手机和平板电脑显示屏), 三原色可混合产生大量色彩。其中红色和绿色可以混合生成黄色,红色和蓝色可以混合生成品红色,蓝色和绿色可以混合生成青色。当红色、绿色和蓝色按相等比例混合时,可以产生白色或灰色。\n\n此外,在印刷和绘画中,三原色指的是以颜料为基础的红、黄和蓝颜色(RYB)。这三种颜色用以通过减色混合原理来创建色彩。不过,三原色的具体定义并不唯一,不同的颜色系统可能会采用不同的三原色。"
  },

  在上述数据中,其各字段意义如下:

  • instruction:任务指令,不能为空。
  • input:任务输入,可为空。如果不为空,项目内部处理训练数据时,会将 instruction、input 拼接在一起作为任务的输入。
  • output:任务输出,不能为空。

该数据截取自alpaca_gpt4_data_zh.json数据,来源于GPT-4 使用 ChatGPT Alpaca 翻译而来的中文提示生成中文指令跟踪数据,获取地址如下: https://github.com/Instruction-Tuning-with-GPT-4/GPT-4-LLM

  在该项目中,也内置了非常多的标准数据集,整体分为预训练的数据集、指令微调数据集和偏好数据集。具体各个数据集的详细情况,大家可以在其GitHub官网查看:https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md

  我们现在所使用的ChatGPT,其训练过程主要会经历三个阶段:首先微调GPT 3模型,然后通过人工对微调后模型的生成结果打分以训练得到一个奖励模型,最后基于微调后的GPT 3结合奖励模型采用强化学习的方法更新策略。而第三步中强化学习的方法就是OpenAI于2017年提出的Proximal Policy Optimization(PPO)算法,它作为一种强化学习算法,用于优化智能体的策略,会试图在策略更新过程中保持稳定性,防止策略更新过大导致学习过程不稳定。PPO 主要应用于连续控制任务和离散决策任务,并在许多领域取得了成功。

  关于奖励模型、PPO以及DPO,涉及大量的数学原理和技术概念,我们将在后面的课程安排中深入讲解与RLHF(Reinforcement Learning with Human Feedback)相关的理论知识。即使用强化学习的方法,利用人类反馈信号直接优化语言模型。此处暂时不展开详细讨论。

  最后且最关键的一点需特别指出:虽然LLaMA-Factory项目允许我们在120余种大模型中灵活选择并快速开启微调工作,但运行特定参数量的模型是否可行,仍然取决于本地硬件资源是否充足。因此,在选择模型进行实践前,大家必须仔细参照下表,结合自己的服务器配置来决定,以避免因硬件资源不足导致的内存溢出等问题。不同模型参数在不同训练方法下的显存占用情况如下:

训练方法

精度

7B

13B

30B

65B

全参数

16

160GB

320GB

600GB

1200GB

部分参数

16

20GB

40GB

120GB

240GB

LoRA

16

16GB

32GB

80GB

160GB

QLoRA

8

10GB

16GB

40GB

80GB

QLoRA

4

6GB

12GB

24GB

48GB

  对于我们课程中重点介绍的ChatGLM3、Qwen和Baichuan2模型,在LLaMA-Factory项目中均实现了高度集成。因此,本文的后续内容将专注于这三个模型,全面介绍LLaMA-Factory项目的使用方法及注意事项。在深入微调操作之前,首要任务是确保LLaMA-Factory开源项目在本地的正确部署。下面,我们将具体执行在本地环境中私有化部署LLaMA-Factory项目的操作。

2. LLaMA-Factory私有化部署

  • Step 1. 下载LLaMA-Factory的项目文件

  进入LLaMA-Factory的官方Github,地址:https://github.com/hiyouga/LLaMA-Factory , 在 GitHub 上将项目文件下载到有两种方式:克隆 (Clone) 和 下载 ZIP 压缩包。推荐使用克隆 (Clone)的方式。我们首先在GitHub上找到其仓库的URL。

  在执行命令之前,需要先安装git软件包,执行命令如下:

Bash
apt install git

然后再主目录中下载项目文件:

Bash
cd
git clone https://github.com/hiyouga/LLaMA-Factory.git

下载完成后即可看到LLaMA-Factory目录:

  • Step 2. 升级pip版本

  建议在执行项目的依赖安装之前升级 pip 的版本,如果使用的是旧版本的 pip,可能无法安装一些最新的包,或者可能无法正确解析依赖关系。升级 pip 很简单,只需要运行命令如下命令:

Bash
python -m pip install --upgrade pip

  • Step 3. 使用pip安装LLaMA-Factory项目代码运行的项目依赖

  在LLaMA-Factory中提供的 requirements.txt文件包含了项目运行所必需的所有 Python 包及其精确版本号。使用pip一次性安装所有必需的依赖,执行命令如下:

Bash
pip install -r requirements.txt --index-url https://mirrors.huaweicloud.com/repository/pypi/simple

通过上述步骤就已经完成了LLaMA-Factory模型的完整私有化部署过程。

3.基于LLaMA-Factory的模型自我意识微调过程

  正如此前所说,微调能够永久性的修改模型的各项能力和“知识记忆”,本次实验中我们就尝试“篡改”模型的“自我意识”。即现在我们让模型进行自我介绍时,模型会表示自己是来自阿里的通义千问模型。但通过微调,我们可以修改模型的“自我意识”,让他认为自己的名字叫“小林”,微调前:

微调后:

同时在这个实验中,我们也将完整的展示从数据集创建到执行微调、再到模型运行的一整个完整流程。基于LLaMA-Factory的完整高效微调流程如下:

  • Step 1. 创建微调数据集并上传

Python
import json
import random

#
定义问题和回答
questions = [
    "请你告诉我你是谁?", "你能介绍一下自己吗?", "你是谁?", "请介绍一下你自己。",
    "能告诉我你的身份吗?", "你的职业是什么?", "你有什么特长?", "你来自哪里?",
    "你的工作是什么?", "你的兴趣爱好是什么?"
]

responses = [
    "我是小林,一个致力于帮助人们解决问题的人工智能。",
    "我叫小林,是一名人工智能助手,专门处理数据分析任务。",
    "我是小林,一个从事教育支持的智能助理。",
    "名字叫小林,我是一款专为提供即时信息而设计的智能系统。",
    "我是小林,我能够协助处理各种复杂的数据问题。",
    "我叫小林,是一个人工智能,帮助人们进行科研和数据分析。",
    "我是小林,我的工作是通过机器学习和人工智能技术来支持决策制定。",
    "我是小林,一个设计用来进行语言翻译和沟通辅助的人工智能。",
    "作为小林,我提供基于云的数据处理服务。",
    "我是小林,主要负责数据挖掘和洞察发现。"
]

# 生成100条数据
extended_data_set = []

for _ in range(100):
    q = random.choice(questions)
    r = random.choice(responses)
    extended_data_set.append({
        "instruction": q,
        "input": "",
        "output": r
    })

# 将扩展的数据集写入JSON文件
extended_file_path = 'WAY_zh.json'
with open(extended_file_path, 'w', encoding='utf-8') as file:
    json.dump(extended_data_set, file, indent=4, ensure_ascii=False)

extended_file_path

Plaintext
'WAY_zh.json'

数据集文件如下:

然后使用cp命令,将其复制到LlaMa-Factory项目data文件夹内:

Bash
cp WAY_zh.json ~/LLaMA-Factory/data

这里的data文件包含了项目自带的各数据集:

  • Step 2. 修改数据集字典,添加数据集说明

  接下来为了让微调框架能够识别我们自定义的数据集,我们需要修改dataset_info.json中的信息,在其中添加我们新增数据集的基本说明。对于一个高效微调的数据集来说,说明文字非常简单,我们只需要添加数据集名字即可。关于完整的dataset_info.json如何修改,可以参考如下:https://github.com/hiyouga/LLaMA-Factory/blob/main/data/README_zh.md

这里我们使用vim命令对该文件进行修改:

Bash
cd ~/LLaMA-Factory/data
vim dataset_info.json

然后在弹出的页面输入i,进入编辑模式,并在开头输入如下内容:

Bash
"WAY_zh":{
  "file_name":"WAY_zh.json"

然后点击Esc,输入冒号(注意需要是英文输入法模式),再输出wq,即可保存并退出。

  • Step 3. 创建微调脚本

  所谓高效微调框架,我们可以将其理解为很多功能都进行了高层封装的工具库,为了使用这些工具完成大模型微调,我们需要编写一些脚本(也就是操作系统可以执行的命令集),来调用这些工具完成大模型微调。这里我们需要先回到LlaMa-Factory项目主目录下:

Bash
cd ..

然后创建一个名为single_lora_qwen.sh的脚本(脚本的名字可以自由命名)。这里我们可以使用使用vim创建这个脚本文件,同时也可以直接把课件中的single_lora_qwen.sh文件直接上传到jupyter主目录下,然后再用cp命令复制到LlaMa-Factory主目录下。这里我们先简单查看这个脚本文件内容:

Bash
#!/bin/bash
export CUDA_DEVICE_MAX_CONNECTIONS=1

export NCCL_P2P_DISABLE="1"
export NCCL_IB_DISABLE="1"


#
如果是预训练,添加参数       --stage pt \
# 如果是指令监督微调,添加参数  --stage sft \
# 如果是奖励模型训练,添加参数  --stage rm \
# 添加 --quantization_bit 4 就是4bit量化的QLoRA微调,不添加此参数就是LoRA微调 \



CUDA_VISIBLE_DEVICES=0 python src/train_bash.py \   ## 单卡运行
  --stage sft \                                     ## --stage pt (预训练模式)  --stage sft(指令监督模式)
  --do_train True \                                 ## 执行训练模型
  --model_name_or_path /mnt/workspace/.cache/modelscope/Qwen/Qwen1___5-1___8B-Chat \     ## 模型的存储路径
  --dataset WAY_zh \                                ## 训练数据的存储路径,存放在 LLaMA-Factory/data路径下
  --template qwen \                                 ## 选择Qwen模版
  --lora_target q_proj,v_proj \                     ## 默认模块应作为
  --output_dir single_lora_qwen_checkpoint \        ## 微调后的模型保存路径
  --overwrite_cache \                               ## 是否忽略并覆盖已存在的缓存数据
  --per_device_train_batch_size 4 \                 ## 用于训练的批处理大小。可根据 GPU 显存大小自行设置。
  --gradient_accumulation_steps 8 \                 ##  梯度累加次数
  --lr_scheduler_type cosine \                      ## 指定学习率调度器的类型
  --logging_steps 5 \                               ## 指定了每隔多少训练步骤记录一次日志。这包括损失、学习率以及其他重要的训练指标,有助于监控训练过程。
  --save_steps 100 \                                ## 每隔多少训练步骤保存一次模型。这是模型保存和检查点创建的频率,允许你在训练过程中定期保存模型的状态
  --learning_rate 5e-5 \                            ## 学习率
  --num_train_epochs 1.0 \                          ## 指定了训练过程将遍历整个数据集的次数。一个epoch表示模型已经看过一次所有的训练数据。
  --finetuning_type lora \                          ## 参数指定了微调的类型,lora代表使用LoRA(Low-Rank Adaptation)技术进行微调。
  --fp16 \                                          ## 开启半精度浮点数训练
  --lora_rank 8 \                                   ## 在使用LoRA微调时设置LoRA适应层的秩。

注:实际脚本文件最好不要出现中文备注,否则容易出现编辑格式导致的问题。

当我们拿到这个脚本文件后,首先将其上传到ModelScope NoteBook主目录下:

然后使用cp命令回到当前项目主目录下,查看脚本情况:

Bash
cd /mnt/workspace
ll

然后将其复制到LlaMa-Factory主目录下,并简单查看脚本位置:

Bash
cp single_lora_qwen.sh ~/LLaMA-Factory
cd ~/LLaMA-Factory/
ll

然后为了保险起见,我们需要对齐格式内容进行调整,以满足Ubuntu操作系统运行需要(此前是从Windows系统上复制过去的文件,一般都需要进行如此操作):

Bash
sed -i 's/\r$//' ./single_lora_qwen.sh

  • Step 4. 运行微调脚本,获取模型微调权重

  当我们准备好微调脚本之后,接下来即可围绕当前模型进行微调了。这里我们直接在命令行中执行sh文件即可,注意运行前需要为该文件增加权限:

Bash
chmod +x ./single_lora_qwen.sh
./single_lora_qwen.sh

由于模型本身并不大,外加文本数据结构较为简单,很快即可得到微调结果:

当微调结束之后,我们就可以在当前主目录下看到新的模型权重文件:

  • Step 5. 合并模型权重,获得微调模型

  接下来我们需要将该模型权重文件和此前的原始模型权重文件进行合并,才能获得最终的微调模型。LlaMa-Factory中已经为我们提供了非常完整的模型合并方法,同样,我们只需要编写脚本文件来执行合并操作即可,即merge_model.sh。同样,该脚本文件也可以按照此前single_lora_qwen.sh脚本相类似的操作,就是将课件中提供的脚本直接上传到Jupyter主目录下,再复制到LlaMa-Factory主目录下进行运行。

  首先简单查看merge_model.sh脚本文件内容:

Bash
#!/bin/bash

python src/export_model.py \               ##
用于执行合并功能的Python代码文件
  --model_name_or_path /mnt/workspace/.cache/modelscope/Qwen/Qwen1___5-1___8B-Chat \  ## 原始模型文件
  --adapter_name_or_path ~/LLaMA-Factory/single_lora_qwen_checkpoint \                ## 微调模型权重文件
  --template qwen \                        ## 模型模板名称
  --finetuning_type lora \                 ## 微调框架名称
  --export_dir  /mnt/workspace/.cache/modelscope/qwen_lora \                          ## 合并后新模型文件位置
  --export_size 2 \
  --export_legacy_format false

注:实际脚本文件最好不要出现中文备注,否则容易出现编辑格式导致的问题。

同样,我们将课件中的merge_model.sh文件上传到在线Jupyter Notebook中:

然后使用cp命令将其复制到LlaMa-Fcotry项目主目录下:

Bash
cd /mnt/workspace
cp merge_model.sh ~/LLaMA-Factory
cd ~/LLaMA-Factory/
chmod +x ./merge_model.sh
sed -i 's/\r$//' ./merge_model.sh

然后运行脚本,进行模型合并:

Bash
./merge_model.sh

接下来即可查看刚刚获得的新的微调模型:

Bash
cd /mnt/workspace/.cache/modelscope
ll

  • Step 6. 测试微调效果

  在我们为大模型“灌输”了一系列自主意识之后,我们尝试与其对话,测试此时模型是否会认为自己是“小林”。

Python
qwen_lora = '/mnt/workspace/.cache/modelscope/qwen_lora'
qwen_lora

Plaintext
'/mnt/workspace/.cache/modelscope/qwen_lora'

Python
from transformers import AutoModelForCausalLM, AutoTokenizer
device = "cuda" # the device to load the model onto

model = AutoModelForCausalLM.from_pretrained(
    qwen_lora,
    torch_dtype="auto",
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(qwen_lora)

Plaintext
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<00:00,  4.14it/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Python
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)

Python
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]

Python
response

Plaintext
'你好,我叫小林,我是来自阿里云的大规模语言模型,能够理解和生成多种自然语言,有任何问题都可以问我'

Logo

免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐