🔗 本文所用工具:
trl
、transformers
、peft
、bitsandbytes
📘 官方文檔參考:https://huggingface.co/docs/trl
一、引言:從有監督微調到 RLHF 全流程
????????隨著語言大模型的發展,如何在大規模預訓練模型基礎上更精細地對齊人類偏好,成為了研究與應用的熱點。本文將介紹一套完整的 RLHF(Reinforcement Learning with Human Feedback)訓練流程,基于 Hugging Face 推出的 trl
庫,從 SFT(Supervised Fine-tuning)、RM(Reward Modeling)、到 PPO(Proximal Policy Optimization)三大階段,逐步實現對 Transformer 模型的強化學習優化。
????????本篇聚焦于 SFT 階段的實現,并以 Hugging Face 提供的 instruction-dataset
為例,介紹如何使用 trl
和 PEFT(參數高效微調)技術訓練一個高效對齊指令的語言模型。
二、安裝與環境準備
????????確保安裝以下庫(建議使用 PyTorch + CUDA 環境):
pip install trl transformers datasets peft bitsandbytes accelerate
三、加載并準備數據集
????????本例使用 HuggingFaceH4 團隊整理的 instruction-dataset
:
from datasets import load_datasetdataset = load_dataset("HuggingFaceH4/instruction-dataset")
dataset = dataset.remove_columns("meta") # 移除無用字段
dataset
四、構建模型及量化配置(4-bit)
????????使用 BitsAndBytesConfig
對模型進行 4-bit 量化,可大幅降低顯存占用:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import prepare_model_for_kbit_trainingmodel_name = "lmsys/fastchat-t5-3b-v1.0"bnb_config = BitsAndBytesConfig(load_in_4bit=True,bnb_4bit_quant_type="nf4",bnb_4bit_compute_dtype=torch.bfloat16,
)base_model = AutoModelForCausalLM.from_pretrained(model_name,torch_dtype=torch.bfloat16,quantization_config=bnb_config
)base_model.config.use_cache = False
base_model = prepare_model_for_kbit_training(base_model)
五、注入 LoRA 參數高效微調機制
????????首先識別所有 4-bit 線性模塊并定義 LoRA 參數配置:
import bitsandbytes as bnb
from peft import get_peft_model, LoraConfigdef find_all_linear_names(model):cls = bnb.nn.Linear4bitlora_module_names = set()for name, module in model.named_modules():if isinstance(module, cls):names = name.split(".")lora_module_names.add(names[0] if len(names) == 1 else names[-1])return list(lora_module_names)peft_config = LoraConfig(r=128,lora_alpha=16,target_modules=find_all_linear_names(base_model),lora_dropout=0.05,bias="none",task_type="CAUSAL_LM",
)base_model = get_peft_model(base_model, peft_config)
????????打印可訓練參數占比:
def print_trainable_parameters(model):trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)total = sum(p.numel() for p in model.parameters())print(f"Trainable params: {trainable} / {total} ({trainable / total:.2%})")print_trainable_parameters(base_model)
六、定義 Prompt 格式化函數
????????將數據集中的 prompt
和 completion
格式化為統一格式:
def formatting_prompts_func(example):return [f"### Input: ```{prompt}```\n ### Output: {completion}"for prompt, completion in zip(example["prompt"], example["completion"])]
七、訓練參數設置與 SFTTrainer 訓練器
????????使用 SFTTrainer
執行指令微調訓練,支持 gradient checkpointing、cosine 學習率調度等高級策略:
from transformers import TrainingArguments
from trl import SFTTraineroutput_dir = "./results"training_args = TrainingArguments(output_dir=output_dir,per_device_train_batch_size=4,gradient_accumulation_steps=4,gradient_checkpointing=True,max_grad_norm=0.3,num_train_epochs=15,learning_rate=2e-4,bf16=True,save_total_limit=3,logging_steps=10,optim="paged_adamw_32bit",lr_scheduler_type="cosine",warmup_ratio=0.05,
)tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"trainer = SFTTrainer(model=base_model,train_dataset=dataset,tokenizer=tokenizer,max_seq_length=2048,formatting_func=formatting_prompts_func,args=training_args
)
????????執行訓練:
trainer.train()
trainer.save_model(output_dir)
????????保存最終模型權重與 tokenizer:
import os
final_output_dir = os.path.join(output_dir, "final_checkpoint")
trainer.model.save_pretrained(final_output_dir)
tokenizer.save_pretrained(final_output_dir)
八、小結與展望
????????通過本文,我們使用 trl
工具鏈完成了 RLHF 的第一階段:SFT 有監督微調。你可以根據項目實際需求,替換為自定義數據集或更大規模模型。后續步驟(RM 獎勵建模 + PPO 策略優化)將在下一篇繼續介紹。
📌 下一篇預告
????????📘《基于 Python 的自然語言處理系列(83):InstructGPT》
????????敬請期待!
如果你覺得這篇博文對你有幫助,請點贊、收藏、關注我,并且可以打賞支持我!
歡迎關注我的后續博文,我將分享更多關于人工智能、自然語言處理和計算機視覺的精彩內容。
謝謝大家的支持!