yule-BUAA / MergeLM

Codebase for Merging Language Models (ICML 2024)
764 stars 44 forks source link

如何合并多个模型? #29

Closed guanfaqian closed 3 months ago

guanfaqian commented 3 months ago

您好,这是一个非常有趣的工作,我想把他在我现在的任务上进行实验。我现在任务是Vicuna7B训练得到的。

请问如何合并呢?我看您的步骤是否可以按以下步骤:

Step 1: 将我训练的模型,得到DARE模型。 python inference_plms_glue.py --language_model_name roberta-base --weight_mask_rate 0.9 --use_weight_rescale 但是我看到language_model_name似乎只支持roberta-base和bert-base-uncased,我这种Vicuna(LLama-7b)要怎么做呢?我看您论文中似乎是支持的?

Step 2:合并DARE模型,似乎可以用mergekit实现? 另外三个任务时合并是可以三个任务一起,还是要两两任务一起?

希望能尽快得到您的回复!

yule-BUAA commented 3 months ago

嗨,

你好呀,

对于第一个问题,有两种解决方案:

  1. 如果想基于本仓库的代码执行模型合并,可以运行merge_llms_instruct_math_code.py文件实现, 例如想使用整合了DARE的Average Merging方法来合并WizardLM-13B-V1.2和WizardMath-13B-V1.0,可以运行
    python merge_llms_instruct_math_code.py --merge_instruct --merge_math --merging_method_name mask_merging --use_weight_rescale --weight_mask_rate 0.2 --mask_apply_method average_merging --tensor_parallel_size 1

    这个文件会首先为WizardLM-13B-V1.2和WizardMath-13B-V1.0执行mask rate为0.2且使用了rescale的DARE,得到两个消除了20%delta参数的模型,而后使用Average Merging进行合并。

考虑到你使用的是基于Vicuna7B的多个模型,而现在的代码仅支持WizardLM-13B-V1.2, WizardMath-13B-V1.0和llama-2-13b-code-alpaca的合并,所以需要适度的修改才能运行。主要修改的地方为将模型和任务的映射关系加入到merge_llms_instruct_math_code.pytask_model_mapping_dictfinetuned_model_backbone_mapping_dict变量中,例如任务是task_1,task_2 (task_1, task_2可以为instruct,math或者code), 模型为model_1, model_2,则修改task_model_mapping_dict={ "task_1": "model_1", "task_2": "model_2", }finetuned_model_backbone_mapping_dict={ "model_1": "Vicuna7B", "model_2": "Vicuna7B", }; 而后在执行merge_llms_instruct_math_code.py传入和模型对应的任务参数和合并方法参数即可。

  1. 使用mergekit库也可以支持DARE模型,可以使用dare_linear或者dare_ties方法,具体的可以参考mergekit库函数的说明。

对于第二个问题,在考虑三个任务时,可以三个都合并在一起验证效果,也可以两两合并验证pairwise的效果,这个取决于具体需求。我们在论文中对于上述两种情况均进行了实验。

yule-BUAA commented 3 months ago

另外我们近期会推出另一篇工作,里面的代码可以很好地支持各类模型的合并,比现在的实现方式更加方便使用。

欢迎到时关注哈^_^。

guanfaqian commented 3 months ago

嗨,

你好呀,

对于第一个问题,有两种解决方案:

  1. 如果想基于本仓库的代码执行模型合并,可以运行merge_llms_instruct_math_code.py文件实现, 例如想使用整合了DARE的Average Merging方法来合并WizardLM-13B-V1.2和WizardMath-13B-V1.0,可以运行
python merge_llms_instruct_math_code.py --merge_instruct --merge_math --merging_method_name mask_merging --use_weight_rescale --weight_mask_rate 0.2 --mask_apply_method average_merging --tensor_parallel_size 1

这个文件会首先为WizardLM-13B-V1.2和WizardMath-13B-V1.0执行mask rate为0.2且使用了rescale的DARE,得到两个消除了20%delta参数的模型,而后使用Average Merging进行合并。

