一、计算平台环境配置
计算平台配置选择MLU370-X8计算卡,镜像使用cambricon_pytorch_container:v24.02.1-torch2.1.0-ubuntu22.04-py310
二、深度学习相关环境配置
文档中需要安装5个定制python库:deepspeed、flash_attn、transformers以及peft,其中镜像中定制的deepspeed(0.10.1)、flash_attn(2.3.3)已经内置。然而,本人并未能获得这两个定制库的源文件或下载地址。感兴趣者可按下列代码安装寒武纪论坛(Index of /static/Basis/ (cambricon.com))发布的最新版安装包进行尝试。
deepspeed:
wget https://sdk.cambricon.com/static/Basis/MLU370_X86_ubuntu20.04/deepspeed_mlu-0.9.1-py3-none-any.whl
pip install deepspeed_mlu-0.9.1-py3-none-any.whl
flash_attn:
wget https://sdk.cambricon.com/static/Basis/MLU370_X86_ubuntu20.04/flash_attn-2.3.3-cp310-cp310-linux_x86_64.whl
pip install flash_attn-2.3.3-cp310-cp310-linux_x86_64.whl
除上述两个安装包外,其他定制库均可以按照“下载源代码”-“转换算子”-“源码安装”的方式进行安装。
accelerate:
git clone https://github.com/huggingface/accelerate.git
python /torch/src/catch/tools/torch_gpu2mlu/torch_gpu2mlu.py -i accelerate/
cd accelerate_mlu
pip install -e .
transformers:
git clone https://github.com/huggingface/transformers.git -b v4.39.0
python /torch/src/catch/tools/torch_gpu2mlu/torch_gpu2mlu.py -i transformers/
cd transformers_mlu
pip install -e .
peft:
git clone https://github.com/huggingface/peft.git
python /torch/src/catch/tools/torch_gpu2mlu/torch_gpu2mlu.py -i peft/
cd peft_mlu
pip install -e .
本文档基于某大模型测试文档修改得到,因此可能部分python库并不需要安装,带来的步骤冗余敬请谅解。
由于llama-factory无法识别deepspeed_mlu,需对deepspeed_mlu的METADATA进行修改,将deepspeed_mlu-0.10.1.dist-info改为deepspeed-0.10.1.dist-info:
cp -r /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed_mlu-0.10.1.dist-info/ /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed-0.10.1.dist-info/
vim /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed-0.10.1.dist-info/METADATA
Vim修改内容:`Name: deepspeed-mlu`修改为`Name: deepspeed`。
若使用0.9.0版本deepspeed,可尝试按照下列教程进行修改
【PyTorch LLM】如何用MLU370运行FastChat的Finetune - 寒武纪软件开发平台 - 开发者论坛 (cambricon.com)
mv /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed_mlu-0.9.0.dist-info/ /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed-0.10.2.dist-info/
vim /torch/venv3/pytorch/lib/python3.10/site-packages/deepspeed-0.10.2.dist-info/METADATA
Vim修改内容:`Name: deepspeed-mlu Version: 0.9.0`修改为`Name: deepspeed Version: 0.10.2`。
三、LLaMA-Factory下载
步骤仍旧为“下载源代码”-“转换算子”。注:本文下载LLaMA-Factory为GitHub - Mu-L/LLaMA-Factory: Easy-to-use LLM fine-tuning framework (LLaMA, BLOOM, Mistral, Baichuan, Qwen, ChatGLM)。官方版地址GitHub - hiyouga/LLaMA-Factory: Unify Efficient Fine-Tuning of 100+ LLMs下载的最新版本需要源码安装,且启动命令为llamafactory-cli,与本文流程有所不同。感兴趣者可自行尝试最新版LLaMA-Factory在寒武纪MLU平台上运行方式。
下载和算子转换代码(注:此版本无需源码安装):
git clone https://github.com/Mu-L/LLaMA-Factory.git
python /torch/src/catch/tools/torch_gpu2mlu/torch_gpu2mlu.py -i LLaMA-Factory
cd LLaMA-Factory_mlu
进入LLaMA-Factory_mlu目录后,需安装依赖。安装依赖前,首先需修改requirements.txt文件,将第二节出现的accelerate、deepspeed、flash_attn、transformers以及peft注释掉,然后安装依赖:
pip install -r requirements
四、SFT微调模型
不同模型训练时有不同模板,若想查询模板,可使用以下命令打开WebUI界面,选择需要训练的模型,填写模型地址,选择数据名称,并调整需要调整的超参数后,点击Preview command,复制代码后在bash中可直接单卡训练,例如:
CUDA_VISIBLE_DEVICES=0 python src/train_bash.py \
--stage sft \
--do_train True \
--model_name_or_path your_model_path \
--adapter_name_or_path your_adapter_path \
--finetuning_type lora \
--template chatglm3 \
--dataset_dir data \
--dataset example,alpaca_en \
--cutoff_len 1024 \
--learning_rate 5e-05 \
--num_train_epochs 3.0 \
--max_samples 100000 \
--per_device_train_batch_size 4 \
--gradient_accumulation_steps 4 \
--lr_scheduler_type cosine \
--max_grad_norm 1.0 \
--logging_steps 5 \
--save_steps 100 \
--warmup_steps 0 \
--lora_rank 8 \
--lora_dropout 0.1 \
--lora_target query_key_value \
--output_dir your_output_path \
--fp16 True \
--plot_loss True
参考Github上信息,若需要多卡训练,可将代码改为:
##需要修改的部分
deepspeed --num_gpus 8 --master_port=9901 src/train_bash.py \
--deepspeed ds_config.json \
##与查询到的代码相同的部分
--stage sft \
--do_train True \
--model_name_or_path your_model_path \
--adapter_name_or_path your_adapter_path \
--finetuning_type lora \
--template chatglm3 \
--dataset_dir data \
--dataset example,alpaca_en \
--cutoff_len 1024 \
--learning_rate 5e-05 \
--num_train_epochs 3.0 \
--max_samples 100000 \
--per_device_train_batch_size 4 \
--gradient_accumulation_steps 4 \
--lr_scheduler_type cosine \
--max_grad_norm 1.0 \
--logging_steps 5 \
--save_steps 100 \
--warmup_steps 0 \
--lora_rank 8 \
--lora_dropout 0.1 \
--lora_target query_key_value \
--output_dir your_output_path \
--fp16 True \
--plot_loss True
由于训练所使用的代码中存在torch.cuda.ipc_collect()函数,而修改后的torch.mlu并没有ipc_collect()功能,因此会报错。针对此问题,本人采取措施为直接注释掉此行代码。具体而言,注释掉`LLaMA-Factory_mlu/src/llmtuner/extras/misc.py`117行的torch.mlu.ipc_collect():
def torch_gc() -> None:
r"""
Collects GPU memory.
"""
gc.collect()
if torch.mlu.is_available():
torch.mlu.empty_cache()
#torch.mlu.ipc_collect() <—— 注释掉这里
由于torch_gc()函数在其他处存在调用,因此不可直接将torch_gc()函数整体注释掉。
五、模型导出
根据Github的文档,导出训练好的模型代码如下:
python src/export_model.py \
--model_name_or_path your_model_path (训练前的模型) \
--adapter_name_or_path your_adapter_path (训练得到的adapter) \
--template default \
--finetuning_type lora \
--export_dir your_export_path \
--export_size 2 \
--export_legacy_format False
使用该代码导出时,会报错`device mlu is invalid`,结合报错信息,做如下修改:
修改`peft/mlu/src/peft/utils`中的441-447行
if use_safetensors:
if hasattr(torch.backends, "mps") and (device == torch.device("mps")):
adapters_weights = safe_load_file(filename, device="cpu")
else:
#原版:adapters_weights = safe_load_file(filename, device=device)
#修改后:
adapters_weights = safe_load_file(filename, device="cpu")
else:
adapters_weights = torch.load(filename, map_location=torch.device(device))
注意,`peft/mlu/src/peft/utils`位置为第二部分peft_mlu所在位置。若找不到,可以从报错信息里查找到需修改文件的具体位置。
六、模型微调效果
具体微调效果因数据和任务而异,本人以所做项目为例展示微调效果。任务为从一段论文摘要中提取出研究结论,要求用陈述事实语气,主语不能为“This study”等,必须为研究结论本身。
微调前:
微调后:
可以看出微调前,抽取的结论全为“This study”,“This research”等作为主语,完全不符合Prompt中提出的要求。经过微调后,除了最后一条,其他的结论均为陈述研究结果,而非“此研究发现了xxx”等内容。同时,结论抽取更为全面。
MLU370
4080 super(16g)
从训练时间来看,单机8卡MLU370训练5000+数据时间为半小时,在单机单卡4080super电脑上训练相同模型,batchsize为2时,预估训练时间为5小时40分钟,而batchsize为1时,预估训练时间仅为1小时40分钟,由于本人对大模型微调理论知识掌握尚不充分,对于此现象较难解释,望对此有了解者悉心指教。
七、存在问题
目前本文所示流程存在以下问题有待解决:
- 模型微调和导出部分所做的代码修改是否合理,是否会导致潜在问题?
- MLU370-X8显存为24G,高于4080super(16G),但在训练时MLU370-X8选择batchsize=1时就会爆显存,只能调低cutoff_lenth,而同样任务,4080super可以选择batchsize=2。该情况是否由注释掉ipc_collect()所致?还是MLU370计算方式不同所致?
- 由于将算子转换为MLU,暂时无法使用bitsandby进行4/8bit量化,是否可以实现以及如何实现有待后续研究。
由于本人刚接触大模型不久,对理论知识掌握极其薄弱。若文中出现不合理指出,欢迎各位批评指正!同时,文中测试流程若存在不明确之处,欢迎评论或私信展开讨论!