gpt4 book ai didi

Llama2-Chinese项目:3.2-LoRA微调和模型量化

转载 作者:我是一只小鸟 更新时间:2023-10-02 07:01:59 73 4
gpt4 key购买 nike

  提供LoRA微调和全量参数微调代码,训练数据为 data/train_sft.csv ,验证数据为 data/dev_sft.csv ,数据格式为 "<s>Human: "+问题+"\n</s><s>Assistant: "+答案 。本文主要介绍Llama-2-7b模型LoRA微调以及4bit量化的实践过程.

1.LoRA微调脚本   LoRA微调脚本 train/sft/finetune_lora.sh 如下所示:

                
                  output_model=save_folder
                  
# 需要修改到自己的输入目录
if  [ ! -d  ${output_model}  ]; then   
    mkdir  ${output_model}
fi
cp ./finetune.sh  ${output_model}
CUDA_VISIBLE_DEVICES=0,1 deepspeed --num_gpus 2  finetune_clm_lora.py \               # 用于训练的脚本
    --model_name_or_path meta-llama/Llama-2-7b-chat-hf \                              # 预训练模型路径
    --train_files ../../data/train_sft.csv \                                          # 训练数据
                ../../data/train_sft_sharegpt.csv \                                   # 训练数据
    --validation_files  ../../data/dev_sft.csv \                                      # 验证数据
                         ../../data/dev_sft_sharegpt.csv \                            # 验证数据
    --per_device_train_batch_size 1 \                                                 # 每个设备的训练批次大小
    --per_device_eval_batch_size 1 \                                                  # 每个设备的验证批次大小
    --do_train \                                                                      # 是否训练
    --do_eval \                                                                       # 是否验证
    --use_fast_tokenizer  false  \                                                      # 是否使用快速分词器
    --output_dir  ${output_model}  \                                                    # 输出目录
    --evaluation_strategy  steps \                                                    # 评估策略
    --max_eval_samples 800 \                                                          # 最大验证样本数
    --learning_rate 1e-4 \                                                            # 学习率
    --gradient_accumulation_steps 8 \                                                 # 梯度累积步数
    --num_train_epochs 10 \                                                           # 训练轮数
    --warmup_steps 400 \                                                              # 预热步数
    --load_in_bits 4 \                                                                # 加载位数
    --lora_r 8 \                                                                      # lora_r表示秩的大小
    --lora_alpha 32 \                                                                 # lora_alpha表示控制模型对原始预训练参数的更新程度
    --target_modules q_proj,k_proj,v_proj,o_proj,down_proj,gate_proj,up_proj \        # 目标模块
    --logging_dir  ${output_model} /logs \                                              # 日志目录
    --logging_strategy steps \                                                        # 日志策略
    --logging_steps 10 \                                                              # 日志步数
    --save_strategy steps \                                                           # 保存策略
    --preprocessing_num_workers 10 \                                                  # 预处理工作数
    --save_steps 20 \                                                                 # 保存步数
    --eval_steps 20 \                                                                 # 评估步数
    --save_total_limit 2000 \                                                         # 保存总数限制
    --seed 42 \                                                                       # 种子
    --disable_tqdm  false  \                                                            # 禁用tqdm
    --ddp_find_unused_parameters  false  \                                              # ddp_find_unused_parameters
    --block_size 2048 \                                                               # 块大小
    --report_to tensorboard \                                                         # 报告到tensorboard
    --overwrite_output_dir \                                                          # 覆盖输出目录
    --deepspeed ds_config_zero2.json \                                                # deepspeed配置文件
    --ignore_data_skip  true  \                                                         # 忽略数据跳过
    --bf16 \                                                                          # bf16
    --gradient_checkpointing \                                                        # 梯度检查点
    --bf16_full_eval \                                                                # bf16_full_eval
    --ddp_timeout 18000000 \                                                          # ddp_timeout
    | tee -a  ${output_model} /train.log                                                # 日志输出

     # --resume_from_checkpoint ${output_model}/checkpoint-20400 \                    # 恢复检查点

2.LoRA微调代码   LoRA微调具体实现代码 train/sft/finetune_clm_lora.py 参考文献[3]。这里要说明下HuggingFace开源的一个高效微调大模型的PEFT库,目前支持很多方法和模型,详见参考文献[4][5]。LoRA(Low-Rank Adaptation)的本质就是奇异值分解,使用包含矩阵能量的秩来近似和还原原始矩阵,这样就可以将平方复杂度转换为线性复杂度了。本人读研期间做了很长时间的概率矩阵分解,对此有所理解。核心代码如下所示:

                
                   # 步骤1:导入peft库中Lora相关模块 
                  
from peft import (
    LoraConfig,
    PeftModel,
    get_peft_model,
    get_peft_model_state_dict,
    prepare_model_for_int8_training,
    prepare_model_for_kbit_training,
    set_peft_model_state_dict,
)