考虑到你使用的是基于Vicuna7B的多个模型,而现在的代码仅支持WizardLM-13B-V1.2, WizardMath-13B-V1.0和llama-2-13b-code-alpaca的合并,所以需要适度的修改才能运行。主要修改的地方为将模型和任务的映射关系加入到merge_llms_instruct_math_code.pytask_model_mapping_dictfinetuned_model_backbone_mapping_dict变量中,例如任务是task_1,task_2 (task_1, task_2可以为instruct,math或者code), 模型为model_1, model_2,则修改task_model_mapping_dict={ "task_1": "model_1", "task_2": "model_2", }finetuned_model_backbone_mapping_dict={ "model_1": "Vicuna7B", "model_2": "Vicuna7B", }; 而后在执行merge_llms_instruct_math_code.py传入和模型对应的任务参数和合并方法参数即可。

  1. 使用mergekit库也可以支持DARE模型,可以使用dare_linear或者dare_ties方法,具体的可以参考mergekit库函数的说明。

对于第二个问题,在考虑三个任务时,可以三个都合并在一起验证效果,也可以两两合并验证pairwise的效果,这个取决于具体需求。我们在论文中对于上述两种情况均进行了实验。

好的,我试试您说的合并。 然后三个也是能一次性合并是吧?

guanfaqian commented 3 months ago

另外我们近期会推出另一篇工作,里面的代码可以很好地支持各类模型的合并,比现在的实现方式更加方便使用。

欢迎到时关注哈^_^。

谢谢,感觉这篇好像不试用7B的vicuna,我在扩散模型那个开源代码试了下,效果并不是很好。不过不清楚是不是参数设置问题。

guanfaqian commented 3 months ago

mergekit合并好像没有dare的操作?

yule-BUAA commented 3 months ago

嗨, 你好呀, 对于第一个问题,有两种解决方案:

  1. 如果想基于本仓库的代码执行模型合并,可以运行merge_llms_instruct_math_code.py文件实现, 例如想使用整合了DARE的Average Merging方法来合并WizardLM-13B-V1.2和WizardMath-13B-V1.0,可以运行
python merge_llms_instruct_math_code.py --merge_instruct --merge_math --merging_method_name mask_merging --use_weight_rescale --weight_mask_rate 0.2 --mask_apply_method average_merging --tensor_parallel_size 1

这个文件会首先为WizardLM-13B-V1.2和WizardMath-13B-V1.0执行mask rate为0.2且使用了rescale的DARE,得到两个消除了20%delta参数的模型,而后使用Average Merging进行合并。 考虑到你使用的是基于Vicuna7B的多个模型,而现在的代码仅支持WizardLM-13B-V1.2, WizardMath-13B-V1.0和llama-2-13b-code-alpaca的合并,所以需要适度的修改才能运行。主要修改的地方为将模型和任务的映射关系加入到merge_llms_instruct_math_code.pytask_model_mapping_dictfinetuned_model_backbone_mapping_dict变量中,例如任务是task_1,task_2 (task_1, task_2可以为instruct,math或者code), 模型为model_1, model_2,则修改task_model_mapping_dict={ "task_1": "model_1", "task_2": "model_2", }finetuned_model_backbone_mapping_dict={ "model_1": "Vicuna7B", "model_2": "Vicuna7B", }; 而后在执行merge_llms_instruct_math_code.py传入和模型对应的任务参数和合并方法参数即可。

  1. 使用mergekit库也可以支持DARE模型,可以使用dare_linear或者dare_ties方法,具体的可以参考mergekit库函数的说明。

对于第二个问题,在考虑三个任务时,可以三个都合并在一起验证效果,也可以两两合并验证pairwise的效果,这个取决于具体需求。我们在论文中对于上述两种情况均进行了实验。

好的,我试试您说的合并。 然后三个也是能一次性合并是吧?

是的,三个模型是可以一起合并的。

yule-BUAA commented 3 months ago

另外我们近期会推出另一篇工作,里面的代码可以很好地支持各类模型的合并,比现在的实现方式更加方便使用。 欢迎到时关注哈^_^。

谢谢,感觉这篇好像不试用7B的vicuna,我在扩散模型那个开源代码试了下,效果并不是很好。不过不清楚是不是参数设置问题。

可以先按照drop rate(0.1, 0.3, 0.5)较小的设置尝试下,再进行合并,防止drop rate过大导致效果不好。

yule-BUAA commented 3 months ago

mergekit合并好像没有dare的操作?

