

LLM-Pruner:关于大语言模型的结构修剪[ARXIV]
Xinyin MA,Gongfan Fang,Xinchao Wang
新加坡国立大学
.from_pretrained()加载模型。 加入我们的微信小组聊天:
pip install -r requirement.txt
bash script/llama_prune.sh
该脚本将用修剪20%的参数压缩Llama-7b模型。所有预训练的模型和数据集将自动下载,因此您无需手动下载资源。首次运行此脚本时,它将需要一些时间才能下载模型和数据集。
它需要三个步骤才能修剪LLM:
修剪和训练后修剪后,我们遵循LM评估 - 进行评估。
? Llama/Llama-2修剪约20%的参数已修剪:
python hf_prune.py --pruning_ratio 0.25
--block_wise
--block_mlp_layer_start 4 --block_mlp_layer_end 30
--block_attention_layer_start 4 --block_attention_layer_end 30
--pruner_type taylor
--test_after_train
--device cpu --eval_device cuda
--save_ckpt_log_name llama_prune
参数:
Base model :从Llama或Llama-2中选择基本模型,然后将pretrained_model_name_or_path _model_name_or_path传递到--base_model 。该模型名称用于AutoModel.from_pretrained加载预训练的LLM。例如,如果要使用具有130亿个参数的Llama-2,则将meta-llama/Llama-2-13b-hf传递到--base_model 。Pruning Strategy :使用相应的命令选项在块,频道或层修剪之间进行选择:{-block_wise},{ - channel_wise},{ - layer_wise-layer_wise -layer-layer number_of_layers}。对于块修剪,请指定要修剪的开始和端层。通过渠道修剪不需要额外的论点。对于图层修剪,请使用-Layer number_of_layers指定修剪后要保留的所需层数。Importance Criterion :使用-pruner_type参数从L1,L2,随机或Taylor中进行选择。对于Taylor Pruner,请选择以下选项之一:vectorize,param_second,param_first,param_mix。默认情况下,使用param_mix,结合了近似的二阶Hessian和一阶梯度。如果使用L1,L2或随机,则无需额外的参数。Pruning Ratio :指定组的修剪比。它与参数的修剪速率不同,因为将组作为最小单元去除。Device和Eval_device :可以在不同的设备上执行修剪和评估。基于泰勒的方法需要在修剪过程中向后计算,这可能需要大量的GPU RAM。我们的实施使用CPU来进行重要的估计(也支持GPU,简单地使用 - 设备CUDA)。 eval_device用于测试修剪模型。 如果您想尝试Vicuna,请指定参数--base_model到达Vicuna重量的路径。请关注https://github.com/lm-sys/fastchat获得Vicuna重量。
python hf_prune.py --pruning_ratio 0.25
--block_wise
--block_mlp_layer_start 4 --block_mlp_layer_end 30
--block_attention_layer_start 4 --block_attention_layer_end 30
--pruner_type taylor
--test_after_train
--device cpu --eval_device cuda
--save_ckpt_log_name llama_prune
--base_model PATH_TO_VICUNA_WEIGHTS
有关更多详细信息,请参阅示例/Baichuan
python llama3.py --pruning_ratio 0.25
--device cuda --eval_device cuda
--base_model meta-llama/Meta-Llama-3-8B-Instruct
--block_wise --block_mlp_layer_start 4 --block_mlp_layer_end 30
--block_attention_layer_start 4 --block_attention_layer_end 30
--save_ckpt_log_name llama3_prune
--pruner_type taylor --taylor param_first
--max_seq_len 2048
--test_after_train --test_before_train --save_model
CUDA_VISIBLE_DEVICES=X python post_training.py --prune_model prune_log/PATH_TO_PRUNE_MODEL/pytorch_model.bin
--data_path yahma/alpaca-cleaned
--lora_r 8
--num_epochs 2
--learning_rate 1e-4
--batch_size 64
--output_dir tune_log/PATH_TO_SAVE_TUNE_MODEL
--wandb_project llama_tune
确保将PATH_TO_PRUNE_MODEL替换为步骤1中修剪模型的路径,然后用要保存调谐模型的所需位置替换PATH_TO_SAVE_TUNE_MODEL 。
提示:不建议在Float16中训练Llama-2,并且众所周知会产生NAN;因此,该模型应在Bfloat16中进行训练。
deepspeed --include=localhost:1,2,3,4 post_training.py
--prune_model prune_log/PATH_TO_PRUNE_MODEL/pytorch_model.bin
--data_path MBZUAI/LaMini-instruction
--lora_r 8
--num_epochs 3
--output_dir tune_log/PATH_TO_SAVE_TUNE_MODEL
--extra_val_dataset wikitext2,ptb
--wandb_project llmpruner_lamini_tune
--learning_rate 5e-5
--cache_dataset
对于修剪模型,只需使用以下命令加载模型即可。
pruned_dict = torch.load(YOUR_CHECKPOINT_PATH, map_location='cpu')
tokenizer, model = pruned_dict['tokenizer'], pruned_dict['model']
由于修剪模型中模块之间的配置不同,在修剪模型中,某些层可能具有更大的宽度,而其他层的修剪较大,因此使用.from_pretrained() (通过拥抱面孔)加载模型是不切实际的。目前,我们使用torch.save存储修剪模型。
由于修剪模型在每一层中具有不同的配置,就像某些图层可能更宽,但有些层的修剪得多,因此该模型无法在拥抱面中加载.from_pretrained() 。当前,我们只需使用torch.save来保存修剪模型和torch.load 。负载即可加载修剪的模型。
我们提供了一个简单的脚本来使用带有培训后培训的预训练 /修剪模型 /修剪模型进行基因文本。
python generate.py --model_type pretrain
python generate.py --model_type pruneLLM --ckpt <YOUR_MODEL_PATH_FOR_PRUNE_MODEL>
python generate.py --model_type tune_prune_LLM --ckpt <YOUR_CKPT_PATH_FOR_PRUNE_MODEL> --lora_ckpt <YOUR_CKPT_PATH_FOR_LORA_WEIGHT>
以上说明将在本地部署您的LLMS。

