# SFT微调
[](https://gitee.com/mindspore/docs/blob/r2.4.0/docs/mindformers/docs/source_zh_cn/usage/sft_tuning.md)
## 概述
SFT(Supervised Fine-Tuning,监督微调)采用有监督学习思想,是指在源数据集上进行预训练,得到一个原始模型,然后在一个新的数据集上对原始模型进行参数调整,得到新的模型,使其在新的任务上有更好的表现。
## SFT微调的基本流程
SFT微调整体包含以下几个部分:
- **预训练:**
首先需要在一个较大规模的数据集上训练一个神经网络模型,比如针对大语言模型,通常是在大量未标记的文本数据上进行,预训练阶段的目标是使模型获取通用的知识和理解能力。
- **微调:**
结合目标任务,用新的训练数据集对已经得到的预训练模型进行微调。在微调过程中,通过反向传播可以对原始模型的全部参数或者部分参数进行优化,使模型在目标任务上取得更好的效果。
- **评估:**
经过微调之后会得到一个新的模型,可以用目标任务的评测数据集对微调模型进行评估,从而得到微调模型在目标任务上的性能指标。
结合实际操作,可以将SFT微调分解为以下步骤:
1. **选择预训练模型:**
选择一个预训练的语言模型,如GPT-2、Llama2等。预训练模型通常是在大型文本语料库上进行过训练,以学习语言的通用表示。
2. **下载模型权重:**
针对选择的预训练模型,可以从HuggingFace模型库中下载预训练的权重。
3. **模型权重转换:**
结合自己所要使用的框架,对已经下载的HuggingFace权重进行权重转换,比如转换为MindSpore框架所支持的ckpt权重。
4. **数据集准备:**
结合微调的目标,选择用于微调任务的数据集,针对大语言模型,微调数据集一般是包含文本和标签的数据,比如alpaca数据集。同时在使用数据集时,需要对数据做相应的预处理,比如使用MindSpore框架时,需要将数据集转换为MindRecord格式。
5. **执行微调任务:**
使用微调任务的数据集对预训练模型进行训练,更新模型参数,如果是全参微调则会对所有参数进行更新,微调任务完成后,便可以得到新的模型。
## 基于MindFormers的全参微调实践
### 选择预训练模型
MindFormers目前已经支持业界主流大模型,该实践流程选择Llama2-7B模型SFT微调为例。
### 下载模型权重
MindFormers提供已经转换完成的预训练权重、词表文件用于预训练、微调和推理,用户也可以下载HuggingFace官方权重经过模型权重转换后进行使用。
词表下载链接:[tokenizer.model](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/tokenizer.model)
| 模型名称 | MindSpore权重 | HuggingFace权重 |
|:----------|:------------------------------------------------------------------------------------------------------------:| :---------------------------------------------------------------------------------------------: |
| Llama2-7B | [Link](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/llama2_7b.ckpt) | [Link](https://huggingface.co/meta-llama/Llama-2-7b-hf) |
> Llama2的所有权重都需要通过向Meta[提交申请](https://ai.meta.com/resources/models-and-libraries/llama-downloads)来获取,如有需要请自行申请。
### 模型权重转换
以[Llama2-7B模型](https://huggingface.co/meta-llama/Llama-2-7b-hf/tree/main)为例,原始的HuggingFace权重文件主要包含:
- `config.json`:模型架构的主要配置信息
- `generation_config.json`:文本生成相关的配置信息
- `safetensors文件`:模型权重文件
- `model.safetensors.index.json`:safetensors模型参数文件索引和描述模型切片的json文件
- `bin文件`:pytorch的模型权重文件
- `pytorch_model.bin.index.json`:pytorch索引和描述模型切片的json文件
- `tokenizer.json`:分词器的词汇配置文件
- `tokenizer.model`:模型的分词器
MindFormers提供权重转换脚本,通过执行[convert_weight.py转换脚本](https://gitee.com/mindspore/mindformers/blob/r1.3.0/convert_weight.py),可以将HuggingFace的权重转换为完整的ckpt权重。
```bash
python convert_weight.py --model llama --input_path TORCH_CKPT_DIR --output_path {path}/MS_CKPT_NAME
```
参数说明:
```commandline
model: 模型名称(其他模型请参考模型说明文档)
input_path: 下载HuggingFace权重的文件夹路径
output_path: 转换后的MindSpore权重文件保存路径
```
### 数据集准备
MindFormers提供**WikiText2**作为预训练数据集,**alpaca**作为微调数据集。
| 数据集名称 | 适用模型 | 适用阶段 | 下载链接 |
|:----------|:-------------------------------------:|:---------:| :--------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| alpaca | Llama2-7B
Llama2-13B
Llama2-70B | 微调 | [Link](https://github.com/tatsu-lab/stanford_alpaca/blob/main/alpaca_data.json) |
以alpaca数据集为例,下载数据集后需要对数据集进行预处理。预处理中所用的`tokenizer.model`可以参考模型权重下载进行下载。
**alpaca 数据预处理**
1. 执行MindFormers中的[alpaca_converter.py脚本](https://gitee.com/mindspore/mindformers/blob/r1.3.0/mindformers/tools/dataset_preprocess/llama/alpaca_converter.py),将数据集转换为多轮对话格式。
```bash
python alpaca_converter.py \
--data_path /{path}/alpaca_data.json \
--output_path /{path}/alpaca-data-conversation.json
```
参数说明:
```commandline
data_path: 输入下载的文件路径
output_path: 输出文件的保存路径
```
2. 执行MindFormers中的[llama_preprocess.py脚本](https://gitee.com/mindspore/mindformers/blob/r1.3.0/mindformers/tools/dataset_preprocess/llama/llama_preprocess.py),将数据转换为MindRecord格式。该操作依赖fastchat工具包解析prompt模板, 请提前安装fastchat >= 0.2.13。
```bash
python llama_preprocess.py \
--dataset_type qa \
--input_glob /{path}/alpaca-data-conversation.json \
--model_file /{path}/tokenizer.model \
--seq_length 4096 \
--output_file /{path}/alpaca-fastchat4096.mindrecord
```
参数说明:
```commandline
dataset_type: 预处理数据类型
input_glob: 转换后的alpaca的文件路径
model_file: 模型tokenizer.model文件路径
seq_length: 输出数据的序列长度
output_file: 输出文件的保存路径
```
### 执行微调任务
#### 单机训练
以Llama2-7B为例,执行msrun启动脚本,进行8卡分布式训练,启动命令如下:
```bash
bash scripts/msrun_launcher.sh "run_mindformer.py \
--config configs/llama2/finetune_llama2_7b.yaml \
--load_checkpoint /{path}/llama2_7b.ckpt \
--train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord \
--use_parallel True \
--run_mode finetune" 8
```
参数说明:
```commandline
config: 模型的配置文件,文件在MindFormers代码仓中config目录下
load_checkpoint: checkpoint文件的路径
train_dataset_dir: 训练数据集路径
use_parallel: 是否开启并行
run_mode: 运行模式,train:训练,finetune:微调,predict:推理
```
任务执行完成后,在mindformers/output目录下,会生成checkpoint文件夹,同时模型文件会保存在该文件夹下。
#### 多机训练
多机多卡微调任务与启动预训练类似,可参考多机多卡的预训练命令,并对命令进行如下修改:
1. 增加启动脚本入参`--load_checkpoint /{path}/llama2_7b.ckpt`加载预训练权重。
2. 设置启动脚本中的`--train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord`加载微调数据集。
3. 设置启动脚本中的`--run_mode finetune`,run_mode表示运行模式,train:训练,finetune:微调,predict:推理。
任务执行完成后,在mindformers/output目录下,会生成checkpoint文件夹,同时模型文件会保存在该文件夹下。