有的,DARE能够作为现有的模型合并方法的一个插件来使用,mergekit里面的dare_lineardare_ties就集成了DARE的操作,可以尝试下效果。

guanfaqian commented 3 months ago

diffusion,你试过他的代码吗?他的-p和 -lambda是否就是你论文中对应的删除的比例和缩放?那他这默认的0.13:3.0是不是不太对? python3 merge.py -p 0.13 -lambda 3.0 sdxl_base.safetensors sd_xl_turbo_1.0_fp16.safetensorssdxl_merged.safetensors``

yule-BUAA commented 3 months ago

我没有使用过这个代码,不过这里面的-p对应的是DARE中的drop rate,而-lambda对应的应该是pretrain参数在融合delta参数时的delta参数的重要性。

guanfaqian commented 3 months ago

我根据你的提示运行了(最后好像也报错了,这算运行成功吗?): python merge_llms_instruct_math_code.py --merge_instruct --merge_math --merge_code --merging_method_name mask_merging --use_weight_rescale --weight_mask_rate 0.2 --mask_apply_method average_merging --tensor_parallel_size 1 INFO:root:** Run starts. ** Loading checkpoint shards: 100%|██████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00, 1.05s/it] /home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/transformers/generation/configuration_utils.py:540: UserWarning: do_sample is set to False. However, temperature is set to 0.9 -- this flag is only used in sample-based generation modes. You should set do_sample=True or unset temperature. This was detected when initializing the generation config instance, which means the corresponding file may hold incorrect parameterization and should be fixed. warnings.warn( /home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/transformers/generation/configuration_utils.py:545: UserWarning: do_sample is set to False. However, top_p is set to 0.6 -- this flag is only used in sample-based generation modes. You should set do_sample=True or unset top_p. This was detected when initializing the generation config instance, which means the corresponding file may hold incorrect parameterization and should be fixed. warnings.warn( /home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/transformers/generation/configuration_utils.py:540: UserWarning: do_sample is set to False. However, temperature is set to 0.9 -- this flag is only used in sample-based generation modes. You should set do_sample=True or unset temperature. warnings.warn( /home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/transformers/generation/configuration_utils.py:545: UserWarning: do_sample is set to False. However, top_p is set to 0.6 -- this flag is only used in sample-based generation modes. You should set do_sample=True or unset top_p. warnings.warn( Loading checkpoint shards: 100%|██████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00, 1.03s/it] Loading checkpoint shards: 100%|██████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00, 1.05s/it] INFO:root:configuration is Namespace(merge_instruct=True, merge_math=True, merge_code=True, merging_method_name='mask_merging', scaling_coefficient=1.0, weight_format='delta_weight', weight_mask_rate=0.2, use_weight_rescale=True, mask_strategy='random', mask_apply_method='average_merging', start_index=0, end_index=9223372036854775807, tensor_parallel_size=1, pretrained_model_name='vicuna-7b-v1.5-16k', weight_mask_rates=[0.2, 0.2, 0.2], save_model_name='mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True') Loading checkpoint shards: 100%|██████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00, 1.12s/it] 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 291/291 [01:23<00:00, 3.50it/s] 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 291/291 [01:24<00:00, 3.46it/s] 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 291/291 [01:22<00:00, 3.54it/s] INFO:root:saving models at ./save_merge_models/instruct_math_code/instruct/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True... [2024-07-22 14:53:57,893] [INFO] [real_accelerator.py:191:get_accelerator] Setting ds_accelerator to cuda (auto detect) INFO:root:saving models at ./save_merge_models/instruct_math_code/math/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True... INFO:root:saving models at ./save_merge_models/instruct_math_code/code/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True... INFO:root:models are saved INFO:root:evaluating merged model on instruct task... INFO 07-22 14:55:42 config.py:1374] Downcasting torch.float32 to torch.float16. INFO 07-22 14:55:42 llm_engine.py:174] Initializing an LLM engine (v0.5.2) with config: model='./save_merge_models/instruct_math_code/instruct/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True', speculative_config=None, tokenizer='./save_merge_models/instruct_math_code/instruct/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, rope_scaling=None, rope_theta=None, tokenizer_revision=None, trust_remote_code=False, dtype=torch.float16, max_seq_len=16384, download_dir=None, load_format=LoadFormat.AUTO, tensor_parallel_size=1, pipeline_parallel_size=1, disable_custom_all_reduce=False, quantization=None, enforce_eager=False, kv_cache_dtype=auto, quantization_param_path=None, device_config=cuda, decoding_config=DecodingConfig(guided_decoding_backend='outlines'), observability_config=ObservabilityConfig(otlp_traces_endpoint=None), seed=0, served_model_name=./save_merge_models/instruct_math_code/instruct/mask_merging/average_merging/mask_0.2_0.2_0.2_rescale_True, use_v2_block_manager=False, enable_prefix_caching=False) INFO 07-22 14:55:50 model_runner.py:266] Loading model weights took 12.5562 GB INFO 07-22 14:55:54 gpu_executor.py:86] # GPU blocks: 3613, # CPU blocks: 512 INFO 07-22 14:55:55 model_runner.py:1007] Capturing the model for CUDA graphs. This may lead to unexpected consequences if the model is not static. To run the model in eager mode, set 'enforce_eager=True' or use '--enforce-eager' in the CLI. INFO 07-22 14:55:55 model_runner.py:1011] CUDA graphs can take additional 1~3 GiB memory per GPU. If you are running out of memory, consider decreasing gpu_memory_utilization or enforcing eager mode. You can also reduce the max_num_seqs as needed to decrease memory usage. INFO 07-22 14:56:07 model_runner.py:1208] Graph capturing finished in 12 secs. DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): huggingface.co:443 DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): stats.vllm.ai:443 DEBUG:urllib3.connectionpool:https://stats.vllm.ai:443 "POST / HTTP/1.1" 200 None [rank0]: Traceback (most recent call last): [rank0]: File "/mnt/drive0/gfq/MergeLM/merge_llms_instruct_math_code.py", line 264, in [rank0]: get_merge_performance(args=args, finetuned_model_names=finetuned_model_names, merge_task_names=merge_task_names, models_to_merge=models_to_merge, [rank0]: File "/mnt/drive0/gfq/MergeLM/merge_llms_instruct_math_code.py", line 143, in get_merge_performance [rank0]: test_alpaca_eval(llm=llm, finetuned_model_name=save_instruct_model_path, [rank0]: File "/mnt/drive0/gfq/MergeLM/inference_llms_instruct_math_code.py", line 154, in test_alpaca_eval [rank0]: eval_set = datasets.load_dataset(path="tatsu-lab/alpaca_eval", name="alpaca_eval", cache_dir=cache_dir)["eval"] [rank0]: File "/home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/datasets/load.py", line 1785, in load_dataset [rank0]: builder_instance = load_dataset_builder( [rank0]: File "/home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/datasets/load.py", line 1514, in load_dataset_builder [rank0]: dataset_module = dataset_module_factory( [rank0]: File "/home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/datasets/load.py", line 1231, in dataset_module_factory [rank0]: raise e1 from None [rank0]: File "/home/gfq/anaconda3/envs/merge/lib/python3.10/site-packages/datasets/load.py", line 1187, in dataset_module_factory [rank0]: raise ConnectionError(f"Couldn't reach '{path}' on the Hub ({type(e).name})") [rank0]: ConnectionError: Couldn't reach 'tatsu-lab/alpaca_eval' on the Hub (ConnectionError) DEBUG:filelock:Attempting to acquire lock 123195158330528 on /home/gfq/.triton/autotune/Fp16Matmul_2d_kernel.pickle.lock DEBUG:filelock:Lock 123195158330528 acquired on /home/gfq/.triton/autotune/Fp16Matmul_2d_kernel.pickle.lock DEBUG:filelock:Attempting to release lock 123195158330528 on /home/gfq/.triton/autotune/Fp16Matmul_2d_kernel.pickle.lock DEBUG:filelock:Lock 123195158330528 released on /home/gfq/.triton/autotune/Fp16Matmul_2d_kernel.pickle.lock DEBUG:filelock:Attempting to acquire lock 123195158330576 on /home/gfq/.triton/autotune/Fp16Matmul_4d_kernel.pickle.lock DEBUG:filelock:Lock 123195158330576 acquired on /home/gfq/.triton/autotune/Fp16Matmul_4d_kernel.pickle.lock DEBUG:filelock:Attempting to release lock 123195158330576 on /home/gfq/.triton/autotune/Fp16Matmul_4d_kernel.pickle.lock DEBUG:filelock:Lock 123195158330576 released on /home/gfq/.triton/autotune/Fp16Matmul_4d_kernel.pickle.lock