为了评估修剪模型的性能,我们遵循LM评估 - 评估模型:
lm-evaluation-harness的输入要求。从训练后步骤中调整的检查点将以以下格式保存: - PATH_TO_SAVE_TUNE_MODEL
| - checkpoint-200
| - pytorch_model.bin
| - optimizer.pt
...
| - checkpoint-400
| - checkpoint-600
...
| - adapter_config.bin
| - adapter-config.json
通过以下命令安排文件:
cd PATH_TO_SAVE_TUNE_MODEL
export epoch=YOUR_EVALUATE_EPOCH
cp adapter_config.json checkpoint-$epoch/
mv checkpoint-$epoch/pytorch_model.bin checkpoint-$epoch/adapter_model.bin
如果要评估checkpoint-200 ,则将Epoch等于200的export epoch=200 。
export PYTHONPATH='.'
python lm-evaluation-harness/main.py --model hf-causal-experimental
--model_args checkpoint=PATH_TO_PRUNE_MODEL,peft=PATH_TO_SAVE_TUNE_MODEL,config_pretrained=PATH_OR_NAME_TO_BASE_MODEL
--tasks openbookqa,arc_easy,winogrande,hellaswag,arc_challenge,piqa,boolq
--device cuda:0 --no_cache
--output_path PATH_TO_SAVE_EVALUATION_LOG
在这里,用保存修剪模型和调谐模型的路径替换PATH_TO_PRUNE_MODEL和PATH_TO_SAVE_TUNE_MODEL ,而PATH_OR_NAME_TO_BASE_MODEL用于加载基本模型的配置文件。
[UPDATE]:如果您想使用调谐检查点评估修剪模型,我们将上传脚本以简单地评估过程。只需使用以下命令:
CUDA_VISIBLE_DEVICES=X bash scripts/evaluate.sh PATH_OR_NAME_TO_BASE_MODEL PATH_TO_SAVE_TUNE_MODEL PATH_TO_PRUNE_MODEL EPOCHS_YOU_WANT_TO_EVALUATE
在命令中替换模型的必要信息。如果您想在一个命令中评估几个检查点,则最终的习惯是在不同的时期迭代。例如:
CUDA_VISIBLE_DEVICES=1 bash scripts/evaluate.sh decapoda-research/llama-7b-hf tune_log/llama_7B_hessian prune_log/llama_prune_7B 200 1000 2000
python test_speedup.py --model_type pretrain
python test_speedup.py --model_type pruneLLM --ckpt <YOUR_MODEL_PATH_FOR_PRUNE_MODEL>
Llama-7b的简短定量结果:

