searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

继Chinese LLaMA2预训练和指令精调实战后续的一些实践

2023-09-14 06:29:38
165
0

Tensorboard指定输出位置

report_to "tensorboard" \
logging_steps 500 \
logging_dir ${logging_dir }
#参数解释:
report_to="tensorboard": 将所有训练和验证的数据报告给 tensorboard
logging_steps:每隔多少步打印一次train loss,结果会打印到日志中,也会保存在tensorboard中
logging_dir: 指定快照输出位置

基于开发机镜像执行llama

docker run -it -u root --name Chinesellama2 -v ~/llama:/root/llama  --gpus all fb79aa125061 /bin/bash
pip uninstall bitsandbytes
pip install scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

# 当时的尝试步骤:
# 1安装scikit-learn
# 2 卸载掉bitsandbytes
# 3测试
>>> import torch
>>> print(torch.cuda.is_available())
False
# 加入GPU参数--gpus all 创建docker容器
# 重复123,欧克

镜像上传到harbor,为后续在k8s上执行打基础

docker images
docker tag image_name:v_version harbor_address:port/project_name/new_image_name:new_v_version
docker login harbor_address:port
docker push harbor_address:port/project_name/new_image_name:new_v_version

因为上传到harbor很慢,所以用tmux终端多路复用程序,快速切换界面,以下为主要用到的操作

连接到会话
tmux attach -t 19
tmux attach -t <session_name>
列出所有会话
tmux list-sessions

ctrl+b w列出所有列表
ctrl+b kill-session 将当前会话结束(kill)
ctrl+b d退出当前会话(detach)

llama2的ptuning实现实战

# 参考 github.com/liguodongiot/llm-action/blob/main/train/peft/clm/peft_p_tuning_clm.ipynb 实现ptuning
# 基于github.com/ymcui/Chinese-LLaMA-Alpaca-2/blob/main/scripts/training/run_clm_sft_with_peft.py修改代码
# 首先去掉Lora部分代码,添加实现ptuning的peft相关库
from peft import (
    get_peft_config,
    TaskType,
    get_peft_model,
    PeftModel,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    PromptEncoderConfig,
)
#  然后创建peft配置,即创建ptuning微调方法的相关配置
 peft_config = PromptEncoderConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=20, encoder_hidden_size=128)

 

训练脚本run_sft_test_ptuning.sh

 

lr=1e-4

pretrained_model=/root/llama/correspond_output_dir
chinese_tokenizer_path=/root/llama/correspond_output_dir
dataset_dir=data_pt
per_device_train_batch_size=1
per_device_eval_batch_size=1
gradient_accumulation_steps=8
max_seq_length=512
output_dir=test
validation_file=data_pt/alpaca_data.json
training_steps=1000

deepspeed_config_file=scripts/training/ds_zero2_no_offload.json

torchrun --nnodes 1 --nproc_per_node 7 scripts/training/run_clm_sft_with_ptuning.py \
    --deepspeed ${deepspeed_config_file} \
    --model_name_or_path ${pretrained_model} \
    --tokenizer_name_or_path ${chinese_tokenizer_path} \
    --dataset_dir ${dataset_dir} \
    --per_device_train_batch_size ${per_device_train_batch_size} \
    --per_device_eval_batch_size ${per_device_eval_batch_size} \
    --do_train \
    --do_eval  \
    --eval_steps 1000 \
    --seed $RANDOM \
    --fp16 \
    --num_train_epochs 1 \
    --lr_scheduler_type cosine \
    --learning_rate ${lr} \
    --warmup_ratio 0.03 \
    --weight_decay 0 \
    --logging_strategy steps \
    --logging_steps 10 \
    --save_strategy steps \
    --save_total_limit 3 \
    --evaluation_strategy steps \
    --eval_steps 1000 \
    --save_steps 1000 \
    --gradient_accumulation_steps ${gradient_accumulation_steps} \
    --preprocessing_num_workers 8 \
    --max_steps ${training_steps} \
    --max_seq_length ${max_seq_length} \
    --output_dir ${output_dir} \
    --overwrite_output_dir \
    --ddp_timeout 30000 \
    --logging_first_step True \
    --torch_dtype float16 \
    --validation_file ${validation_file}

 

llama2的ptuning v2实现实战

# 参考 github.com/liguodongiot/llm-action/blob/main/train/peft/clm/peft_p_tuning_clm.ipynb 实现ptuning
# 基于github.com/ymcui/Chinese-LLaMA-Alpaca-2/blob/main/scripts/training/run_clm_sft_with_peft.py修改代码
# 首先去掉Lora部分代码,添加实现ptuning v2的peft相关库
from peft import (
    get_peft_config,
    TaskType,
    get_peft_model,
    PeftModel,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    PrefixTuningConfig,
)
#  然后创建peft配置,即创建ptuning微调方法的相关配置
peft_config = PrefixTuningConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=300)

 

