做游戏网站思想步骤,手机免费图片制作软件,建设旅游网网站软件,电子商务网站软件建设#xff08;T4 16G#xff09;模型预训练colab脚本在github主页面。详见Finetuning_LLama_2_0_on_Colab_with_1_GPU.ipynb
在上一篇博客提到两种改进预训练模型性能的方法Retrieval-Augmented Generation (RAG) 或者 finetuning。本篇博客过一下模型微调。
微调#xff1a…T4 16G模型预训练colab脚本在github主页面。详见Finetuning_LLama_2_0_on_Colab_with_1_GPU.ipynb
在上一篇博客提到两种改进预训练模型性能的方法Retrieval-Augmented Generation (RAG) 或者 finetuning。本篇博客过一下模型微调。
微调这是采用预训练的LLM并在较小的特定数据集上进一步训练它以适应特定任务或提高其性能的过程。通过微调我们根据我们的数据调整模型的权重使其更适合我们应用程序的独特需求。
从Hugging face的开源大模型排行榜open_llm_leaderboard可以看到Llama 2是一个高性能base model并且其授权许可宽松可用于商业用途的大语言模型因而本篇以Llma-2的模型微调为例。
Llama-2 预训练
从零开始训练一个类似LlaMA 2的预训练模型需要庞大的数据和算力预计的所有花费在一亿美金左右这是很多公司和个人不具备这一经济条件因而更容易些的做法是在开源预训练模型的基础上进行微调这大大降低了数据集和算力的需求作为个人也是可以实现的。
模型预训练colab脚本在github主页面。详见Finetuning_LLama_2_0_on_Colab_with_1_GPU.ipynb
模型量化
为了模型推理速度更快对模型进行量化是个不错的选择而在微调的过程中感知量化微调可以提升量化模型的性能本小节先介绍模型的量化下一小节介绍LlaMA-2的感知量化。
内存和磁盘需求
由于磁盘上的模型是完全加载到内存中再运行的因而内存所需的空间和磁盘空间大小事一样的。
Model模型原始大小4比特量化大小7B13GB3.9GB13B24GB7.8GB30B60GB19.5GB65B120GB38.5GB
模型量化借助于github 上Llama2.cpp工程。可以实现模型的量化和高效的推理llama2.cpp官方特性介绍如下
Plain C/C implementation without dependenciesApple silicon first-class citizen - optimized via ARM NEON, Accelerate and Metal frameworksAVX, AVX2 and AVX512 support for x86 architecturesMixed F16 / F32 precision2-bit, 3-bit, 4-bit, 5-bit, 6-bit and 8-bit integer quantization supportCUDA, Metal and OpenCL GPU backend support
量化的方法
量化的方法比较多命名方法遵循”q” 量化比特位变种如下基于Huggingface上TheBloke模型库列出了可行的量化方法和他们的使用例子。
q2_k:用Q4_k对attention.wv和feed_forward.w2量化其他用Q2_K量化q3_k_l:用Q5_k对attention.wv、attention.wo和feed_forward.w2量化其他用Q2_K量化q3_k_m:用Q4_k对attention.wv、attention.wo和feed_forward.w2量化其他用Q2_K量化q3_k_s:用用Q3_K量化所有张量q4_0:原始4比特方法量化q4_l:准确度介于q4_0和q5_0之间但是推理速度比q5模型快q4_k_m:使用Q6_K对attention.wv和feed_forward.w2张量的前一半量化其他使用Q4_K量化q4_k_s:使用Q4_K量化所有张量q5_0:更高准确性更高资源占用率更慢的推理速度q5_1:相比q5_0可能有更高准确性更高资源占用率以及更慢的推理速度q5_k_m:使用Q6_K对attention.wv和feed_forward.w2张量的前一半量化其他使用Q5_K量化q5_k_s:使用Q5_K量化所有张量q6_k_s:使用Q8_K量化所有张量q8_0:几乎和半精度浮点float16一样资源占用率和速度都很慢对大多数用户是不推荐的 上述的wv、wo的意义如下关于Llama-2模型的推导可以大语言模型之四-LlaMA-2从模型到应用 从众多的经验上看Q5_K_M是模型表现和资源占用平衡不错的模型如果可以进一步牺牲性能以减少资源的消耗可以考虑Q4_K_M。总的来说K_M版本的量化比K_S版本的性能要好一些。Q2_K和Q3_*的量化版本由于牺牲的性能比较多所以一半并不推荐。
ModelMeasureF16Q4_0Q4_1Q5_0Q5_1Q8_07Bperplexity5.90666.15656.09125.98625.94815.90707Bfile size13.0G3.5G3.9G4.3G4.7G6.7G7Bms/tok 4th12755547683727Bms/tok 8th12243455256677Bbits/weight16.04.55.05.56.08.513Bperplexity5.25435.38605.36085.28565.27065.254813Bfile size25.0G6.8G7.6G8.3G9.1G13G13Bms/tok 4th-10310514816013113Bms/tok 8th-73829810512813Bbits/weight16.04.55.05.56.08.5
困惑度-模型质量评估 Perplexity的计算基于模型对测试数据集中每个单词的预测概率将这些概率取对数并取平均值然后将结果取负指数得到Perplexity值。Perplexity值越低表示模型对测试数据集的预测能力越好。 上表中的困惑度测量是针对wikitext2测试数据集进行的上下文长度为512。每个token的时间是在MacBook M1 Pro 32GB RAM上使用4和8线程测量的。
# Variables
MODEL_ID mlabonne/EvolCodeLlama-7b
QUANTIZATION_METHODS [q4_k_m]# Constants
MODEL_NAME MODEL_ID.split(/)[-1]
GGML_VERSION gguf# Install llama.cpp
!git clone https://github.com/ggerganov/llama.cpp
!cd llama.cpp git pull make clean LLAMA_CUBLAS1 make
!pip install -r llama.cpp/requirements.txt# Download model
!git lfs install
!git clone https://huggingface.co/{MODEL_ID}# Convert to fp16
fp16 f{MODEL_NAME}/{MODEL_NAME.lower()}.{GGML_VERSION}.fp16.bin
!python llama.cpp/convert.py {MODEL_NAME} --outtype f16 --outfile {fp16}# Quantize the model for each method in the QUANTIZATION_METHODS list
for method in QUANTIZATION_METHODS:qtype f{MODEL_NAME}/{MODEL_NAME.lower()}.{GGML_VERSION}.{method}.bin!./llama.cpp/quantize {fp16} {qtype} {method}
终端输出如下
Cloning into llama.cpp...
remote: Enumerating objects: 7959, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 7959 (delta 11), reused 19 (delta 8), pack-reused 7929
Receiving objects: 100% (7959/7959), 7.71 MiB | 15.48 MiB/s, done.
Resolving deltas: 100% (5477/5477), done.
Already up to date.
I llama.cpp build info:
I UNAME_S: Linux
I UNAME_P: x86_64
I UNAME_M: x86_64
I CFLAGS: -I. -O3 -stdc11 -fPIC -DNDEBUG -Wall -Wextra -Wpedantic -Wcast-qual -Wdouble-promotion -Wshadow -Wstrict-prototypes -Wpointer-arith -Wmissing-prototypes -pthread -marchnative -mtunenative -DGGML_USE_K_QUANTS
I CXXFLAGS: -I. -I./common -O3 -stdc11 -fPIC -DNDEBUG -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function -Wno-multichar -pthread -marchnative -mtunenative -DGGML_USE_K_QUANTS
I LDFLAGS:
I CC: cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
I CXX: g (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0Git LFS initialized.
Cloning into EvolCodeLlama-7b...
remote: Enumerating objects: 35, done.
remote: Counting objects: 100% (32/32), done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 35 (delta 8), reused 0 (delta 0), pack-reused 3
Unpacking objects: 100% (35/35), 483.46 KiB | 2.78 MiB/s, done.
Gguf GGUF是为GGML推理而提出的存储模型的文件格式GGUF是为了能够快速加载、保存和阅读模型的二进制文件格式通常由Pytorch或者其他框架训练的模型需要导出为GGUF格式后再由GGML推理使用GGUF是GGML、GGMF以及GGJT的后继者。
enum ggml_type {GGML_TYPE_F32 0,GGML_TYPE_F16 1,GGML_TYPE_Q4_0 2,GGML_TYPE_Q4_1 3,// GGML_TYPE_Q4_2 4, support has been removed// GGML_TYPE_Q4_3 (5) support has been removedGGML_TYPE_Q5_0 6,GGML_TYPE_Q5_1 7,GGML_TYPE_Q8_0 8,GGML_TYPE_Q8_1 9,// k-quantizationsGGML_TYPE_Q2_K 10,GGML_TYPE_Q3_K 11,GGML_TYPE_Q4_K 12,GGML_TYPE_Q5_K 13,GGML_TYPE_Q6_K 14,GGML_TYPE_Q8_K 15,GGML_TYPE_I8,GGML_TYPE_I16,GGML_TYPE_I32,GGML_TYPE_COUNT,
};GGUF的具体细节参见https://github.com/philpax/ggml/blob/gguf-spec/docs/gguf.md
模型训练流程
安装环境—加载预训练模型—微调模型—保存模型 当然也可以直接使用huggingface开发的模型微调库TRL这会更简洁。
安装环境
!pip install huggingface_hub
!pip install transformers4.31.0
!pip install accelerate0.21.0 peft0.4.0 bitsandbytes0.40.2 trl0.4.7
!pip install sentencepiecetransformers是大语言模型通用的架构peftParameter Efficiency Fine-Tuning) 是集成允许先进的训练技术如k-bit量化、低秩(low-rank)逼近和梯度检查点从而产生更高效和资源友好的模型。 trl是Hugging face提供的强化学习库本文只是指令微调模型并不涉及Reward model和RLHF训练部分。 bitsandbytes是对CUDA自定义函数的轻量级封装特别是针对8位优化器、矩阵乘法LLM.int8()和量化函数。
加载模型
导入预训练模型. 使用transformers库的AutoTokenizer类和 AutoModelForCausalLM 类自动下载和创建模型实例. The BitsAndBytesConfig类用于模型的量化参数设置比如4-bit是量化位数torch.bfloat16是微调时用的数据类型。
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig# Activate 4-bit precision base model loading
use_4bit True
# Compute dtype for 4-bit base models
bnb_4bit_compute_dtype float16# Quantization type (fp4 or nf4)
bnb_4bit_quant_type nf4# Load tokenizer and model with QLoRA configuration
compute_dtype getattr(torch, bnb_4bit_compute_dtype)# Activate nested quantization for 4-bit base models (double quantization)
use_nested_quant Falsebnb_config BitsAndBytesConfig(load_in_4bituse_4bit,bnb_4bit_quant_typebnb_4bit_quant_type,bnb_4bit_compute_dtypecompute_dtype,bnb_4bit_use_double_quantuse_nested_quant,
)model_name meta-llama/Llama-2-7b-chat-hf
#Load LLaMA tokenizer
tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue)
# needed for llama tokenizer
tokenizer.pad_token tokenizer.eos_token####Below is for mlabonne/guanaco-llama2-1k dataset
#tokenizer.padding_side right # Fix weird overflow issue with fp16 training#Load the entire model on the GPU 0
device_map {: 0}#Load base model
model AutoModelForCausalLM.from_pretrained(model_name,quantization_configbnb_config,device_mapdevice_map
)从peft库导入prepare_model_for_kbit_training函数并使用该函数进行k-bit量化前准备. gradient_checkpointing_enable() 函数是能了在训练阶段可以降低内存使用的梯度 checkpointing特性。
from peft import prepare_model_for_kbit_training
model.gradient_checkpointing_enable()
model prepare_model_for_kbit_training(model)可训练参数
print_trainable_parameters函数用于打印模型可训练参数. 从peft库导入 LoraConfig 和 get_peft_model函数。LoraConfig用于配置缩减训练参数的LORA (Low Rank Approximation)方法。get_peft_model将LORA方法应用于模型. 打印的是模型可训练参数的情况。
从终端输出可以看到使用LORA方法后约11%的参数才会被微调时更新 这大大降低了内存不同的LORA参数会需要不同的内存下图中的两种配置分别对应了训练的时候需要内存情况。 不同的LORA参数设置可训练的参数量会有所差异。
def print_trainable_parameters(model):Prints the number of trainable parameters in the model.trainable_params 0all_param 0for _, param in model.named_parameters():all_param param.numel()if param.requires_grad:trainable_params param.numel()print(ftrainable params: {trainable_params} || all params: {all_param} || trainable%: {100 * trainable_params / all_param})from peft import LoraConfig, get_peft_model# LoRA attention dimension 64 8
lora_r 8# Alpha parameter for LoRA scaling 16,32
lora_alpha 32# Dropout probability for LoRA layers 0.1 0.05
lora_dropout 0.1peft_config LoraConfig(rlora_r,lora_alphalora_alpha,target_modules[q_proj,v_proj],lora_dropoutlora_dropout,biasnone,task_typeCAUSAL_LM
)model get_peft_model(model, peft_config)
print_trainable_parameters(model)该函数输出的一个示例是
trainable params: 32768 || all params: 139493376 || trainable%: 0.02349072116513977
trainable params: 65536 || all params: 139526144 || trainable%: 0.04697040864255519
trainable params: 98304 || all params: 156336128 || trainable%: 0.06287989939216097
trainable params: 131072 || all params: 156368896 || trainable%: 0.08382229673093043
trainable params: 163840 || all params: 240820224 || trainable%: 0.06803415314487873
trainable params: 196608 || all params: 240852992 || trainable%: 0.08162987653481174
trainable params: 229376 || all params: 257662976 || trainable%: 0.08902171493975138
trainable params: 262144 || all params: 257695744 || trainable%: 0.10172616587722923
trainable params: 294912 || all params: 342147072 || trainable%: 0.086194512282718
trainable params: 327680 || all params: 342179840 || trainable%: 0.09576250897773522
trainable params: 360448 || all params: 358989824 || trainable%: 0.10040618867235634
trainable params: 393216 || all params: 359022592 || trainable%: 0.10952402683338658
trainable params: 425984 || all params: 443473920 || trainable%: 0.09605615590652997
trainable params: 458752 || all params: 443506688 || trainable%: 0.10343744805038882
trainable params: 491520 || all params: 460316672 || trainable%: 0.1067786656226086
trainable params: 524288 || all params: 460349440 || trainable%: 0.11388913604413203
trainable params: 557056 || all params: 544800768 || trainable%: 0.10224948875255624
trainable params: 589824 || all params: 544833536 || trainable%: 0.10825765321465088
trainable params: 622592 || all params: 561643520 || trainable%: 0.11085180863477247
trainable params: 655360 || all params: 561676288 || trainable%: 0.11667930692491686
trainable params: 688128 || all params: 646127616 || trainable%: 0.10650032330455289
trainable params: 720896 || all params: 646160384 || trainable%: 0.11156610925871926
trainable params: 753664 || all params: 662970368 || trainable%: 0.11367989225123257
trainable params: 786432 || all params: 663003136 || trainable%: 0.11861663351167015
trainable params: 819200 || all params: 747454464 || trainable%: 0.10959864974463515
trainable params: 851968 || all params: 747487232 || trainable%: 0.11397759901803915
trainable params: 884736 || all params: 764297216 || trainable%: 0.11575810842676156
trainable params: 917504 || all params: 764329984 || trainable%: 0.1200402992433174
trainable params: 950272 || all params: 848781312 || trainable%: 0.11195722461900763
trainable params: 983040 || all params: 848814080 || trainable%: 0.11581334748829802
...加载训练数据集 from datasets import load_dataset
dataset load_dataset(Abirate/english_quotes)
dataset dataset.map(lambda samples: tokenizer(samples[quote]), batchedTrue)Downloading readme: 0%| | 0.00/5.55k [00:00?, ?B/s] Downloading data files: 0%| | 0/1 [00:00?, ?it/s] Downloading data: 0%| | 0.00/647k [00:00?, ?B/s] Extracting data files: 0%| | 0/1 [00:00?, ?it/s] Generating train split: 0 examples [00:00, ? examples/s] Map: 0%| | 0/2508 [00:00?, ? examples/s] 从Huggingface的datasets库导入load_dataset函数 用其加载Abirate/english_quotes数据集中的“quotes”字段然后使用LLaMA tokenizer对其tokenize化。
定义训练参数并训练模型
可以使用tranformers和trl库两种方式实现微调TRL是huggingface开发的模型微调库旨在简化和简化语言模型的微调过程凭借其直观的接口和广泛的功能TRL使研究人员和从业者能够轻松高效地微调大型语言模型如LLaMA-v2-7B。
通过利用TRL我们可以释放语言模型化的全部潜力。它为各种NLP任务提供了一套全面的工具和技术包括文本分类、命名实体识别、情感分析等等。有了TRL能够根据特定需求微调LLaMA-v2-7B定制模型的功能。 这里使用了transformers库中的Trainer类使用模型, 训练数据集, 以及训练参数对Trainer实例化训练数据集设置了训练时的各种参数比如 batch size, learning rate, and 优化算法 (paged_adamw_8bit)。 DataCollatorForLanguageModeling 用于整理和批处理batch标记化数据。 最终调用trainer.train()方法开启微调训练。在后文又给了基于trl库的更简单的接口。
import transformers################################################################################
# TrainingArguments parameters
################################################################################# Output directory where the model predictions and checkpoints will be stored
output_dir ./results# Number of training epochs
num_train_epochs 1# Enable fp16/bf16 training (set bf16 to True with an A100)
fp16 False
bf16 False# Batch size per GPU for training
per_device_train_batch_size 4# Batch size per GPU for evaluation
per_device_eval_batch_size 4# Number of update steps to accumulate the gradients for
gradient_accumulation_steps 1# Enable gradient checkpointing
gradient_checkpointing True# Maximum gradient normal (gradient clipping)
max_grad_norm 0.3# Initial learning rate (AdamW optimizer)
learning_rate 2e-4# Weight decay to apply to all layers except bias/LayerNorm weights
weight_decay 0.001# Optimizer to use, paged_adamw_8bit paged_adamw_32bit etc...
optim paged_adamw_8bit# Learning rate schedule
lr_scheduler_type cosine# Number of training steps (overrides num_train_epochs)
max_steps -1# Ratio of steps for a linear warmup (from 0 to learning rate)
warmup_ratio 0.03# Group sequences into batches with same length
# Saves memory and speeds up training considerably
group_by_length True# Save checkpoint every X updates steps
save_steps 0# Log every X updates steps
logging_steps 25# Fine-tuned model name
new_model llama-2-7b-shichaog# Set training parameters
training_arguments transformers.TrainingArguments(output_diroutput_dir,num_train_epochsnum_train_epochs,per_device_train_batch_sizeper_device_train_batch_size,gradient_accumulation_stepsgradient_accumulation_steps,optimoptim,save_stepssave_steps,logging_stepslogging_steps,learning_ratelearning_rate,weight_decayweight_decay,fp16fp16,bf16bf16,max_grad_normmax_grad_norm,max_stepsmax_steps,warmup_ratiowarmup_ratio,group_by_lengthgroup_by_length,lr_scheduler_typelr_scheduler_type,report_totensorboard
)## needed for llama tokenizer
tokenizer.pad_token tokenizer.eos_token
trainer transformers.Trainer(modelmodel,train_datasetdataset[train],# argstransformers.TrainingArguments(# per_device_train_batch_size1,# gradient_accumulation_steps4,# warmup_steps2,# max_steps10,# learning_rate2e-4,# fp16True,# logging_steps1,# output_diroutputs,# optimpaged_adamw_8bit# ),argstraining_arguments,data_collatortransformers.DataCollatorForLanguageModeling(tokenizer, mlmFalse),
)model.config.use_cache False # silence the warnings. Please re-enable for inference!
trainer.train()
trainer.model.save_pretrained(new_model)图右侧显示了GPU内存使用情况 可以使用trl库接口实现上面的功能这会比上面更简单一些作用上是一致的。
################################################################################
# SFT parameters
################################################################################
from trl import SFTTrainer
# Maximum sequence length to use
max_seq_length None# Pack multiple short examples in the same input sequence to increase efficiency
packing False# Load the entire model on the GPU 0
device_map {: 0}# Set supervised fine-tuning parameters from trl library
trainer2 SFTTrainer(modelmodel,train_datasetdataset[train],peft_configpeft_config,dataset_text_fieldquote,max_seq_lengthmax_seq_length,tokenizertokenizer,argstraining_arguments,packingpacking,
)# Train model
trainer2.train()# Save trained model
trainer2.model.save_pretrained(new_model)这段代码和上一段使用transformers库的Trainer是一样的意义和作用这里的SFTTrainer是对上面Trainer的封装参数的意义都是一样的。因为trl库支持了PPO之类的RLHF所以把SFT也支持了会使trl库更完备一些。