guanfaqian commented 3 months ago

1.这算运行成功吗?这个ConnectionError(f"Couldn't reach '{path}' on the Hub ({type(e).name})")要怎么解决?

2.另外我合并三个模型为什么得到三个文件夹,code, instruct, and math 不是应该得到三合一的模型吗?

3.文件中似乎是合并三个模型,我如果合并四个模型除了更改task_model_mapping_dict和finetuned_model_backbone_mapping_dict还有哪里要改的吗?

yule-BUAA commented 3 months ago
  1. 这个模型合并过程是成功了,就是在加载Alpaca Eval数据集的时候网络连接错误 ,解决方案为手动下载这个数据集,然后评测的时候指定这行cache_dir
  2. 代码的实现是考虑到不同任务的模型的tokenizer可能存在差异,所以为每个任务都保存了相应的tokenizer和模型,不过虽然是三个模型,这些模型的权重是完全一样的,只是存储了三份。我们也发现其实只需要额外存储tokenizer就行了,不需要多次存储模型,我们下一个工作的代码中解决了这个问题。
  3. 你如果想新增加模型,还需要额外考虑这个模型对应的评测任务是否是code, instruct, and math 中的某一种,如果不是的话,还需要额外写一个评测的函数,并在merge_llms_instruct_math_code.py中类比已有的任务增加相应的处理逻辑。