# 步骤2:lora配置
lora_config = LoraConfig(   # lora配置
        r = model_args.lora_r,   # r表示秩
        lora_alpha = model_args.lora_alpha,   # alpha表示缩放因子
         # target_modules = ["query_key_value"], # 目标模块
         # target_modules =  ['q_proj', 'k_proj', 'v_proj', 'o_proj'], # 目标模块
        target_modules = model_args.target_modules,   # 目标模块
        fan_in_fan_out = False,   # 是否使用fan_in_fan_out
        lora_dropout = 0.05,   # lora_dropout
        inference_mode = False,   # 是否使用推理模式
        bias =  "none" ,   # 偏置
        task_type =  "CAUSAL_LM" ,   # 任务类型
    )

# 步骤3:加载model
model = AutoModelForCausalLM.from_pretrained(  # 从预训练模型中加载模型
    model_args.model_name_or_path,  # 模型名或路径
    from_tf = bool( ".ckpt"   in  model_args.model_name_or_path),  # 是否从tensorflow加载
    config = config,  # 配置
    cache_dir = model_args.cache_dir,  # 缓存目录
    revision = model_args.model_revision,  # 模型版本
    use_auth_token = True  if  model_args.use_auth_token  else  None,  # 是否使用token
    torch_dtype = torch_dtype,  # torch数据类型
    device_map = { "" : int(os.environ.get( "LOCAL_RANK" ) or 0)}  # 设备映射
)

# 步骤4:获取peft模型
model = get_peft_model(model, lora_config)

# 步骤5:初始化Trainer
trainer = Trainer(  # 训练器
    model = model,  # 模型
    args = training_args,  # 训练参数
    train_dataset = train_dataset  if  training_args.do_train  else  None,  # 训练数据集
    eval_dataset = eval_dataset  if  training_args.do_eval  else  None,  # 评估数据集
    tokenizer = tokenizer,  # tokenizer
     # 数据收集器将默认为DataCollatorWithPadding,因此我们将其更改
    data_collator = transformers.DataCollatorForSeq2Seq(  # 数据收集器
        tokenizer, pad_to_multiple_of=8, return_tensors= "pt" , padding=True  # tokenizer,填充到8的倍数,返回张量,填充
    ),
    compute_metrics=compute_metrics  if  training_args.do_eval and not is_torch_tpu_available()  else  None,  # 计算指标
    preprocess_logits_for_metrics=preprocess_logits_for_metrics  if  training_args.do_eval and not is_torch_tpu_available()  else  None,  # 为指标预处理logits
    callbacks=([SavePeftModelCallback]  if  isinstance(model, PeftModel)  else  None),  # 回调
)

3.加载LoRA微调模型   加载LoRA微调模型需要通过PEFT加载预训练模型参数和微调模型参数,base_model_name_or_path为预训练模型参数保存路径,finetune_model_path为微调模型参数保存路径。核心代码如下所示:

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

# 例如: finetune_model_path='Llama2-Chinese-7b-LoRA'
finetune_model_path= ''   #微调模型参数保存路径

# 例如: base_model_name_or_path='meta-llama/Llama-2-7b'
base_model_name_or_path= ''   #为预训练模型参数保存路径

tokenizer = AutoTokenizer.from_pretrained(base_model_name_or_path,use_fast=False)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(base_model_name_or_path,device_map= 'auto' ,torch_dtype=torch.float16,load_in_8bit=True)

model = PeftModel.from_pretrained(model, finetune_model_path, device_map={ "" : 0})
model = model.eval()
input_ids = tokenizer([ '<s>Human: 介绍一下北京\n</s><s>Assistant: ' ], return_tensors= "pt" ,add_special_tokens=False).input_ids.to( 'cuda' )
generate_input = {
     "input_ids" :input_ids,
     "max_new_tokens" :512,
     "do_sample" :True,
     "top_k" :50,
     "top_p" :0.95,
     "temperature" :0.3,
     "repetition_penalty" :1.3,
     "eos_token_id" :tokenizer.eos_token_id,
     "bos_token_id" :tokenizer.bos_token_id,
     "pad_token_id" :tokenizer.pad_token_id
}
generate_ids = model.generate(**generate_input)
text = tokenizer.decode(generate_ids[0])
print (text)

4.模型量化和加载方式   模型量化和LoRA微调具体实现代码 train/sft/finetune_clm_lora.py 参考文献[3]。修改 ModelArguments 类中的 load_in_bits: Optional[int] = field(default=4) 。本质上就是先对模型做量化,然后再LoRA微调。核心代码如下所示:

                
                   # 步骤1:导入peft库中Lora相关模块 
                  
from peft import (
    LoraConfig,
    PeftModel,
    get_peft_model,
    get_peft_model_state_dict,
    prepare_model_for_int8_training,
    prepare_model_for_kbit_training,
    set_peft_model_state_dict,
)

# 步骤2:导入transformers库中量化相关模块
from transformers import (
    BitsAndBytesConfig,
)