Vicuna-7b的结果:

CHATGLM-6B的结果:

修剪模型的统计数据:

LLM-Pruner的结果为259万样品:
| 修剪比率 | #param | 记忆 | 潜伏期 | 加速 | 布尔克 | piqa | Hellaswag | Winogrande | 弧 | 弧 | OBQA | 平均的 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Llama-7b | 6.74b | 12884.5MIB | 69.32 | 1倍 | 73.18 | 78.35 | 72.99 | 67.01 | 67.45 | 41.38 | 42.40 | 63.25 |
| 与羊驼(50k)的骆驼5.4b | 5.47b | 10488.4mib | 58.55 | 1.18x | 64.62 | 77.20 | 68.80 | 63.14 | 64.31 | 36.77 | 39.80 | 59.23 |
| Lamini(259m) | 5.47b | 10488.4mib | 58.55 | 1.18x | 76.57 | 77.37 | 66.60 | 65.82 | 70.62 | 40.70 | 38.80 | 62.36 |
可以在论文中找到更多结果。
| 原始型号 | 输出 | 修剪模型 | 输出 |
|---|---|---|---|
| Llama-7b | 宇宙是存在的全部空间,时间,物质和能量。它包括所有物质和能量,无论是否可见,实际上整个宇宙都是看不见的。关于其起源和最终命运的理论很多... | Llama-5.4b | 宇宙是存在的全部空间,时间,物质和能量。构成物理学的法律 - 电子原子,吸引其他物体的磁铁,绕太阳绕行的行星 - 一直保持一致... |
| Vicuna-7b | 建立iOS应用程序的10个步骤:1。研究和发展这个想法。 2。确定要使用的平台(iOS,Android或两者)。 3。制定计划和预算。 4.雇用一个开发人员团队。 5。设计用户界面(UI)。 6。开发用户界面(UI)。 7。在应用程序上进行测试和迭代。 8。将应用程序提交到应用商店。 9.优化应用程序的性能和用户体验(UX)。 10。市场并推广该应用程序。 | Vicuna-5.4b | 构建iOS应用程序的10个步骤:1。计划您的应用程序:确定应该做什么,它的外观以及构建它的成本。 2.雇用开发人员:良好的iOS开发人员将帮助您设计用户界面,创建应用程序并确保它不含错误。 3。创建一个用户界面:这是魔术发生的地方。您应用程序的用户界面将在这一点上进行设计和嘲笑... |
| chatglm-6b | 写一首关于爱与和平的诗。在人生的喧嚣中,我发现你的爱是一个舒缓的和平。这种感觉无法传达,这种联系是无法远距离的。凭着你的微笑,你的眼睛,你的拥抱,我感到只有你才能给予的归属感。这是一种永远持续的爱,一种不能失败的爱... | chatglm-5.6b | 写一首关于爱与和平的诗。爱与和平,这两个奇妙的事情我的心中纯净而无尽的欲望,我必须寻求很长一段时间,我知道。 |
由于该项目中使用的模型和存储库的版本变化,我们列出了一些已知版本问题以及重现我们方法所需的特定版本:
如果您觉得这个项目有用,请引用
@inproceedings{ma2023llmpruner,
title={LLM-Pruner: On the Structural Pruning of Large Language Models},
author={Xinyin Ma and Gongfan Fang and Xinchao Wang},
booktitle={Advances in Neural Information Processing Systems},
year={2023},
}
@article{fang2023depgraph,
title={DepGraph: Towards Any Structural Pruning},
author={Fang, Gongfan and Ma, Xinyin and Song, Mingli and Mi, Michael Bi and Wang, Xinchao},
journal={The IEEE/CVF Conference on Computer Vision and Pattern Recognition},
year={2023}
}