guanfaqian commented 2 months ago

您好,我在mergekit中运行成功了合并,使用以下的yml。但是,mergekit并没有给出如何填写您论文中重要参数drop probability和lambda ,您能教我怎么写吗?然后一般两者默认的关系有没有比例的要求?

models:
  - model: models/vicuna-7b-v1.5-16k
    parameters:
      weight: 1.0
  - model: models/vicuna_7b_A
    parameters:
      weight: 1.0
  - model: models/vicuna_7b_B
    parameters:
      weight: 1.0
  - model: models/vicuna_7b_C
    parameters:
      weight: 1.0
  - model: models/vicuna_7b_D
    parameters:
      weight: 1.0
base_model: models/vicuna-7b-v1.5-16k
merge_method: dare_ties
parameters:
  normalize: true
  int8_mask: true
dtype: float16
yule-BUAA commented 2 months ago

在mergekit中,可以通过指定density设置参数保留比例,即对应 1- drop probability;通过指定weight设置参数的重要性,对应lambda。这二者一般没有默认的比例关系,可以在0.3 ~ 0.9的范围内尝试density,在0.3 ~ 1.0的范围内尝试weight,具体的设定要看实际的合并效果。例如以0.5的density和0.5的weight来使用DARE:

models:
  - model: models/vicuna_7b_A
    parameters:
      density: 0.5
      weight: 0.5
  - model: models/vicuna_7b_B
    parameters:
      density: 0.5
      weight: 0.5
base_model: models/vicuna-7b-v1.5-16k
merge_method: dare_linear
dtype: bfloat16
tokenizer_source : union

也可以尝试组合DARE和TIES,例如

models:
  - model: models/vicuna_7b_A
    parameters:
      density: 0.5
      weight: 0.5
  - model: models/vicuna_7b_B
    parameters:
      density: 0.5
      weight: 0.5
base_model: models/vicuna-7b-v1.5-16k
merge_method: dare_ties
dtype: bfloat16
tokenizer_source : union
guanfaqian commented 2 months ago

weight对应lambda?那不是缩放吗?在0.3 ~ 1.0的范围内尝试weight?不是理论上drop0.5,缩放应该是2吗?

yule-BUAA commented 2 months ago

不是的,mergekit在实现DARE时,会自动使用density(即1 - drop rate)进行缩放,不需要人为指定缩放的比例,请参照这里

weight对应的是lambda,控制参数在合并中的重要性。

yule-BUAA commented 2 months ago

另外我们最新工作的代码也已经开源了,在当前代码的基础上进行了优化,更方便使用,应该也能解决你的这个需求。 如果有需要的话,可以通过 https://github.com/yule-BUAA/MergeLLM 使用。

guanfaqian commented 2 months ago

哦哦,好的,我试试。谢谢