trainable params: 78643200 || all params: 7007899648 || trainable%: 1.122207850428397

 

精华部分(踩坑部分)

    if training_args.gradient_checkpointing and \
        (not model.modules_to_save or 'embed_tokens' not in model.modules_to_save):
        # enable requires_grad to avoid exception during backward pass when using gradient_checkpoint without tuning embed.
        if hasattr(model.base_model, "enable_input_require_grads"):
            model.base_model.enable_input_require_grads()
        elif hasattr(model.base_model, "get_input_embeddings"):
            def make_inputs_require_grad(_module, _input, _output):
                _output.requires_grad_(True)
            model.base_model.get_input_embeddings().register_forward_hook(make_inputs_require_grad)

 

这段代码主要是在处理模型训练中的梯度检查点问题。梯度检查点是一种内存优化技术,可以在训练深度神经网络时减少GPU内存的使用,但可能会增加一些计算开销。

  • if training_args.gradient_checkpointing and (not model.modules_to_save or 'embed_tokens' not in model.modules_to_save): 这行代码首先检查是否开启了梯度检查点(gradient_checkpointing),并且模型没有需要保存的模块(modules_to_save)或者'embed_tokens'不在需要保存的模块中。如果这两个条件都满足,那么就会执行下面的代码。

  • if hasattr(model.base_model, "enable_input_require_grads"): 这行代码检查基础模型(base_model)是否有一个名为enable_input_require_grads的方法。如果有,那么就调用这个方法,使得输入向量可以计算梯度。

  • elif hasattr(model.base_model, "get_input_embeddings"): 这行代码在上一个条件不满足的情况下执行。它检查基础模型是否有一个名为get_input_embeddings的方法。如果有,那么就注册一个前向钩子(forward_hook)到输入嵌入向量上。这个钩子会在每次前向传播时被调用,并使得输出向量可以计算梯度。

总的来说,这段代码的目的是在使用梯度检查点时确保输入向量可以计算梯度,以避免在反向传播过程中出现异常。这是因为当使用梯度检查点时,PyTorch会在前向传播过程中释放一些中间结果以节省内存,然后在反向传播过程中重新计算这些结果。如果输入向量不能计算梯度,那么在反向传播过程中就可能出现问题。

llama2的全量微调实现实战

参考github.com/FlagAlpha/Llama2-Chinese/blob/main/train/sft/finetune.sh

github.com/FlagAlpha/Llama2-Chinese/blob/main/train/sft/finetune_clm.py

output_model=./finetune_output
# 需要修改到自己的输入目录
if [ ! -d ${output_model} ];then
    mkdir ${output_model}
fi
cp ./finetune.sh ${output_model}
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 deepspeed --num_gpus 7  finetune_clm.py \
    --model_name_or_path /root/llama/correspond_output_dir \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --train_files ./finetune_data/train_sft.csv \
    --validation_files  ./finetune_data/dev_sft.csv \
                         ./finetune_data/dev_sft_sharegpt.csv \
    --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 40 \
    --logging_dir ${output_model}/logs \
    --logging_strategy steps \
    --logging_steps 10 \
    --save_strategy steps \
    --preprocessing_num_workers 10 \
    --save_steps 20 \
    --max_steps 800 \
    --eval_steps 20 \
    --save_total_limit 2000 \
    --seed 42 \
    --disable_tqdm false \
    --ddp_find_unused_parameters false \
    --block_size 2048 \
    --report_to tensorboard \
    --overwrite_output_dir \
    --deepspeed scripts/training/ds_zero2_no_offload.json \
    --ignore_data_skip true \
    --bf16 \
    --gradient_checkpointing \
    --bf16_full_eval \
    --ddp_timeout 18000000 \
    | tee -a ${output_model}/train.log



    # --resume_from_checkpoint ${output_model}/checkpoint-20400 \

 

调用

# github.com/FlagAlpha/Llama2-Chinese#%E5%85%A8%E9%87%8F%E5%8F%82%E6%95%B0%E5%BE%AE%E8%B0%83
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained('/root/llama/finetune_output/checkpoint-800',device_map='auto',torch_dtype=torch.float16)
model =model.eval()
tokenizer = AutoTokenizer.from_pretrained('/root/llama/finetune_output/checkpoint-800',use_fast=False)
tokenizer.pad_token = tokenizer.eos_token
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)

 

0条评论
0 / 1000
l****n
28文章数
5粉丝数
l****n
28 文章 | 5 粉丝
原创