# 步骤3:lora配置
lora_config = LoraConfig(   # lora配置
        r = model_args.lora_r,   # r表示秩
        lora_alpha = model_args.lora_alpha,   # alpha表示缩放因子
         # target_modules = ["query_key_value"], # 目标模块
         # target_modules =  ['q_proj', 'k_proj', 'v_proj', 'o_proj'], # 目标模块
        target_modules = model_args.target_modules,   # 目标模块
        fan_in_fan_out = False,   # 是否使用fan_in_fan_out
        lora_dropout = 0.05,   # lora_dropout
        inference_mode = False,   # 是否使用推理模式
        bias =  "none" ,   # 偏置
        task_type =  "CAUSAL_LM" ,   # 任务类型
    )

# 步骤4:bnb配置
bnb_config = BitsAndBytesConfig(   # bnb配置
        load_in_4bit=True,   # 是否使用4bit
        bnb_4bit_use_double_quant=True,   # 是否使用双量化
        bnb_4bit_quant_type= "nf4" ,   # 量化类型
        bnb_4bit_compute_dtype=torch.bfloat16   # 计算类型
    )

# 步骤5:加载model
model = AutoModelForCausalLM.from_pretrained(  # 从预训练模型中加载模型
    model_args.model_name_or_path,  # 模型名或路径
    from_tf = bool( ".ckpt"   in  model_args.model_name_or_path),  # 是否从tensorflow加载
    config = config,  # 配置
    cache_dir = model_args.cache_dir,  # 缓存目录
    revision = model_args.model_revision,  # 模型版本
    use_auth_token = True  if  model_args.use_auth_token  else  None,  # 是否使用token
    torch_dtype = torch_dtype,  # torch数据类型
    load_in_8bit = True  if  model_args.load_in_bits == 8  else  False,  # 是否使用8bit
    quantization_config = bnb_config  if  model_args.load_in_bits == 4  else  None,  # 量化配置
    device_map = { "" : int(os.environ.get( "LOCAL_RANK" ) or 0)}  # 设备映射
)

# 步骤6:准备模型进行kbit训练
model = prepare_model_for_kbit_training(model) 

# 步骤7:获取peft模型
model = get_peft_model(model, lora_config)

# 步骤8:初始化Trainer
trainer = Trainer(  # 训练器
    model = model,  # 模型
    args = training_args,  # 训练参数
    train_dataset = train_dataset  if  training_args.do_train  else  None,  # 训练数据集
    eval_dataset = eval_dataset  if  training_args.do_eval  else  None,  # 评估数据集
    tokenizer = tokenizer,  # tokenizer
     # 数据收集器将默认为DataCollatorWithPadding,因此我们将其更改
    data_collator = transformers.DataCollatorForSeq2Seq(  # 数据收集器
        tokenizer, pad_to_multiple_of=8, return_tensors= "pt" , padding=True  # tokenizer,填充到8的倍数,返回张量,填充
    ),
    compute_metrics=compute_metrics  if  training_args.do_eval and not is_torch_tpu_available()  else  None,  # 计算指标
    preprocess_logits_for_metrics=preprocess_logits_for_metrics  if  training_args.do_eval and not is_torch_tpu_available()  else  None,  # 为指标预处理logits
    callbacks=([SavePeftModelCallback]  if  isinstance(model, PeftModel)  else  None),  # 回调
)

  虽然LoRA微调和模型量化代码走通了,但是里面涉及到很多细节知识点需要深挖,比如LoRA具体代码实现[4][5][6],peft库支持微调方法( LoRA|Prefix Tuning|P-Tuning v1|P-Tuning v2|Prompt Tuning|AdaLoRA|LLaMA-Adapter|IA3 )和模型( Causal Language Modeling|Conditional Generation|Sequence Classification|Token Classification|Text-to-Image Generation|Image Classification|Image to text (Multi-modal models)|Semantic Segmentation )的具体代码实现[4][5],模型量化(混合精度训练、4bit、8bit、fp16、fp32、bf16、AutoGPTQ库和bitsandbytes库)等。不管怎样先实践起来,更高一层的实践才能够理解低一层的理论.

参考文献: [1]llama2 hf:https://huggingface.co/blog/llama2 [2]全参数微调时,报没有target_modules变量:https://github.com/FlagAlpha/Llama2-Chinese/issues/169 [3]finetune_clm_lora.py:https://github.com/ai408/nlp-engineering/blob/main/20230916_Llama2-Chinese/train/sft/finetune_clm_lora.py [4]peft github:https://github.com/huggingface/peft [5]peft hf:https://huggingface.co/docs/peft [6]LoRA论文:https://arxiv.org/pdf/2106.09685.pdf 。

最后此篇关于Llama2-Chinese项目:3.2-LoRA微调和模型量化的文章就讲到这里了,如果你想了解更多关于Llama2-Chinese项目:3.2-LoRA微调和模型量化的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

73 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com