将lora权重合并到原模型

这是一个把lora参数合并到原模型的代码。

为什么要合并,虽然微调后预测时需要合并但不一定且保存,但是部分大模型评测项目都是用正常的huggingface checkpoint来测试,因此需要先行合并。

import os
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel, PeftConfig

def compare_model_weights(model1, model2):
    """
    Compare the weights of two models and return True as soon as any layer's weights are different (early exit).
    Return False if all weights are the same.
    """
    for name1, param1 in model1.named_parameters():
        if name1 in model2.state_dict():
            param2 = model2.state_dict()[name1]
            # Early exit if any weights are different
            if not torch.allclose(param1, param2):
                print(f"Layer '{name1}': Weights are DIFFERENT.")
                return True
        else:
            print(f"Layer '{name1}' not found in the second model.")
            return True
    
    # Return False if no differences were found
    return False


# Define the paths to your base model and LoRA directories
base_model_dir = os.environ.get("BASE_MODEL_DIR", None)
lora_model_dir = os.environ.get("LORA_MODEL_DIR", None)
merged_model_dir = os.environ.get("MERGED_MODEL_DIR", None)

# Step 1: Load the base model and tokenizer
# !!!! check torch_dtype in the config.json is same as below
# !!!! otherwise the size will change
print("Loading base model and tokenizer...")
model_base = AutoModelForCausalLM.from_pretrained(
    base_model_dir,
    load_in_8bit=False,
    torch_dtype=torch.float16,
    device_map={"": "cpu"},
    )
tokenizer = AutoTokenizer.from_pretrained(base_model_dir)

# Optional: check model params before and after merging
import copy
model_base_original = copy.deepcopy(model_base)

# Step 2: Load the LoRA configuration
print("Loading LoRA configuration...")
peft_config = PeftConfig.from_pretrained(lora_model_dir)

# Step 3: Load the LoRA weights into the base model
print("Loading LoRA model and applying weights...")
model_lora = PeftModel.from_pretrained(
    model_base, 
    lora_model_dir,
    device_map={"": "cpu"},
    torch_dtype=torch.float16,
    )

# Step 4: Merge the LoRA weights with the base model and unload LoRA
print("Merging LoRA weights into base model...")
model_merged = model_lora.merge_and_unload()
# Now `merged_model` contains the base model with LoRA weights merged

# Optional: check model params before and after merging
isdifferent = compare_model_weights(model_base_original, model_merged)
if isdifferent:
    print("Merging is valid.")
else:
    print("Merging changes no params. Merging may be invalid.")

# Save the merged model
print(f"Saving merged model to {merged_model_dir}...")
model_merged.save_pretrained(merged_model_dir, max_shard_size="1GB")
tokenizer.save_pretrained(merged_model_dir)

print("Model merging complete.")

这个代码会在合并时顺便检查合并前后的参数是否很接近(可能lora没训练成果,参数变化很小)。很接近时会通知你可能有异常,但还是会保存合并结果。

export BASE_MODEL_DIR=<?>
export LORA_MODEL_DIR=<?>
export MERGED_MODEL_DIR=<?>

python merge_and_check.py

 这是脚本命令,把前三个变量分别换成1.原模型地址、2.lora训练结果保存地址、3.用于保存合并后的模型地址。

{
  "_name_or_path": "meta-llama/Llama-2-7b-hf",
  "architectures": [
    "LlamaForCausalLM"
  ],
  "bos_token_id": 1,
  "eos_token_id": 2,
  "hidden_act": "silu",
  "hidden_size": 4096,
  "initializer_range": 0.02,
  "intermediate_size": 11008,
  "max_position_embeddings": 4096,
  "model_type": "llama",
  "num_attention_heads": 32,
  "num_hidden_layers": 32,
  "num_key_value_heads": 32,
  "pretraining_tp": 1,
  "rms_norm_eps": 1e-05,
  "rope_scaling": null,
  "tie_word_embeddings": false,
  "torch_dtype": "float16",       !!!!!!!!!!!!!!注意这个参数
  "transformers_version": "4.31.0.dev0",
  "use_cache": true,
  "vocab_size": 32000
}

问题:lora合并前后模型大小不一样

说明:使用时注意下torch_dtype参数,要与你原先下载的模型的config.json里的torch_dtype要一致,如上面的json内容。模型预加载时这个参数默认是float32,如果没有指定的话,合并前后的模型大小会不一致。以Llama2-7b为例,下载的模型是float16,不指定torch_dtype,你的模型大小会是原模型大小的两倍。

参考:

Model size doubles after .merge_and_unload() and .save_pretrained() · Issue #137 · bigcode-project/starcoder · GitHub

LORA(Locally Optimal Block-wise Alignment)是一种用于合并模型的机器学习方法。在LORA中,模型合并是通过将多个基于树的模型(例如决策树或随机森林)的预测结果进行整合来实现的。 首先,我们需要训练多个基于树的模型,每个模型使用不同的训练集或特征集合。这些模型可以使用相同的算法或不同的算法进行训练,只要它们能够产生有意义的预测结果。 一旦我们训练完成了多个模型,我们就可以开始合并它们的预测结果。合并过程中,我们需要定义一个规则或算法来决定如何将多个模型的预测结果进行整合。 常用的合并方法是投票,即对每个样本的预测结果进行统计,根据多数票则来确定最终的预测结果。这意味着如果多数模型对某个样本预测为A类别,则最终的预测结果也为A类别。 另一种常用的合并方法是平均,即将多个模型的预测结果取平均。这种方法适用于回归问题,其中每个模型都给出一个连续值的预测结果,最终的预测结果可以通过取平均值来获得。 此外,还有一些更复杂的合并方法,例如基于权重合并,其中给每个模型分配一个权重,并根据权重对预测结果进行加权平均。这种方法可以更好地利用每个模型的特点,提高整体预测性能。 通过使用LORA方法,我们可以有效地合并多个基于树的模型,提高预测的准确性和鲁棒性。然而,在选择模型合并方法时,我们需要谨慎地考虑各种因素,例如模型之间的相关性、模型的性能指标和数据集的特点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值