继Chinese LLaMA2预训练和指令精调实战后续的一些实践

2023-09-14 06:29:38
165
0

Tensorboard指定输出位置

report_to "tensorboard" \
logging_steps 500 \
logging_dir ${logging_dir }
#参数解释:
report_to="tensorboard": 将所有训练和验证的数据报告给 tensorboard
logging_steps:每隔多少步打印一次train loss,结果会打印到日志中,也会保存在tensorboard中
logging_dir: 指定快照输出位置

基于开发机镜像执行llama

docker run -it -u root --name Chinesellama2 -v ~/llama:/root/llama  --gpus all fb79aa125061 /bin/bash
pip uninstall bitsandbytes
pip install scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

# 当时的尝试步骤:
# 1安装scikit-learn
# 2 卸载掉bitsandbytes
# 3测试
>>> import torch
>>> print(torch.cuda.is_available())
False
# 加入GPU参数--gpus all 创建docker容器
# 重复123,欧克

镜像上传到harbor,为后续在k8s上执行打基础

docker images
docker tag image_name:v_version harbor_address:port/project_name/new_image_name:new_v_version
docker login harbor_address:port
docker push harbor_address:port/project_name/new_image_name:new_v_version

因为上传到harbor很慢,所以用tmux终端多路复用程序,快速切换界面,以下为主要用到的操作

连接到会话
tmux attach -t 19
tmux attach -t <session_name>
列出所有会话
tmux list-sessions

ctrl+b w列出所有列表
ctrl+b kill-session 将当前会话结束(kill)
ctrl+b d退出当前会话(detach)

llama2的ptuning实现实战

# 参考 github.com/liguodongiot/llm-action/blob/main/train/peft/clm/peft_p_tuning_clm.ipynb 实现ptuning
# 基于github.com/ymcui/Chinese-LLaMA-Alpaca-2/blob/main/scripts/training/run_clm_sft_with_peft.py修改代码
# 首先去掉Lora部分代码,添加实现ptuning的peft相关库
from peft import (
    get_peft_config,
    TaskType,
    get_peft_model,
    PeftModel,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    PromptEncoderConfig,
)
#  然后创建peft配置,即创建ptuning微调方法的相关配置
 peft_config = PromptEncoderConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=20, encoder_hidden_size=128)

 

训练脚本run_sft_test_ptuning.sh

 

lr=1e-4

pretrained_model=/root/llama/correspond_output_dir
chinese_tokenizer_path=/root/llama/correspond_output_dir
dataset_dir=data_pt
per_device_train_batch_size=1
per_device_eval_batch_size=1
gradient_accumulation_steps=8
max_seq_length=512
output_dir=test
validation_file=data_pt/alpaca_data.json
training_steps=1000

deepspeed_config_file=scripts/training/ds_zero2_no_offload.json

torchrun --nnodes 1 --nproc_per_node 7 scripts/training/run_clm_sft_with_ptuning.py \
    --deepspeed ${deepspeed_config_file} \
    --model_name_or_path ${pretrained_model} \
    --tokenizer_name_or_path ${chinese_tokenizer_path} \
    --dataset_dir ${dataset_dir} \
    --per_device_train_batch_size ${per_device_train_batch_size} \
    --per_device_eval_batch_size ${per_device_eval_batch_size} \
    --do_train \
    --do_eval  \
    --eval_steps 1000 \
    --seed $RANDOM \
    --fp16 \
    --num_train_epochs 1 \
    --lr_scheduler_type cosine \
    --learning_rate ${lr} \
    --warmup_ratio 0.03 \
    --weight_decay 0 \
    --logging_strategy steps \
    --logging_steps 10 \
    --save_strategy steps \
    --save_total_limit 3 \
    --evaluation_strategy steps \
    --eval_steps 1000 \
    --save_steps 1000 \
    --gradient_accumulation_steps ${gradient_accumulation_steps} \
    --preprocessing_num_workers 8 \
    --max_steps ${training_steps} \
    --max_seq_length ${max_seq_length} \
    --output_dir ${output_dir} \
    --overwrite_output_dir \
    --ddp_timeout 30000 \
    --logging_first_step True \
    --torch_dtype float16 \
    --validation_file ${validation_file}

 

llama2的ptuning v2实现实战

# 参考 github.com/liguodongiot/llm-action/blob/main/train/peft/clm/peft_p_tuning_clm.ipynb 实现ptuning
# 基于github.com/ymcui/Chinese-LLaMA-Alpaca-2/blob/main/scripts/training/run_clm_sft_with_peft.py修改代码
# 首先去掉Lora部分代码,添加实现ptuning v2的peft相关库
from peft import (
    get_peft_config,
    TaskType,
    get_peft_model,
    PeftModel,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    PrefixTuningConfig,
)
#  然后创建peft配置,即创建ptuning微调方法的相关配置
peft_config = PrefixTuningConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=300)

 

trainable params: 78643200 || all params: 7007899648 || trainable%: 1.122207850428397

 

精华部分(踩坑部分)

    if training_args.gradient_checkpointing and \
        (not model.modules_to_save or 'embed_tokens' not in model.modules_to_save):
        # enable requires_grad to avoid exception during backward pass when using gradient_checkpoint without tuning embed.
        if hasattr(model.base_model, "enable_input_require_grads"):
            model.base_model.enable_input_require_grads()
        elif hasattr(model.base_model, "get_input_embeddings"):
            def make_inputs_require_grad(_module, _input, _output):
                _output.requires_grad_(True)
            model.base_model.get_input_embeddings().register_forward_hook(make_inputs_require_grad)

 

这段代码主要是在处理模型训练中的梯度检查点问题。梯度检查点是一种内存优化技术,可以在训练深度神经网络时减少GPU内存的使用,但可能会增加一些计算开销。

  • if training_args.gradient_checkpointing and (not model.modules_to_save or 'embed_tokens' not in model.modules_to_save): 这行代码首先检查是否开启了梯度检查点(gradient_checkpointing),并且模型没有需要保存的模块(modules_to_save)或者'embed_tokens'不在需要保存的模块中。如果这两个条件都满足,那么就会执行下面的代码。

  • if hasattr(model.base_model, "enable_input_require_grads"): 这行代码检查基础模型(base_model)是否有一个名为enable_input_require_grads的方法。如果有,那么就调用这个方法,使得输入向量可以计算梯度。

  • elif hasattr(model.base_model, "get_input_embeddings"): 这行代码在上一个条件不满足的情况下执行。它检查基础模型是否有一个名为get_input_embeddings的方法。如果有,那么就注册一个前向钩子(forward_hook)到输入嵌入向量上。这个钩子会在每次前向传播时被调用,并使得输出向量可以计算梯度。

总的来说,这段代码的目的是在使用梯度检查点时确保输入向量可以计算梯度,以避免在反向传播过程中出现异常。这是因为当使用梯度检查点时,PyTorch会在前向传播过程中释放一些中间结果以节省内存,然后在反向传播过程中重新计算这些结果。如果输入向量不能计算梯度,那么在反向传播过程中就可能出现问题。

llama2的全量微调实现实战

参考github.com/FlagAlpha/Llama2-Chinese/blob/main/train/sft/finetune.sh

github.com/FlagAlpha/Llama2-Chinese/blob/main/train/sft/finetune_clm.py

output_model=./finetune_output
# 需要修改到自己的输入目录
if [ ! -d ${output_model} ];then
    mkdir ${output_model}
fi
cp ./finetune.sh ${output_model}
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 deepspeed --num_gpus 7  finetune_clm.py \
    --model_name_or_path /root/llama/correspond_output_dir \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --train_files ./finetune_data/train_sft.csv \
    --validation_files  ./finetune_data/dev_sft.csv \
                         ./finetune_data/dev_sft_sharegpt.csv \
    --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 40 \
    --logging_dir ${output_model}/logs \
    --logging_strategy steps \
    --logging_steps 10 \
    --save_strategy steps \
    --preprocessing_num_workers 10 \
    --save_steps 20 \
    --max_steps 800 \
    --eval_steps 20 \
    --save_total_limit 2000 \
    --seed 42 \
    --disable_tqdm false \
    --ddp_find_unused_parameters false \
    --block_size 2048 \
    --report_to tensorboard \
    --overwrite_output_dir \
    --deepspeed scripts/training/ds_zero2_no_offload.json \
    --ignore_data_skip true \
    --bf16 \
    --gradient_checkpointing \
    --bf16_full_eval \
    --ddp_timeout 18000000 \
    | tee -a ${output_model}/train.log



    # --resume_from_checkpoint ${output_model}/checkpoint-20400 \

 

调用

# github.com/FlagAlpha/Llama2-Chinese#%E5%85%A8%E9%87%8F%E5%8F%82%E6%95%B0%E5%BE%AE%E8%B0%83
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained('/root/llama/finetune_output/checkpoint-800',device_map='auto',torch_dtype=torch.float16)
model =model.eval()
tokenizer = AutoTokenizer.from_pretrained('/root/llama/finetune_output/checkpoint-800',use_fast=False)
tokenizer.pad_token = tokenizer.eos_token
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)

 

文章来自个人专栏
AI-llama大模型,go语言开发
28 文章 | 2 订阅
0条评论
0 / 1000
请输入你的评论
0
0